00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #include "asterisk.h"
00031
00032 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 369001 $")
00033
00034 #include "asterisk/_private.h"
00035
00036 #include "asterisk/event.h"
00037 #include "asterisk/linkedlists.h"
00038 #include "asterisk/dlinkedlists.h"
00039 #include "asterisk/lock.h"
00040 #include "asterisk/utils.h"
00041 #include "asterisk/unaligned.h"
00042 #include "asterisk/utils.h"
00043 #include "asterisk/taskprocessor.h"
00044 #include "asterisk/astobj2.h"
00045 #include "asterisk/cli.h"
00046
00047 static struct ast_taskprocessor *event_dispatcher;
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057 struct ast_event_ie {
00058 enum ast_event_ie_type ie_type:16;
00059
00060 uint16_t ie_payload_len;
00061 unsigned char ie_payload[0];
00062 } __attribute__((packed));
00063
00064
00065
00066
00067 struct ast_event_ie_str_payload {
00068
00069 uint32_t hash;
00070
00071 char str[1];
00072 } __attribute__((packed));
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085 struct ast_event {
00086
00087 enum ast_event_type type:16;
00088
00089 uint16_t event_len:16;
00090
00091 unsigned char payload[0];
00092 } __attribute__((packed));
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104 struct ast_event_ref {
00105 struct ast_event *event;
00106 };
00107
00108 struct ast_event_ie_val {
00109 AST_LIST_ENTRY(ast_event_ie_val) entry;
00110 enum ast_event_ie_type ie_type;
00111 enum ast_event_ie_pltype ie_pltype;
00112 union {
00113 uint32_t uint;
00114 struct {
00115 uint32_t hash;
00116 const char *str;
00117 };
00118 void *raw;
00119 } payload;
00120 size_t raw_datalen;
00121 };
00122
00123
00124 struct ast_event_sub {
00125 enum ast_event_type type;
00126 ast_event_cb_t cb;
00127 char description[64];
00128 void *userdata;
00129 uint32_t uniqueid;
00130 AST_LIST_HEAD_NOLOCK(, ast_event_ie_val) ie_vals;
00131 AST_RWDLLIST_ENTRY(ast_event_sub) entry;
00132 };
00133
00134 static uint32_t sub_uniqueid;
00135
00136
00137
00138 static AST_RWDLLIST_HEAD(ast_event_sub_list, ast_event_sub) ast_event_subs[AST_EVENT_TOTAL];
00139
00140 static int ast_event_cmp(void *obj, void *arg, int flags);
00141 static int ast_event_hash_mwi(const void *obj, const int flags);
00142 static int ast_event_hash_devstate(const void *obj, const int flags);
00143 static int ast_event_hash_devstate_change(const void *obj, const int flags);
00144
00145 #ifdef LOW_MEMORY
00146 #define NUM_CACHE_BUCKETS 17
00147 #else
00148 #define NUM_CACHE_BUCKETS 563
00149 #endif
00150
00151 #define MAX_CACHE_ARGS 8
00152
00153
00154
00155
00156 static struct {
00157
00158
00159
00160
00161
00162
00163 struct ao2_container *container;
00164
00165 ao2_hash_fn *hash_fn;
00166
00167
00168
00169
00170
00171
00172
00173
00174 enum ast_event_ie_type cache_args[MAX_CACHE_ARGS];
00175 } ast_event_cache[AST_EVENT_TOTAL] = {
00176 [AST_EVENT_MWI] = {
00177 .hash_fn = ast_event_hash_mwi,
00178 .cache_args = { AST_EVENT_IE_MAILBOX, AST_EVENT_IE_CONTEXT },
00179 },
00180 [AST_EVENT_DEVICE_STATE] = {
00181 .hash_fn = ast_event_hash_devstate,
00182 .cache_args = { AST_EVENT_IE_DEVICE, },
00183 },
00184 [AST_EVENT_DEVICE_STATE_CHANGE] = {
00185 .hash_fn = ast_event_hash_devstate_change,
00186 .cache_args = { AST_EVENT_IE_DEVICE, AST_EVENT_IE_EID, },
00187 },
00188 };
00189
00190
00191
00192
00193
00194
00195 static const char * const cached_event_types[] = { "MWI", "DeviceState", "DeviceStateChange", NULL };
00196
00197
00198
00199
00200 static const char * const event_names[AST_EVENT_TOTAL] = {
00201 [AST_EVENT_ALL] = "All",
00202 [AST_EVENT_CUSTOM] = "Custom",
00203 [AST_EVENT_MWI] = "MWI",
00204 [AST_EVENT_SUB] = "Subscription",
00205 [AST_EVENT_UNSUB] = "Unsubscription",
00206 [AST_EVENT_DEVICE_STATE] = "DeviceState",
00207 [AST_EVENT_DEVICE_STATE_CHANGE] = "DeviceStateChange",
00208 [AST_EVENT_CEL] = "CEL",
00209 [AST_EVENT_SECURITY] = "Security",
00210 [AST_EVENT_NETWORK_CHANGE] = "NetworkChange",
00211 };
00212
00213
00214
00215
00216 static const struct ie_map {
00217 enum ast_event_ie_pltype ie_pltype;
00218 const char *name;
00219 } ie_maps[AST_EVENT_IE_TOTAL] = {
00220 [AST_EVENT_IE_NEWMSGS] = { AST_EVENT_IE_PLTYPE_UINT, "NewMessages" },
00221 [AST_EVENT_IE_OLDMSGS] = { AST_EVENT_IE_PLTYPE_UINT, "OldMessages" },
00222 [AST_EVENT_IE_MAILBOX] = { AST_EVENT_IE_PLTYPE_STR, "Mailbox" },
00223 [AST_EVENT_IE_UNIQUEID] = { AST_EVENT_IE_PLTYPE_UINT, "UniqueID" },
00224 [AST_EVENT_IE_EVENTTYPE] = { AST_EVENT_IE_PLTYPE_UINT, "EventType" },
00225 [AST_EVENT_IE_EXISTS] = { AST_EVENT_IE_PLTYPE_UINT, "Exists" },
00226 [AST_EVENT_IE_DEVICE] = { AST_EVENT_IE_PLTYPE_STR, "Device" },
00227 [AST_EVENT_IE_STATE] = { AST_EVENT_IE_PLTYPE_UINT, "State" },
00228 [AST_EVENT_IE_CONTEXT] = { AST_EVENT_IE_PLTYPE_STR, "Context" },
00229 [AST_EVENT_IE_EID] = { AST_EVENT_IE_PLTYPE_RAW, "EntityID" },
00230 [AST_EVENT_IE_CEL_EVENT_TYPE] = { AST_EVENT_IE_PLTYPE_UINT, "CELEventType" },
00231 [AST_EVENT_IE_CEL_EVENT_TIME] = { AST_EVENT_IE_PLTYPE_UINT, "CELEventTime" },
00232 [AST_EVENT_IE_CEL_EVENT_TIME_USEC] = { AST_EVENT_IE_PLTYPE_UINT, "CELEventTimeUSec" },
00233 [AST_EVENT_IE_CEL_USEREVENT_NAME] = { AST_EVENT_IE_PLTYPE_UINT, "CELUserEventName" },
00234 [AST_EVENT_IE_CEL_CIDNAME] = { AST_EVENT_IE_PLTYPE_STR, "CELCIDName" },
00235 [AST_EVENT_IE_CEL_CIDNUM] = { AST_EVENT_IE_PLTYPE_STR, "CELCIDNum" },
00236 [AST_EVENT_IE_CEL_EXTEN] = { AST_EVENT_IE_PLTYPE_STR, "CELExten" },
00237 [AST_EVENT_IE_CEL_CONTEXT] = { AST_EVENT_IE_PLTYPE_STR, "CELContext" },
00238 [AST_EVENT_IE_CEL_CHANNAME] = { AST_EVENT_IE_PLTYPE_STR, "CELChanName" },
00239 [AST_EVENT_IE_CEL_APPNAME] = { AST_EVENT_IE_PLTYPE_STR, "CELAppName" },
00240 [AST_EVENT_IE_CEL_APPDATA] = { AST_EVENT_IE_PLTYPE_STR, "CELAppData" },
00241 [AST_EVENT_IE_CEL_AMAFLAGS] = { AST_EVENT_IE_PLTYPE_STR, "CELAMAFlags" },
00242 [AST_EVENT_IE_CEL_ACCTCODE] = { AST_EVENT_IE_PLTYPE_UINT, "CELAcctCode" },
00243 [AST_EVENT_IE_CEL_UNIQUEID] = { AST_EVENT_IE_PLTYPE_STR, "CELUniqueID" },
00244 [AST_EVENT_IE_CEL_USERFIELD] = { AST_EVENT_IE_PLTYPE_STR, "CELUserField" },
00245 [AST_EVENT_IE_CEL_CIDANI] = { AST_EVENT_IE_PLTYPE_STR, "CELCIDani" },
00246 [AST_EVENT_IE_CEL_CIDRDNIS] = { AST_EVENT_IE_PLTYPE_STR, "CELCIDrdnis" },
00247 [AST_EVENT_IE_CEL_CIDDNID] = { AST_EVENT_IE_PLTYPE_STR, "CELCIDdnid" },
00248 [AST_EVENT_IE_CEL_PEER] = { AST_EVENT_IE_PLTYPE_STR, "CELPeer" },
00249 [AST_EVENT_IE_CEL_LINKEDID] = { AST_EVENT_IE_PLTYPE_STR, "CELLinkedID" },
00250 [AST_EVENT_IE_CEL_PEERACCT] = { AST_EVENT_IE_PLTYPE_STR, "CELPeerAcct" },
00251 [AST_EVENT_IE_CEL_EXTRA] = { AST_EVENT_IE_PLTYPE_STR, "CELExtra" },
00252 [AST_EVENT_IE_SECURITY_EVENT] = { AST_EVENT_IE_PLTYPE_STR, "SecurityEvent" },
00253 [AST_EVENT_IE_EVENT_VERSION] = { AST_EVENT_IE_PLTYPE_UINT, "EventVersion" },
00254 [AST_EVENT_IE_SERVICE] = { AST_EVENT_IE_PLTYPE_STR, "Service" },
00255 [AST_EVENT_IE_MODULE] = { AST_EVENT_IE_PLTYPE_STR, "Module" },
00256 [AST_EVENT_IE_ACCOUNT_ID] = { AST_EVENT_IE_PLTYPE_STR, "AccountID" },
00257 [AST_EVENT_IE_SESSION_ID] = { AST_EVENT_IE_PLTYPE_STR, "SessionID" },
00258 [AST_EVENT_IE_SESSION_TV] = { AST_EVENT_IE_PLTYPE_STR, "SessionTV" },
00259 [AST_EVENT_IE_ACL_NAME] = { AST_EVENT_IE_PLTYPE_STR, "ACLName" },
00260 [AST_EVENT_IE_LOCAL_ADDR] = { AST_EVENT_IE_PLTYPE_STR, "LocalAddress" },
00261 [AST_EVENT_IE_REMOTE_ADDR] = { AST_EVENT_IE_PLTYPE_STR, "RemoteAddress" },
00262 [AST_EVENT_IE_EVENT_TV] = { AST_EVENT_IE_PLTYPE_STR, "EventTV" },
00263 [AST_EVENT_IE_REQUEST_TYPE] = { AST_EVENT_IE_PLTYPE_STR, "RequestType" },
00264 [AST_EVENT_IE_REQUEST_PARAMS] = { AST_EVENT_IE_PLTYPE_STR, "RequestParams" },
00265 [AST_EVENT_IE_AUTH_METHOD] = { AST_EVENT_IE_PLTYPE_STR, "AuthMethod" },
00266 [AST_EVENT_IE_SEVERITY] = { AST_EVENT_IE_PLTYPE_STR, "Severity" },
00267 [AST_EVENT_IE_EXPECTED_ADDR] = { AST_EVENT_IE_PLTYPE_STR, "ExpectedAddress" },
00268 [AST_EVENT_IE_CHALLENGE] = { AST_EVENT_IE_PLTYPE_STR, "Challenge" },
00269 [AST_EVENT_IE_RESPONSE] = { AST_EVENT_IE_PLTYPE_STR, "Response" },
00270 [AST_EVENT_IE_EXPECTED_RESPONSE] = { AST_EVENT_IE_PLTYPE_STR, "ExpectedResponse" },
00271 };
00272
00273 const char *ast_event_get_type_name(const struct ast_event *event)
00274 {
00275 enum ast_event_type type;
00276
00277 type = ast_event_get_type(event);
00278
00279 if (type < 0 || type >= ARRAY_LEN(event_names)) {
00280 ast_log(LOG_ERROR, "Invalid event type - '%d'\n", type);
00281 return "";
00282 }
00283
00284 return event_names[type];
00285 }
00286
00287 int ast_event_str_to_event_type(const char *str, enum ast_event_type *event_type)
00288 {
00289 int i;
00290
00291 for (i = 0; i < ARRAY_LEN(event_names); i++) {
00292 if (ast_strlen_zero(event_names[i]) || strcasecmp(event_names[i], str)) {
00293 continue;
00294 }
00295
00296 *event_type = i;
00297 return 0;
00298 }
00299
00300 return -1;
00301 }
00302
00303 const char *ast_event_get_ie_type_name(enum ast_event_ie_type ie_type)
00304 {
00305 if (ie_type <= 0 || ie_type >= ARRAY_LEN(ie_maps)) {
00306 ast_log(LOG_ERROR, "Invalid IE type - '%d'\n", ie_type);
00307 return "";
00308 }
00309
00310 return ie_maps[ie_type].name;
00311 }
00312
00313 enum ast_event_ie_pltype ast_event_get_ie_pltype(enum ast_event_ie_type ie_type)
00314 {
00315 if (ie_type <= 0 || ie_type >= ARRAY_LEN(ie_maps)) {
00316 ast_log(LOG_ERROR, "Invalid IE type - '%d'\n", ie_type);
00317 return AST_EVENT_IE_PLTYPE_UNKNOWN;
00318 }
00319
00320 return ie_maps[ie_type].ie_pltype;
00321 }
00322
00323 int ast_event_str_to_ie_type(const char *str, enum ast_event_ie_type *ie_type)
00324 {
00325 int i;
00326
00327 for (i = 0; i < ARRAY_LEN(ie_maps); i++) {
00328 if (strcasecmp(ie_maps[i].name, str)) {
00329 continue;
00330 }
00331
00332 *ie_type = i;
00333 return 0;
00334 }
00335
00336 return -1;
00337 }
00338
00339 size_t ast_event_get_size(const struct ast_event *event)
00340 {
00341 size_t res;
00342
00343 res = ntohs(event->event_len);
00344
00345 return res;
00346 }
00347
00348 static void ast_event_ie_val_destroy(struct ast_event_ie_val *ie_val)
00349 {
00350 switch (ie_val->ie_pltype) {
00351 case AST_EVENT_IE_PLTYPE_STR:
00352 ast_free((char *) ie_val->payload.str);
00353 break;
00354 case AST_EVENT_IE_PLTYPE_RAW:
00355 ast_free(ie_val->payload.raw);
00356 break;
00357 case AST_EVENT_IE_PLTYPE_UINT:
00358 case AST_EVENT_IE_PLTYPE_BITFLAGS:
00359 case AST_EVENT_IE_PLTYPE_EXISTS:
00360 case AST_EVENT_IE_PLTYPE_UNKNOWN:
00361 break;
00362 }
00363
00364 ast_free(ie_val);
00365 }
00366
00367
00368 struct ast_ev_check_list {
00369 AST_LIST_HEAD_NOLOCK(, ast_event_ie_val) ie_vals;
00370 };
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382 static int match_sub_ie_val_to_event(const struct ast_event_ie_val *sub_ie_val, const struct ast_ev_check_list *check_ie_vals)
00383 {
00384 const struct ast_event_ie_val *event_ie_val;
00385 int res = 0;
00386
00387 AST_LIST_TRAVERSE(&check_ie_vals->ie_vals, event_ie_val, entry) {
00388 if (sub_ie_val->ie_type == event_ie_val->ie_type) {
00389 break;
00390 }
00391 }
00392 if (!event_ie_val) {
00393
00394 return 0;
00395 }
00396
00397 if (sub_ie_val->ie_pltype != event_ie_val->ie_pltype) {
00398 if (sub_ie_val->ie_pltype == AST_EVENT_IE_PLTYPE_EXISTS) {
00399
00400 return 1;
00401 }
00402
00403 return 0;
00404 }
00405
00406 switch (sub_ie_val->ie_pltype) {
00407 case AST_EVENT_IE_PLTYPE_UINT:
00408 res = (sub_ie_val->payload.uint == event_ie_val->payload.uint);
00409 break;
00410 case AST_EVENT_IE_PLTYPE_BITFLAGS:
00411
00412
00413
00414
00415 res = (sub_ie_val->payload.uint & event_ie_val->payload.uint);
00416 break;
00417 case AST_EVENT_IE_PLTYPE_STR:
00418 {
00419 const char *substr = sub_ie_val->payload.str;
00420 const char *estr = event_ie_val->payload.str;
00421 if (sub_ie_val->ie_type == AST_EVENT_IE_DEVICE) {
00422 substr = ast_tech_to_upper(ast_strdupa(substr));
00423 estr = ast_tech_to_upper(ast_strdupa(estr));
00424 }
00425 res = !strcmp(substr, estr);
00426 break;
00427 }
00428 case AST_EVENT_IE_PLTYPE_RAW:
00429 res = (sub_ie_val->raw_datalen == event_ie_val->raw_datalen
00430 && !memcmp(sub_ie_val->payload.raw, event_ie_val->payload.raw,
00431 sub_ie_val->raw_datalen));
00432 break;
00433 case AST_EVENT_IE_PLTYPE_EXISTS:
00434
00435 break;
00436 case AST_EVENT_IE_PLTYPE_UNKNOWN:
00437
00438
00439
00440
00441 break;
00442 }
00443
00444 return res;
00445 }
00446
00447 enum ast_event_subscriber_res ast_event_check_subscriber(enum ast_event_type type, ...)
00448 {
00449 va_list ap;
00450 enum ast_event_ie_type ie_type;
00451 enum ast_event_subscriber_res res = AST_EVENT_SUB_NONE;
00452 struct ast_event_ie_val *ie_val;
00453 struct ast_event_sub *sub;
00454 struct ast_ev_check_list check_ie_vals = {
00455 .ie_vals = AST_LIST_HEAD_NOLOCK_INIT_VALUE
00456 };
00457 const enum ast_event_type event_types[] = { type, AST_EVENT_ALL };
00458 int i;
00459 int want_specific_event;
00460
00461 if (type >= AST_EVENT_TOTAL) {
00462 ast_log(LOG_ERROR, "%u is an invalid type!\n", type);
00463 return res;
00464 }
00465
00466 want_specific_event = 0;
00467 va_start(ap, type);
00468 for (ie_type = va_arg(ap, enum ast_event_ie_type);
00469 ie_type != AST_EVENT_IE_END;
00470 ie_type = va_arg(ap, enum ast_event_ie_type))
00471 {
00472 struct ast_event_ie_val *ie_value = alloca(sizeof(*ie_value));
00473 int insert = 0;
00474
00475 memset(ie_value, 0, sizeof(*ie_value));
00476 ie_value->ie_type = ie_type;
00477 ie_value->ie_pltype = va_arg(ap, enum ast_event_ie_pltype);
00478 switch (ie_value->ie_pltype) {
00479 case AST_EVENT_IE_PLTYPE_UINT:
00480 ie_value->payload.uint = va_arg(ap, uint32_t);
00481 insert = 1;
00482 break;
00483 case AST_EVENT_IE_PLTYPE_BITFLAGS:
00484 ie_value->payload.uint = va_arg(ap, uint32_t);
00485 insert = 1;
00486 break;
00487 case AST_EVENT_IE_PLTYPE_STR:
00488 ie_value->payload.str = va_arg(ap, const char *);
00489 insert = 1;
00490 break;
00491 case AST_EVENT_IE_PLTYPE_RAW:
00492 {
00493 void *data = va_arg(ap, void *);
00494 size_t datalen = va_arg(ap, size_t);
00495
00496 ie_value->payload.raw = alloca(datalen);
00497 memcpy(ie_value->payload.raw, data, datalen);
00498 ie_value->raw_datalen = datalen;
00499 insert = 1;
00500 break;
00501 }
00502 case AST_EVENT_IE_PLTYPE_UNKNOWN:
00503 case AST_EVENT_IE_PLTYPE_EXISTS:
00504
00505 break;
00506 }
00507
00508 if (insert) {
00509 want_specific_event = 1;
00510 AST_LIST_INSERT_TAIL(&check_ie_vals.ie_vals, ie_value, entry);
00511 } else {
00512 ast_log(LOG_WARNING, "Unsupported PLTYPE(%d)\n", ie_value->ie_pltype);
00513 }
00514 }
00515 va_end(ap);
00516
00517 for (i = 0; i < ARRAY_LEN(event_types); i++) {
00518 AST_RWDLLIST_RDLOCK(&ast_event_subs[event_types[i]]);
00519 if (want_specific_event) {
00520 AST_RWDLLIST_TRAVERSE(&ast_event_subs[event_types[i]], sub, entry) {
00521 AST_LIST_TRAVERSE(&sub->ie_vals, ie_val, entry) {
00522 if (!match_sub_ie_val_to_event(ie_val, &check_ie_vals)) {
00523
00524 break;
00525 }
00526 }
00527 if (!ie_val) {
00528
00529 break;
00530 }
00531 }
00532 } else {
00533
00534 sub = AST_RWLIST_FIRST(&ast_event_subs[event_types[i]]);
00535 }
00536 AST_RWDLLIST_UNLOCK(&ast_event_subs[event_types[i]]);
00537 if (sub) {
00538 break;
00539 }
00540 }
00541
00542 return sub ? AST_EVENT_SUB_EXISTS : AST_EVENT_SUB_NONE;
00543 }
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558 static int match_ie_val(const struct ast_event *event,
00559 const struct ast_event_ie_val *ie_val, const struct ast_event *event2)
00560 {
00561 switch (ie_val->ie_pltype) {
00562 case AST_EVENT_IE_PLTYPE_UINT:
00563 {
00564 uint32_t val = event2 ? ast_event_get_ie_uint(event2, ie_val->ie_type) : ie_val->payload.uint;
00565
00566 return (val == ast_event_get_ie_uint(event, ie_val->ie_type)) ? 1 : 0;
00567 }
00568
00569 case AST_EVENT_IE_PLTYPE_BITFLAGS:
00570 {
00571 uint32_t flags = event2 ? ast_event_get_ie_uint(event2, ie_val->ie_type) : ie_val->payload.uint;
00572
00573
00574
00575
00576
00577 return (flags & ast_event_get_ie_bitflags(event, ie_val->ie_type)) ? 1 : 0;
00578 }
00579
00580 case AST_EVENT_IE_PLTYPE_STR:
00581 {
00582 const char *str;
00583 uint32_t hash;
00584
00585 hash = event2 ? ast_event_get_ie_str_hash(event2, ie_val->ie_type) : ie_val->payload.hash;
00586 if (hash != ast_event_get_ie_str_hash(event, ie_val->ie_type)) {
00587 return 0;
00588 }
00589
00590 str = event2 ? ast_event_get_ie_str(event2, ie_val->ie_type) : ie_val->payload.str;
00591 if (str) {
00592 const char *e1str, *e2str;
00593 e1str = ast_event_get_ie_str(event, ie_val->ie_type);
00594 e2str = str;
00595
00596 if (ie_val->ie_type == AST_EVENT_IE_DEVICE) {
00597 e1str = ast_tech_to_upper(ast_strdupa(e1str));
00598 e2str = ast_tech_to_upper(ast_strdupa(e2str));
00599 }
00600
00601 if (!strcmp(e1str, e2str)) {
00602 return 1;
00603 }
00604 }
00605
00606 return 0;
00607 }
00608
00609 case AST_EVENT_IE_PLTYPE_RAW:
00610 {
00611 const void *buf = event2 ? ast_event_get_ie_raw(event2, ie_val->ie_type) : ie_val->payload.raw;
00612 uint16_t ie_payload_len = event2 ? ast_event_get_ie_raw_payload_len(event2, ie_val->ie_type) : ie_val->raw_datalen;
00613
00614 return (buf
00615 && ie_payload_len == ast_event_get_ie_raw_payload_len(event, ie_val->ie_type)
00616 && !memcmp(buf, ast_event_get_ie_raw(event, ie_val->ie_type), ie_payload_len)) ? 1 : 0;
00617 }
00618
00619 case AST_EVENT_IE_PLTYPE_EXISTS:
00620 {
00621 return ast_event_get_ie_raw(event, ie_val->ie_type) ? 1 : 0;
00622 }
00623
00624 case AST_EVENT_IE_PLTYPE_UNKNOWN:
00625 return 0;
00626 }
00627
00628 return 0;
00629 }
00630
00631 static int dump_cache_cb(void *obj, void *arg, int flags)
00632 {
00633 const struct ast_event_ref *event_ref = obj;
00634 const struct ast_event *event = event_ref->event;
00635 const struct ast_event_sub *event_sub = arg;
00636 struct ast_event_ie_val *ie_val = NULL;
00637
00638 AST_LIST_TRAVERSE(&event_sub->ie_vals, ie_val, entry) {
00639 if (!match_ie_val(event, ie_val, NULL)) {
00640 break;
00641 }
00642 }
00643
00644 if (!ie_val) {
00645
00646 event_sub->cb(event, event_sub->userdata);
00647 }
00648
00649 return 0;
00650 }
00651
00652
00653 void ast_event_dump_cache(const struct ast_event_sub *event_sub)
00654 {
00655 ao2_callback(ast_event_cache[event_sub->type].container, OBJ_NODATA,
00656 dump_cache_cb, (void *) event_sub);
00657 }
00658
00659 static struct ast_event *gen_sub_event(struct ast_event_sub *sub)
00660 {
00661 struct ast_event_ie_val *ie_val;
00662 struct ast_event *event;
00663
00664 event = ast_event_new(AST_EVENT_SUB,
00665 AST_EVENT_IE_UNIQUEID, AST_EVENT_IE_PLTYPE_UINT, sub->uniqueid,
00666 AST_EVENT_IE_EVENTTYPE, AST_EVENT_IE_PLTYPE_UINT, sub->type,
00667 AST_EVENT_IE_DESCRIPTION, AST_EVENT_IE_PLTYPE_STR, sub->description,
00668 AST_EVENT_IE_END);
00669 if (!event)
00670 return NULL;
00671
00672 AST_LIST_TRAVERSE(&sub->ie_vals, ie_val, entry) {
00673 switch (ie_val->ie_pltype) {
00674 case AST_EVENT_IE_PLTYPE_UNKNOWN:
00675 break;
00676 case AST_EVENT_IE_PLTYPE_EXISTS:
00677 ast_event_append_ie_uint(&event, AST_EVENT_IE_EXISTS, ie_val->ie_type);
00678 break;
00679 case AST_EVENT_IE_PLTYPE_UINT:
00680 ast_event_append_ie_uint(&event, ie_val->ie_type, ie_val->payload.uint);
00681 break;
00682 case AST_EVENT_IE_PLTYPE_BITFLAGS:
00683 ast_event_append_ie_bitflags(&event, ie_val->ie_type, ie_val->payload.uint);
00684 break;
00685 case AST_EVENT_IE_PLTYPE_STR:
00686 ast_event_append_ie_str(&event, ie_val->ie_type, ie_val->payload.str);
00687 break;
00688 case AST_EVENT_IE_PLTYPE_RAW:
00689 ast_event_append_ie_raw(&event, ie_val->ie_type, ie_val->payload.raw, ie_val->raw_datalen);
00690 break;
00691 }
00692 if (!event)
00693 break;
00694 }
00695
00696 return event;
00697 }
00698
00699
00700 void ast_event_report_subs(const struct ast_event_sub *event_sub)
00701 {
00702 struct ast_event *event;
00703 struct ast_event_sub *sub;
00704 enum ast_event_type event_type = -1;
00705 struct ast_event_ie_val *ie_val;
00706
00707 if (event_sub->type != AST_EVENT_SUB)
00708 return;
00709
00710 AST_LIST_TRAVERSE(&event_sub->ie_vals, ie_val, entry) {
00711 if (ie_val->ie_type == AST_EVENT_IE_EVENTTYPE) {
00712 event_type = ie_val->payload.uint;
00713 break;
00714 }
00715 }
00716
00717 if (event_type == -1)
00718 return;
00719
00720 AST_RWDLLIST_RDLOCK(&ast_event_subs[event_type]);
00721 AST_RWDLLIST_TRAVERSE(&ast_event_subs[event_type], sub, entry) {
00722 if (event_sub == sub) {
00723 continue;
00724 }
00725
00726 event = gen_sub_event(sub);
00727 if (!event) {
00728 continue;
00729 }
00730
00731 event_sub->cb(event, event_sub->userdata);
00732
00733 ast_event_destroy(event);
00734 }
00735 AST_RWDLLIST_UNLOCK(&ast_event_subs[event_type]);
00736 }
00737
00738 struct ast_event_sub *ast_event_subscribe_new(enum ast_event_type type,
00739 ast_event_cb_t cb, void *userdata)
00740 {
00741 struct ast_event_sub *sub;
00742
00743 if (type < 0 || type >= AST_EVENT_TOTAL) {
00744 ast_log(LOG_ERROR, "%u is an invalid type!\n", type);
00745 return NULL;
00746 }
00747
00748 if (!(sub = ast_calloc(1, sizeof(*sub)))) {
00749 return NULL;
00750 }
00751
00752 sub->type = type;
00753 sub->cb = cb;
00754 sub->userdata = userdata;
00755 sub->uniqueid = ast_atomic_fetchadd_int((int *) &sub_uniqueid, 1);
00756
00757 return sub;
00758 }
00759
00760 int ast_event_sub_append_ie_uint(struct ast_event_sub *sub,
00761 enum ast_event_ie_type ie_type, uint32_t unsigned_int)
00762 {
00763 struct ast_event_ie_val *ie_val;
00764
00765 if (ie_type <= 0 || ie_type >= AST_EVENT_IE_TOTAL) {
00766 return -1;
00767 }
00768
00769 if (!(ie_val = ast_calloc(1, sizeof(*ie_val)))) {
00770 return -1;
00771 }
00772
00773 ie_val->ie_type = ie_type;
00774 ie_val->payload.uint = unsigned_int;
00775 ie_val->ie_pltype = AST_EVENT_IE_PLTYPE_UINT;
00776
00777 AST_LIST_INSERT_TAIL(&sub->ie_vals, ie_val, entry);
00778
00779 return 0;
00780 }
00781
00782 int ast_event_sub_append_ie_bitflags(struct ast_event_sub *sub,
00783 enum ast_event_ie_type ie_type, uint32_t flags)
00784 {
00785 struct ast_event_ie_val *ie_val;
00786
00787 if (ie_type <= 0 || ie_type >= AST_EVENT_IE_TOTAL) {
00788 return -1;
00789 }
00790
00791 if (!(ie_val = ast_calloc(1, sizeof(*ie_val)))) {
00792 return -1;
00793 }
00794
00795 ie_val->ie_type = ie_type;
00796 ie_val->payload.uint = flags;
00797 ie_val->ie_pltype = AST_EVENT_IE_PLTYPE_BITFLAGS;
00798
00799 AST_LIST_INSERT_TAIL(&sub->ie_vals, ie_val, entry);
00800
00801 return 0;
00802 }
00803
00804 int ast_event_sub_append_ie_exists(struct ast_event_sub *sub,
00805 enum ast_event_ie_type ie_type)
00806 {
00807 struct ast_event_ie_val *ie_val;
00808
00809 if (ie_type <= 0 || ie_type >= AST_EVENT_IE_TOTAL) {
00810 return -1;
00811 }
00812
00813 if (!(ie_val = ast_calloc(1, sizeof(*ie_val)))) {
00814 return -1;
00815 }
00816
00817 ie_val->ie_type = ie_type;
00818 ie_val->ie_pltype = AST_EVENT_IE_PLTYPE_EXISTS;
00819
00820 AST_LIST_INSERT_TAIL(&sub->ie_vals, ie_val, entry);
00821
00822 return 0;
00823 }
00824
00825 int ast_event_sub_append_ie_str(struct ast_event_sub *sub,
00826 enum ast_event_ie_type ie_type, const char *str)
00827 {
00828 struct ast_event_ie_val *ie_val;
00829
00830 if (ie_type <= 0 || ie_type >= AST_EVENT_IE_TOTAL) {
00831 return -1;
00832 }
00833
00834 if (!(ie_val = ast_calloc(1, sizeof(*ie_val)))) {
00835 return -1;
00836 }
00837
00838 ie_val->ie_type = ie_type;
00839 ie_val->ie_pltype = AST_EVENT_IE_PLTYPE_STR;
00840
00841 if (!(ie_val->payload.str = ast_strdup(str))) {
00842 ast_free(ie_val);
00843 return -1;
00844 }
00845
00846 if (ie_type == AST_EVENT_IE_DEVICE) {
00847 char *uppertech = ast_strdupa(str);
00848 ast_tech_to_upper(uppertech);
00849 ie_val->payload.hash = ast_str_hash(uppertech);
00850 } else {
00851 ie_val->payload.hash = ast_str_hash(str);
00852 }
00853
00854 AST_LIST_INSERT_TAIL(&sub->ie_vals, ie_val, entry);
00855
00856 return 0;
00857 }
00858
00859 int ast_event_sub_append_ie_raw(struct ast_event_sub *sub,
00860 enum ast_event_ie_type ie_type, void *data, size_t raw_datalen)
00861 {
00862 struct ast_event_ie_val *ie_val;
00863
00864 if (ie_type <= 0 || ie_type >= AST_EVENT_IE_TOTAL) {
00865 return -1;
00866 }
00867
00868 if (!(ie_val = ast_calloc(1, sizeof(*ie_val)))) {
00869 return -1;
00870 }
00871
00872 ie_val->ie_type = ie_type;
00873 ie_val->ie_pltype = AST_EVENT_IE_PLTYPE_RAW;
00874 ie_val->raw_datalen = raw_datalen;
00875
00876 if (!(ie_val->payload.raw = ast_malloc(raw_datalen))) {
00877 ast_free(ie_val);
00878 return -1;
00879 }
00880
00881 memcpy(ie_val->payload.raw, data, raw_datalen);
00882
00883 AST_LIST_INSERT_TAIL(&sub->ie_vals, ie_val, entry);
00884
00885 return 0;
00886 }
00887
00888 int ast_event_sub_activate(struct ast_event_sub *sub)
00889 {
00890 if (ast_event_check_subscriber(AST_EVENT_SUB,
00891 AST_EVENT_IE_EVENTTYPE, AST_EVENT_IE_PLTYPE_UINT, sub->type,
00892 AST_EVENT_IE_END) != AST_EVENT_SUB_NONE) {
00893 struct ast_event *event;
00894
00895 event = gen_sub_event(sub);
00896 if (event && ast_event_queue(event)) {
00897 ast_event_destroy(event);
00898 }
00899 }
00900
00901 AST_RWDLLIST_WRLOCK(&ast_event_subs[sub->type]);
00902 AST_RWDLLIST_INSERT_TAIL(&ast_event_subs[sub->type], sub, entry);
00903 AST_RWDLLIST_UNLOCK(&ast_event_subs[sub->type]);
00904
00905 return 0;
00906 }
00907
00908 struct ast_event_sub *ast_event_subscribe(enum ast_event_type type, ast_event_cb_t cb,
00909 const char *description, void *userdata, ...)
00910 {
00911 va_list ap;
00912 enum ast_event_ie_type ie_type;
00913 struct ast_event_sub *sub;
00914
00915 if (!(sub = ast_event_subscribe_new(type, cb, userdata))) {
00916 return NULL;
00917 }
00918
00919 ast_copy_string(sub->description, description, sizeof(sub->description));
00920
00921 va_start(ap, userdata);
00922 for (ie_type = va_arg(ap, enum ast_event_ie_type);
00923 ie_type != AST_EVENT_IE_END;
00924 ie_type = va_arg(ap, enum ast_event_ie_type))
00925 {
00926 enum ast_event_ie_pltype ie_pltype;
00927
00928 ie_pltype = va_arg(ap, enum ast_event_ie_pltype);
00929
00930 switch (ie_pltype) {
00931 case AST_EVENT_IE_PLTYPE_UNKNOWN:
00932 break;
00933 case AST_EVENT_IE_PLTYPE_UINT:
00934 {
00935 uint32_t unsigned_int = va_arg(ap, uint32_t);
00936 ast_event_sub_append_ie_uint(sub, ie_type, unsigned_int);
00937 break;
00938 }
00939 case AST_EVENT_IE_PLTYPE_BITFLAGS:
00940 {
00941 uint32_t unsigned_int = va_arg(ap, uint32_t);
00942 ast_event_sub_append_ie_bitflags(sub, ie_type, unsigned_int);
00943 break;
00944 }
00945 case AST_EVENT_IE_PLTYPE_STR:
00946 {
00947 const char *str = va_arg(ap, const char *);
00948 ast_event_sub_append_ie_str(sub, ie_type, str);
00949 break;
00950 }
00951 case AST_EVENT_IE_PLTYPE_RAW:
00952 {
00953 void *data = va_arg(ap, void *);
00954 size_t data_len = va_arg(ap, size_t);
00955 ast_event_sub_append_ie_raw(sub, ie_type, data, data_len);
00956 break;
00957 }
00958 case AST_EVENT_IE_PLTYPE_EXISTS:
00959 ast_event_sub_append_ie_exists(sub, ie_type);
00960 break;
00961 }
00962 }
00963 va_end(ap);
00964
00965 ast_event_sub_activate(sub);
00966
00967 return sub;
00968 }
00969
00970 void ast_event_sub_destroy(struct ast_event_sub *sub)
00971 {
00972 struct ast_event_ie_val *ie_val;
00973
00974 while ((ie_val = AST_LIST_REMOVE_HEAD(&sub->ie_vals, entry))) {
00975 ast_event_ie_val_destroy(ie_val);
00976 }
00977
00978 ast_free(sub);
00979 }
00980
00981 const char *ast_event_subscriber_get_description(struct ast_event_sub *sub)
00982 {
00983 return sub ? sub->description : NULL;
00984 }
00985
00986 struct ast_event_sub *ast_event_unsubscribe(struct ast_event_sub *sub)
00987 {
00988 struct ast_event *event;
00989
00990 AST_RWDLLIST_WRLOCK(&ast_event_subs[sub->type]);
00991 AST_DLLIST_REMOVE(&ast_event_subs[sub->type], sub, entry);
00992 AST_RWDLLIST_UNLOCK(&ast_event_subs[sub->type]);
00993
00994 if (ast_event_check_subscriber(AST_EVENT_UNSUB,
00995 AST_EVENT_IE_EVENTTYPE, AST_EVENT_IE_PLTYPE_UINT, sub->type,
00996 AST_EVENT_IE_END) != AST_EVENT_SUB_NONE) {
00997
00998 event = ast_event_new(AST_EVENT_UNSUB,
00999 AST_EVENT_IE_UNIQUEID, AST_EVENT_IE_PLTYPE_UINT, sub->uniqueid,
01000 AST_EVENT_IE_EVENTTYPE, AST_EVENT_IE_PLTYPE_UINT, sub->type,
01001 AST_EVENT_IE_DESCRIPTION, AST_EVENT_IE_PLTYPE_STR, sub->description,
01002 AST_EVENT_IE_END);
01003 if (event && ast_event_queue(event)) {
01004 ast_event_destroy(event);
01005 }
01006 }
01007
01008 ast_event_sub_destroy(sub);
01009
01010 return NULL;
01011 }
01012
01013 int ast_event_iterator_init(struct ast_event_iterator *iterator, const struct ast_event *event)
01014 {
01015 int res = 0;
01016
01017 iterator->event_len = ast_event_get_size(event);
01018 iterator->event = event;
01019 if (iterator->event_len >= sizeof(*event) + sizeof(struct ast_event_ie)) {
01020 iterator->ie = (struct ast_event_ie *) ( ((char *) event) + sizeof(*event) );
01021 } else {
01022 iterator->ie = NULL;
01023 res = -1;
01024 }
01025
01026 return res;
01027 }
01028
01029 int ast_event_iterator_next(struct ast_event_iterator *iterator)
01030 {
01031 iterator->ie = (struct ast_event_ie *) ( ((char *) iterator->ie) + sizeof(*iterator->ie) + ntohs(iterator->ie->ie_payload_len));
01032 return ((iterator->event_len <= (((char *) iterator->ie) - ((char *) iterator->event))) ? -1 : 0);
01033 }
01034
01035 enum ast_event_ie_type ast_event_iterator_get_ie_type(struct ast_event_iterator *iterator)
01036 {
01037 return ntohs(iterator->ie->ie_type);
01038 }
01039
01040 uint32_t ast_event_iterator_get_ie_uint(struct ast_event_iterator *iterator)
01041 {
01042 return ntohl(get_unaligned_uint32(iterator->ie->ie_payload));
01043 }
01044
01045 uint32_t ast_event_iterator_get_ie_bitflags(struct ast_event_iterator *iterator)
01046 {
01047 return ntohl(get_unaligned_uint32(iterator->ie->ie_payload));
01048 }
01049
01050 const char *ast_event_iterator_get_ie_str(struct ast_event_iterator *iterator)
01051 {
01052 const struct ast_event_ie_str_payload *str_payload;
01053
01054 str_payload = (struct ast_event_ie_str_payload *) iterator->ie->ie_payload;
01055
01056 return str_payload ? str_payload->str : NULL;
01057 }
01058
01059 void *ast_event_iterator_get_ie_raw(struct ast_event_iterator *iterator)
01060 {
01061 return iterator->ie->ie_payload;
01062 }
01063
01064 uint16_t ast_event_iterator_get_ie_raw_payload_len(struct ast_event_iterator *iterator)
01065 {
01066 return ntohs(iterator->ie->ie_payload_len);
01067 }
01068
01069 enum ast_event_type ast_event_get_type(const struct ast_event *event)
01070 {
01071 return ntohs(event->type);
01072 }
01073
01074 uint32_t ast_event_get_ie_uint(const struct ast_event *event, enum ast_event_ie_type ie_type)
01075 {
01076 const uint32_t *ie_val;
01077
01078 ie_val = ast_event_get_ie_raw(event, ie_type);
01079
01080 return ie_val ? ntohl(get_unaligned_uint32(ie_val)) : 0;
01081 }
01082
01083 uint32_t ast_event_get_ie_bitflags(const struct ast_event *event, enum ast_event_ie_type ie_type)
01084 {
01085 const uint32_t *ie_val;
01086
01087 ie_val = ast_event_get_ie_raw(event, ie_type);
01088
01089 return ie_val ? ntohl(get_unaligned_uint32(ie_val)) : 0;
01090 }
01091
01092 uint32_t ast_event_get_ie_str_hash(const struct ast_event *event, enum ast_event_ie_type ie_type)
01093 {
01094 const struct ast_event_ie_str_payload *str_payload;
01095
01096 str_payload = ast_event_get_ie_raw(event, ie_type);
01097
01098 return str_payload ? str_payload->hash : 0;
01099 }
01100
01101 const char *ast_event_get_ie_str(const struct ast_event *event, enum ast_event_ie_type ie_type)
01102 {
01103 const struct ast_event_ie_str_payload *str_payload;
01104
01105 str_payload = ast_event_get_ie_raw(event, ie_type);
01106
01107 return str_payload ? str_payload->str : NULL;
01108 }
01109
01110 const void *ast_event_get_ie_raw(const struct ast_event *event, enum ast_event_ie_type ie_type)
01111 {
01112 struct ast_event_iterator iterator;
01113 int res;
01114
01115 for (res = ast_event_iterator_init(&iterator, event); !res; res = ast_event_iterator_next(&iterator)) {
01116 if (ast_event_iterator_get_ie_type(&iterator) == ie_type) {
01117 return ast_event_iterator_get_ie_raw(&iterator);
01118 }
01119 }
01120
01121 return NULL;
01122 }
01123
01124 uint16_t ast_event_get_ie_raw_payload_len(const struct ast_event *event, enum ast_event_ie_type ie_type)
01125 {
01126 struct ast_event_iterator iterator;
01127 int res;
01128
01129 for (res = ast_event_iterator_init(&iterator, event); !res; res = ast_event_iterator_next(&iterator)) {
01130 if (ast_event_iterator_get_ie_type(&iterator) == ie_type) {
01131 return ast_event_iterator_get_ie_raw_payload_len(&iterator);
01132 }
01133 }
01134
01135 return 0;
01136 }
01137
01138 int ast_event_append_ie_str(struct ast_event **event, enum ast_event_ie_type ie_type,
01139 const char *str)
01140 {
01141 struct ast_event_ie_str_payload *str_payload;
01142 size_t payload_len;
01143
01144 payload_len = sizeof(*str_payload) + strlen(str);
01145 str_payload = alloca(payload_len);
01146
01147 strcpy(str_payload->str, str);
01148 if (ie_type == AST_EVENT_IE_DEVICE) {
01149 char *uppertech = ast_strdupa(str);
01150 ast_tech_to_upper(uppertech);
01151 str_payload->hash = ast_str_hash(uppertech);
01152 } else {
01153 str_payload->hash = ast_str_hash(str);
01154 }
01155
01156 return ast_event_append_ie_raw(event, ie_type, str_payload, payload_len);
01157 }
01158
01159 int ast_event_append_ie_uint(struct ast_event **event, enum ast_event_ie_type ie_type,
01160 uint32_t data)
01161 {
01162 data = htonl(data);
01163 return ast_event_append_ie_raw(event, ie_type, &data, sizeof(data));
01164 }
01165
01166 int ast_event_append_ie_bitflags(struct ast_event **event, enum ast_event_ie_type ie_type,
01167 uint32_t flags)
01168 {
01169 flags = htonl(flags);
01170 return ast_event_append_ie_raw(event, ie_type, &flags, sizeof(flags));
01171 }
01172
01173 int ast_event_append_ie_raw(struct ast_event **event, enum ast_event_ie_type ie_type,
01174 const void *data, size_t data_len)
01175 {
01176 struct ast_event_ie *ie;
01177 unsigned int extra_len;
01178 uint16_t event_len;
01179
01180 event_len = ntohs((*event)->event_len);
01181 extra_len = sizeof(*ie) + data_len;
01182
01183 if (!(*event = ast_realloc(*event, event_len + extra_len))) {
01184 return -1;
01185 }
01186
01187 ie = (struct ast_event_ie *) ( ((char *) *event) + event_len );
01188 ie->ie_type = htons(ie_type);
01189 ie->ie_payload_len = htons(data_len);
01190 memcpy(ie->ie_payload, data, data_len);
01191
01192 (*event)->event_len = htons(event_len + extra_len);
01193
01194 return 0;
01195 }
01196
01197 struct ast_event *ast_event_new(enum ast_event_type type, ...)
01198 {
01199 va_list ap;
01200 struct ast_event *event;
01201 enum ast_event_ie_type ie_type;
01202 struct ast_event_ie_val *ie_val;
01203 int has_ie = 0;
01204 AST_LIST_HEAD_NOLOCK_STATIC(ie_vals, ast_event_ie_val);
01205
01206
01207 if (type >= AST_EVENT_TOTAL) {
01208 ast_log(LOG_WARNING, "Someone tried to create an event of invalid "
01209 "type '%d'!\n", type);
01210 return NULL;
01211 }
01212
01213 va_start(ap, type);
01214 for (ie_type = va_arg(ap, enum ast_event_ie_type);
01215 ie_type != AST_EVENT_IE_END;
01216 ie_type = va_arg(ap, enum ast_event_ie_type))
01217 {
01218 struct ast_event_ie_val *ie_value = alloca(sizeof(*ie_value));
01219 int insert = 0;
01220
01221 memset(ie_value, 0, sizeof(*ie_value));
01222 ie_value->ie_type = ie_type;
01223 ie_value->ie_pltype = va_arg(ap, enum ast_event_ie_pltype);
01224 switch (ie_value->ie_pltype) {
01225 case AST_EVENT_IE_PLTYPE_UINT:
01226 ie_value->payload.uint = va_arg(ap, uint32_t);
01227 insert = 1;
01228 break;
01229 case AST_EVENT_IE_PLTYPE_BITFLAGS:
01230 ie_value->payload.uint = va_arg(ap, uint32_t);
01231 insert = 1;
01232 break;
01233 case AST_EVENT_IE_PLTYPE_STR:
01234 ie_value->payload.str = va_arg(ap, const char *);
01235 insert = 1;
01236 break;
01237 case AST_EVENT_IE_PLTYPE_RAW:
01238 {
01239 void *data = va_arg(ap, void *);
01240 size_t datalen = va_arg(ap, size_t);
01241 ie_value->payload.raw = alloca(datalen);
01242 memcpy(ie_value->payload.raw, data, datalen);
01243 ie_value->raw_datalen = datalen;
01244 insert = 1;
01245 break;
01246 }
01247 case AST_EVENT_IE_PLTYPE_UNKNOWN:
01248 case AST_EVENT_IE_PLTYPE_EXISTS:
01249 break;
01250 }
01251
01252 if (insert) {
01253 AST_LIST_INSERT_TAIL(&ie_vals, ie_value, entry);
01254 has_ie = 1;
01255 } else {
01256 ast_log(LOG_WARNING, "Unsupported PLTYPE(%d)\n", ie_value->ie_pltype);
01257 }
01258 }
01259 va_end(ap);
01260
01261 if (!(event = ast_calloc(1, sizeof(*event)))) {
01262 return NULL;
01263 }
01264
01265 event->type = htons(type);
01266 event->event_len = htons(sizeof(*event));
01267
01268 AST_LIST_TRAVERSE(&ie_vals, ie_val, entry) {
01269 switch (ie_val->ie_pltype) {
01270 case AST_EVENT_IE_PLTYPE_STR:
01271 ast_event_append_ie_str(&event, ie_val->ie_type, ie_val->payload.str);
01272 break;
01273 case AST_EVENT_IE_PLTYPE_UINT:
01274 ast_event_append_ie_uint(&event, ie_val->ie_type, ie_val->payload.uint);
01275 break;
01276 case AST_EVENT_IE_PLTYPE_BITFLAGS:
01277 ast_event_append_ie_bitflags(&event, ie_val->ie_type, ie_val->payload.uint);
01278 break;
01279 case AST_EVENT_IE_PLTYPE_RAW:
01280 ast_event_append_ie_raw(&event, ie_val->ie_type,
01281 ie_val->payload.raw, ie_val->raw_datalen);
01282 break;
01283 case AST_EVENT_IE_PLTYPE_EXISTS:
01284 case AST_EVENT_IE_PLTYPE_UNKNOWN:
01285 break;
01286 }
01287
01288
01289 if (!event) {
01290 return NULL;
01291 }
01292 }
01293
01294 if (has_ie && !ast_event_get_ie_raw(event, AST_EVENT_IE_EID)) {
01295
01296
01297 ast_event_append_eid(&event);
01298 }
01299
01300 return event;
01301 }
01302
01303 int ast_event_append_eid(struct ast_event **event)
01304 {
01305 return ast_event_append_ie_raw(event, AST_EVENT_IE_EID,
01306 &ast_eid_default, sizeof(ast_eid_default));
01307 }
01308
01309 void ast_event_destroy(struct ast_event *event)
01310 {
01311 ast_free(event);
01312 }
01313
01314 static void ast_event_ref_destroy(void *obj)
01315 {
01316 struct ast_event_ref *event_ref = obj;
01317
01318 ast_event_destroy(event_ref->event);
01319 }
01320
01321 static struct ast_event *ast_event_dup(const struct ast_event *event)
01322 {
01323 struct ast_event *dup_event;
01324 uint16_t event_len;
01325
01326 event_len = ast_event_get_size(event);
01327
01328 if (!(dup_event = ast_calloc(1, event_len))) {
01329 return NULL;
01330 }
01331
01332 memcpy(dup_event, event, event_len);
01333
01334 return dup_event;
01335 }
01336
01337 struct ast_event *ast_event_get_cached(enum ast_event_type type, ...)
01338 {
01339 va_list ap;
01340 enum ast_event_ie_type ie_type;
01341 struct ast_event *dup_event = NULL;
01342 struct ast_event_ref *cached_event_ref;
01343 struct ast_event *cache_arg_event;
01344 struct ast_event_ref tmp_event_ref = {
01345 .event = NULL,
01346 };
01347 struct ao2_container *container = NULL;
01348
01349 if (type >= AST_EVENT_TOTAL) {
01350 ast_log(LOG_ERROR, "%u is an invalid type!\n", type);
01351 return NULL;
01352 }
01353
01354 if (!(container = ast_event_cache[type].container)) {
01355 ast_log(LOG_ERROR, "%u is not a cached event type\n", type);
01356 return NULL;
01357 }
01358
01359 if (!(cache_arg_event = ast_event_new(type, AST_EVENT_IE_END))) {
01360 return NULL;
01361 }
01362
01363 va_start(ap, type);
01364 for (ie_type = va_arg(ap, enum ast_event_ie_type);
01365 ie_type != AST_EVENT_IE_END;
01366 ie_type = va_arg(ap, enum ast_event_ie_type))
01367 {
01368 enum ast_event_ie_pltype ie_pltype;
01369
01370 ie_pltype = va_arg(ap, enum ast_event_ie_pltype);
01371
01372 switch (ie_pltype) {
01373 case AST_EVENT_IE_PLTYPE_UINT:
01374 ast_event_append_ie_uint(&cache_arg_event, ie_type, va_arg(ap, uint32_t));
01375 break;
01376 case AST_EVENT_IE_PLTYPE_BITFLAGS:
01377 ast_event_append_ie_bitflags(&cache_arg_event, ie_type, va_arg(ap, uint32_t));
01378 break;
01379 case AST_EVENT_IE_PLTYPE_STR:
01380 ast_event_append_ie_str(&cache_arg_event, ie_type, va_arg(ap, const char *));
01381 break;
01382 case AST_EVENT_IE_PLTYPE_RAW:
01383 {
01384 void *data = va_arg(ap, void *);
01385 size_t datalen = va_arg(ap, size_t);
01386 ast_event_append_ie_raw(&cache_arg_event, ie_type, data, datalen);
01387 break;
01388 }
01389 case AST_EVENT_IE_PLTYPE_EXISTS:
01390 ast_log(LOG_WARNING, "PLTYPE_EXISTS not supported by this function\n");
01391 break;
01392 case AST_EVENT_IE_PLTYPE_UNKNOWN:
01393 break;
01394 }
01395 }
01396 va_end(ap);
01397
01398 tmp_event_ref.event = cache_arg_event;
01399
01400 cached_event_ref = ao2_find(container, &tmp_event_ref, OBJ_POINTER);
01401
01402 ast_event_destroy(cache_arg_event);
01403 cache_arg_event = NULL;
01404
01405 if (cached_event_ref) {
01406 dup_event = ast_event_dup(cached_event_ref->event);
01407 ao2_ref(cached_event_ref, -1);
01408 cached_event_ref = NULL;
01409 }
01410
01411 return dup_event;
01412 }
01413
01414 static struct ast_event_ref *alloc_event_ref(void)
01415 {
01416 return ao2_alloc(sizeof(struct ast_event_ref), ast_event_ref_destroy);
01417 }
01418
01419
01420
01421
01422
01423
01424
01425
01426
01427
01428
01429 static void event_update_cache(struct ao2_container *cache, struct ast_event *event)
01430 {
01431 struct ast_event_ref tmp_event_ref = {
01432 .event = event,
01433 };
01434 struct ast_event *dup_event;
01435 struct ast_event_ref *event_ref;
01436
01437
01438 ao2_lock(cache);
01439
01440
01441 ao2_callback(cache, OBJ_POINTER | OBJ_UNLINK | OBJ_MULTIPLE | OBJ_NODATA,
01442 ast_event_cmp, &tmp_event_ref);
01443
01444
01445 dup_event = ast_event_dup(event);
01446 if (dup_event) {
01447 event_ref = alloc_event_ref();
01448 if (event_ref) {
01449 event_ref->event = dup_event;
01450 ao2_link(cache, event_ref);
01451 ao2_ref(event_ref, -1);
01452 } else {
01453 ast_event_destroy(dup_event);
01454 }
01455 }
01456
01457 ao2_unlock(cache);
01458 }
01459
01460 int ast_event_queue_and_cache(struct ast_event *event)
01461 {
01462 struct ao2_container *container;
01463
01464 container = ast_event_cache[ast_event_get_type(event)].container;
01465 if (!container) {
01466 ast_log(LOG_WARNING, "cache requested for non-cached event type\n");
01467 } else {
01468 event_update_cache(container, event);
01469 }
01470
01471 if (ast_event_queue(event)) {
01472 ast_event_destroy(event);
01473 }
01474 return 0;
01475 }
01476
01477 static int handle_event(void *data)
01478 {
01479 struct ast_event_ref *event_ref = data;
01480 struct ast_event_sub *sub;
01481 const enum ast_event_type event_types[] = {
01482 ntohs(event_ref->event->type),
01483 AST_EVENT_ALL
01484 };
01485 int i;
01486
01487 for (i = 0; i < ARRAY_LEN(event_types); i++) {
01488 AST_RWDLLIST_RDLOCK(&ast_event_subs[event_types[i]]);
01489 AST_RWDLLIST_TRAVERSE(&ast_event_subs[event_types[i]], sub, entry) {
01490 struct ast_event_ie_val *ie_val;
01491
01492 AST_LIST_TRAVERSE(&sub->ie_vals, ie_val, entry) {
01493 if (!match_ie_val(event_ref->event, ie_val, NULL)) {
01494
01495 break;
01496 }
01497 }
01498 if (ie_val) {
01499
01500 continue;
01501 }
01502 sub->cb(event_ref->event, sub->userdata);
01503 }
01504 AST_RWDLLIST_UNLOCK(&ast_event_subs[event_types[i]]);
01505 }
01506
01507 ao2_ref(event_ref, -1);
01508
01509 return 0;
01510 }
01511
01512 int ast_event_queue(struct ast_event *event)
01513 {
01514 struct ast_event_ref *event_ref;
01515 uint16_t host_event_type;
01516 int res;
01517
01518 host_event_type = ntohs(event->type);
01519
01520
01521 if (host_event_type >= AST_EVENT_TOTAL) {
01522 ast_log(LOG_WARNING, "Someone tried to queue an event of invalid "
01523 "type '%d'!\n", host_event_type);
01524 return -1;
01525 }
01526
01527
01528 if (ast_event_check_subscriber(host_event_type, AST_EVENT_IE_END)
01529 == AST_EVENT_SUB_NONE) {
01530 ast_event_destroy(event);
01531 return 0;
01532 }
01533
01534 if (!(event_ref = alloc_event_ref())) {
01535 return -1;
01536 }
01537
01538 event_ref->event = event;
01539
01540 res = ast_taskprocessor_push(event_dispatcher, handle_event, event_ref);
01541 if (res) {
01542 event_ref->event = NULL;
01543 ao2_ref(event_ref, -1);
01544 }
01545 return res;
01546 }
01547
01548 static int ast_event_hash_mwi(const void *obj, const int flags)
01549 {
01550 const struct ast_event *event = obj;
01551 const char *mailbox = ast_event_get_ie_str(event, AST_EVENT_IE_MAILBOX);
01552 const char *context = ast_event_get_ie_str(event, AST_EVENT_IE_CONTEXT);
01553
01554 return ast_str_hash_add(context, ast_str_hash(mailbox));
01555 }
01556
01557
01558
01559
01560
01561
01562
01563
01564
01565
01566 static int ast_event_hash_devstate(const void *obj, const int flags)
01567 {
01568 const struct ast_event *event = obj;
01569
01570 return ast_str_hash(ast_event_get_ie_str(event, AST_EVENT_IE_DEVICE));
01571 }
01572
01573
01574
01575
01576
01577
01578
01579
01580
01581
01582 static int ast_event_hash_devstate_change(const void *obj, const int flags)
01583 {
01584 const struct ast_event *event = obj;
01585
01586 return ast_str_hash(ast_event_get_ie_str(event, AST_EVENT_IE_DEVICE));
01587 }
01588
01589 static int ast_event_hash(const void *obj, const int flags)
01590 {
01591 const struct ast_event_ref *event_ref;
01592 const struct ast_event *event;
01593 ao2_hash_fn *hash_fn;
01594
01595 event_ref = obj;
01596 event = event_ref->event;
01597
01598 if (!(hash_fn = ast_event_cache[ast_event_get_type(event)].hash_fn)) {
01599 return 0;
01600 }
01601
01602 return hash_fn(event, flags);
01603 }
01604
01605
01606
01607
01608
01609
01610
01611
01612
01613
01614
01615
01616
01617
01618
01619
01620
01621
01622
01623 static int ast_event_cmp(void *obj, void *arg, int flags)
01624 {
01625 struct ast_event_ref *event_ref, *event_ref2;
01626 struct ast_event *event, *event2;
01627 int res = CMP_MATCH;
01628 int i;
01629 enum ast_event_ie_type *cache_args;
01630
01631 event_ref = obj;
01632 event = event_ref->event;
01633
01634 event_ref2 = arg;
01635 event2 = event_ref2->event;
01636
01637 cache_args = ast_event_cache[ast_event_get_type(event)].cache_args;
01638
01639 for (i = 0; i < ARRAY_LEN(ast_event_cache[0].cache_args) && cache_args[i]; i++) {
01640 struct ast_event_ie_val ie_val = {
01641 .ie_pltype = ast_event_get_ie_pltype(cache_args[i]),
01642 .ie_type = cache_args[i],
01643 };
01644
01645 if (!match_ie_val(event, &ie_val, event2)) {
01646 res = 0;
01647 break;
01648 }
01649 }
01650
01651 return res;
01652 }
01653
01654 static void dump_raw_ie(struct ast_event_iterator *i, struct ast_cli_args *a)
01655 {
01656 char eid_buf[32];
01657 enum ast_event_ie_type ie_type;
01658 const char *ie_type_name;
01659
01660 ie_type = ast_event_iterator_get_ie_type(i);
01661 ie_type_name = ast_event_get_ie_type_name(ie_type);
01662
01663 switch (ie_type) {
01664 case AST_EVENT_IE_EID:
01665 ast_eid_to_str(eid_buf, sizeof(eid_buf), ast_event_iterator_get_ie_raw(i));
01666 ast_cli(a->fd, "%.30s: %s\n", ie_type_name, eid_buf);
01667 break;
01668 default:
01669 ast_cli(a->fd, "%s\n", ie_type_name);
01670 break;
01671 }
01672 }
01673
01674 static int event_dump_cli(void *obj, void *arg, int flags)
01675 {
01676 const struct ast_event_ref *event_ref = obj;
01677 const struct ast_event *event = event_ref->event;
01678 struct ast_cli_args *a = arg;
01679 struct ast_event_iterator i;
01680
01681 if (ast_event_iterator_init(&i, event)) {
01682 ast_cli(a->fd, "Failed to initialize event iterator. :-(\n");
01683 return 0;
01684 }
01685
01686 ast_cli(a->fd, "Event: %s\n", ast_event_get_type_name(event));
01687
01688 do {
01689 enum ast_event_ie_type ie_type;
01690 enum ast_event_ie_pltype ie_pltype;
01691 const char *ie_type_name;
01692
01693 ie_type = ast_event_iterator_get_ie_type(&i);
01694 ie_type_name = ast_event_get_ie_type_name(ie_type);
01695 ie_pltype = ast_event_get_ie_pltype(ie_type);
01696
01697 switch (ie_pltype) {
01698 case AST_EVENT_IE_PLTYPE_UNKNOWN:
01699 case AST_EVENT_IE_PLTYPE_EXISTS:
01700 ast_cli(a->fd, "%s\n", ie_type_name);
01701 break;
01702 case AST_EVENT_IE_PLTYPE_STR:
01703 ast_cli(a->fd, "%.30s: %s\n", ie_type_name,
01704 ast_event_iterator_get_ie_str(&i));
01705 break;
01706 case AST_EVENT_IE_PLTYPE_UINT:
01707 ast_cli(a->fd, "%.30s: %u\n", ie_type_name,
01708 ast_event_iterator_get_ie_uint(&i));
01709 break;
01710 case AST_EVENT_IE_PLTYPE_BITFLAGS:
01711 ast_cli(a->fd, "%.30s: %u\n", ie_type_name,
01712 ast_event_iterator_get_ie_bitflags(&i));
01713 break;
01714 case AST_EVENT_IE_PLTYPE_RAW:
01715 dump_raw_ie(&i, a);
01716 break;
01717 }
01718 } while (!ast_event_iterator_next(&i));
01719
01720 ast_cli(a->fd, "\n");
01721
01722 return 0;
01723 }
01724
01725 static char *event_dump_cache(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
01726 {
01727 enum ast_event_type event_type;
01728 enum ast_event_ie_type *cache_args;
01729 int i;
01730
01731 switch (cmd) {
01732 case CLI_INIT:
01733 e->command = "event dump cache";
01734 e->usage =
01735 "Usage: event dump cache <event type>\n"
01736 " Dump all of the cached events for the given event type.\n"
01737 " This is primarily intended for debugging.\n";
01738 return NULL;
01739 case CLI_GENERATE:
01740 if (a->pos == 3) {
01741 return ast_cli_complete(a->word, cached_event_types, a->n);
01742 }
01743 return NULL;
01744 case CLI_HANDLER:
01745 break;
01746 }
01747
01748 if (a->argc != e->args + 1) {
01749 return CLI_SHOWUSAGE;
01750 }
01751
01752 if (ast_event_str_to_event_type(a->argv[e->args], &event_type)) {
01753 ast_cli(a->fd, "Invalid cached event type: '%s'\n", a->argv[e->args]);
01754 return CLI_SHOWUSAGE;
01755 }
01756
01757 if (!ast_event_cache[event_type].container) {
01758 ast_cli(a->fd, "Event type '%s' has no cache.\n", a->argv[e->args]);
01759 return CLI_SUCCESS;
01760 }
01761
01762 ast_cli(a->fd, "Event Type: %s\n", a->argv[e->args]);
01763 ast_cli(a->fd, "Cache Unique Keys:\n");
01764 cache_args = ast_event_cache[event_type].cache_args;
01765 for (i = 0; i < ARRAY_LEN(ast_event_cache[0].cache_args) && cache_args[i]; i++) {
01766 ast_cli(a->fd, "--> %s\n", ast_event_get_ie_type_name(cache_args[i]));
01767 }
01768
01769 ast_cli(a->fd, "\n--- Begin Cache Dump ---\n\n");
01770 ao2_callback(ast_event_cache[event_type].container, OBJ_NODATA, event_dump_cli, a);
01771 ast_cli(a->fd, "--- End Cache Dump ---\n\n");
01772
01773 return CLI_SUCCESS;
01774 }
01775
01776 static struct ast_cli_entry event_cli[] = {
01777 AST_CLI_DEFINE(event_dump_cache, "Dump the internal event cache (for debugging)"),
01778 };
01779
01780 int ast_event_init(void)
01781 {
01782 int i;
01783
01784 for (i = 0; i < AST_EVENT_TOTAL; i++) {
01785 AST_RWDLLIST_HEAD_INIT(&ast_event_subs[i]);
01786 }
01787
01788 for (i = 0; i < AST_EVENT_TOTAL; i++) {
01789 if (!ast_event_cache[i].hash_fn) {
01790
01791 continue;
01792 }
01793
01794 if (!(ast_event_cache[i].container = ao2_container_alloc(NUM_CACHE_BUCKETS,
01795 ast_event_hash, ast_event_cmp))) {
01796 return -1;
01797 }
01798 }
01799
01800 if (!(event_dispatcher = ast_taskprocessor_get("core_event_dispatcher", 0))) {
01801 return -1;
01802 }
01803
01804 ast_cli_register_multiple(event_cli, ARRAY_LEN(event_cli));
01805
01806 return 0;
01807 }
01808
01809 size_t ast_event_minimum_length(void)
01810 {
01811 return sizeof(struct ast_event);
01812 }