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: 413586 $")
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 [AST_EVENT_IE_CACHABLE] = { AST_EVENT_IE_PLTYPE_UINT, "Cachable" },
00272 };
00273
00274 const char *ast_event_get_type_name(const struct ast_event *event)
00275 {
00276 enum ast_event_type type;
00277
00278 type = ast_event_get_type(event);
00279
00280 if (type < 0 || type >= ARRAY_LEN(event_names)) {
00281 ast_log(LOG_ERROR, "Invalid event type - '%u'\n", type);
00282 return "";
00283 }
00284
00285 return event_names[type];
00286 }
00287
00288 int ast_event_str_to_event_type(const char *str, enum ast_event_type *event_type)
00289 {
00290 int i;
00291
00292 for (i = 0; i < ARRAY_LEN(event_names); i++) {
00293 if (ast_strlen_zero(event_names[i]) || strcasecmp(event_names[i], str)) {
00294 continue;
00295 }
00296
00297 *event_type = i;
00298 return 0;
00299 }
00300
00301 return -1;
00302 }
00303
00304 const char *ast_event_get_ie_type_name(enum ast_event_ie_type ie_type)
00305 {
00306 if (ie_type <= 0 || ie_type >= ARRAY_LEN(ie_maps)) {
00307 ast_log(LOG_ERROR, "Invalid IE type - '%d'\n", ie_type);
00308 return "";
00309 }
00310
00311 return ie_maps[ie_type].name;
00312 }
00313
00314 enum ast_event_ie_pltype ast_event_get_ie_pltype(enum ast_event_ie_type ie_type)
00315 {
00316 if (ie_type <= 0 || ie_type >= ARRAY_LEN(ie_maps)) {
00317 ast_log(LOG_ERROR, "Invalid IE type - '%d'\n", ie_type);
00318 return AST_EVENT_IE_PLTYPE_UNKNOWN;
00319 }
00320
00321 return ie_maps[ie_type].ie_pltype;
00322 }
00323
00324 int ast_event_str_to_ie_type(const char *str, enum ast_event_ie_type *ie_type)
00325 {
00326 int i;
00327
00328 for (i = 0; i < ARRAY_LEN(ie_maps); i++) {
00329 if (strcasecmp(ie_maps[i].name, str)) {
00330 continue;
00331 }
00332
00333 *ie_type = i;
00334 return 0;
00335 }
00336
00337 return -1;
00338 }
00339
00340 size_t ast_event_get_size(const struct ast_event *event)
00341 {
00342 size_t res;
00343
00344 res = ntohs(event->event_len);
00345
00346 return res;
00347 }
00348
00349 static void ast_event_ie_val_destroy(struct ast_event_ie_val *ie_val)
00350 {
00351 switch (ie_val->ie_pltype) {
00352 case AST_EVENT_IE_PLTYPE_STR:
00353 ast_free((char *) ie_val->payload.str);
00354 break;
00355 case AST_EVENT_IE_PLTYPE_RAW:
00356 ast_free(ie_val->payload.raw);
00357 break;
00358 case AST_EVENT_IE_PLTYPE_UINT:
00359 case AST_EVENT_IE_PLTYPE_BITFLAGS:
00360 case AST_EVENT_IE_PLTYPE_EXISTS:
00361 case AST_EVENT_IE_PLTYPE_UNKNOWN:
00362 break;
00363 }
00364
00365 ast_free(ie_val);
00366 }
00367
00368
00369 struct ast_ev_check_list {
00370 AST_LIST_HEAD_NOLOCK(, ast_event_ie_val) ie_vals;
00371 };
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383 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)
00384 {
00385 const struct ast_event_ie_val *event_ie_val;
00386 int res = 0;
00387
00388 AST_LIST_TRAVERSE(&check_ie_vals->ie_vals, event_ie_val, entry) {
00389 if (sub_ie_val->ie_type == event_ie_val->ie_type) {
00390 break;
00391 }
00392 }
00393 if (!event_ie_val) {
00394
00395 return 0;
00396 }
00397
00398 if (sub_ie_val->ie_pltype != event_ie_val->ie_pltype) {
00399 if (sub_ie_val->ie_pltype == AST_EVENT_IE_PLTYPE_EXISTS) {
00400
00401 return 1;
00402 }
00403
00404 return 0;
00405 }
00406
00407 switch (sub_ie_val->ie_pltype) {
00408 case AST_EVENT_IE_PLTYPE_UINT:
00409 res = (sub_ie_val->payload.uint == event_ie_val->payload.uint);
00410 break;
00411 case AST_EVENT_IE_PLTYPE_BITFLAGS:
00412
00413
00414
00415
00416 res = (sub_ie_val->payload.uint & event_ie_val->payload.uint);
00417 break;
00418 case AST_EVENT_IE_PLTYPE_STR:
00419 {
00420 const char *substr = sub_ie_val->payload.str;
00421 const char *estr = event_ie_val->payload.str;
00422 if (sub_ie_val->ie_type == AST_EVENT_IE_DEVICE) {
00423 substr = ast_tech_to_upper(ast_strdupa(substr));
00424 estr = ast_tech_to_upper(ast_strdupa(estr));
00425 }
00426 res = !strcmp(substr, estr);
00427 break;
00428 }
00429 case AST_EVENT_IE_PLTYPE_RAW:
00430 res = (sub_ie_val->raw_datalen == event_ie_val->raw_datalen
00431 && !memcmp(sub_ie_val->payload.raw, event_ie_val->payload.raw,
00432 sub_ie_val->raw_datalen));
00433 break;
00434 case AST_EVENT_IE_PLTYPE_EXISTS:
00435
00436 break;
00437 case AST_EVENT_IE_PLTYPE_UNKNOWN:
00438
00439
00440
00441
00442 break;
00443 }
00444
00445 return res;
00446 }
00447
00448 enum ast_event_subscriber_res ast_event_check_subscriber(enum ast_event_type type, ...)
00449 {
00450 va_list ap;
00451 enum ast_event_ie_type ie_type;
00452 enum ast_event_subscriber_res res = AST_EVENT_SUB_NONE;
00453 struct ast_event_ie_val *ie_val;
00454 struct ast_event_sub *sub;
00455 struct ast_ev_check_list check_ie_vals = {
00456 .ie_vals = AST_LIST_HEAD_NOLOCK_INIT_VALUE
00457 };
00458 const enum ast_event_type event_types[] = { type, AST_EVENT_ALL };
00459 int i;
00460 int want_specific_event;
00461
00462 if (type >= AST_EVENT_TOTAL) {
00463 ast_log(LOG_ERROR, "%u is an invalid type!\n", type);
00464 return res;
00465 }
00466
00467 want_specific_event = 0;
00468 va_start(ap, type);
00469 for (ie_type = va_arg(ap, enum ast_event_ie_type);
00470 ie_type != AST_EVENT_IE_END;
00471 ie_type = va_arg(ap, enum ast_event_ie_type))
00472 {
00473 struct ast_event_ie_val *ie_value = ast_alloca(sizeof(*ie_value));
00474 int insert = 0;
00475
00476 memset(ie_value, 0, sizeof(*ie_value));
00477 ie_value->ie_type = ie_type;
00478 ie_value->ie_pltype = va_arg(ap, enum ast_event_ie_pltype);
00479 switch (ie_value->ie_pltype) {
00480 case AST_EVENT_IE_PLTYPE_UINT:
00481 ie_value->payload.uint = va_arg(ap, uint32_t);
00482 insert = 1;
00483 break;
00484 case AST_EVENT_IE_PLTYPE_BITFLAGS:
00485 ie_value->payload.uint = va_arg(ap, uint32_t);
00486 insert = 1;
00487 break;
00488 case AST_EVENT_IE_PLTYPE_STR:
00489 ie_value->payload.str = va_arg(ap, const char *);
00490 insert = 1;
00491 break;
00492 case AST_EVENT_IE_PLTYPE_RAW:
00493 {
00494 void *data = va_arg(ap, void *);
00495 size_t datalen = va_arg(ap, size_t);
00496
00497 ie_value->payload.raw = ast_alloca(datalen);
00498 memcpy(ie_value->payload.raw, data, datalen);
00499 ie_value->raw_datalen = datalen;
00500 insert = 1;
00501 break;
00502 }
00503 case AST_EVENT_IE_PLTYPE_UNKNOWN:
00504 case AST_EVENT_IE_PLTYPE_EXISTS:
00505
00506 break;
00507 }
00508
00509 if (insert) {
00510 want_specific_event = 1;
00511 AST_LIST_INSERT_TAIL(&check_ie_vals.ie_vals, ie_value, entry);
00512 } else {
00513 ast_log(LOG_WARNING, "Unsupported PLTYPE(%d)\n", ie_value->ie_pltype);
00514 }
00515 }
00516 va_end(ap);
00517
00518 for (i = 0; i < ARRAY_LEN(event_types); i++) {
00519 AST_RWDLLIST_RDLOCK(&ast_event_subs[event_types[i]]);
00520 if (want_specific_event) {
00521 AST_RWDLLIST_TRAVERSE(&ast_event_subs[event_types[i]], sub, entry) {
00522 AST_LIST_TRAVERSE(&sub->ie_vals, ie_val, entry) {
00523 if (!match_sub_ie_val_to_event(ie_val, &check_ie_vals)) {
00524
00525 break;
00526 }
00527 }
00528 if (!ie_val) {
00529
00530 break;
00531 }
00532 }
00533 } else {
00534
00535 sub = AST_RWLIST_FIRST(&ast_event_subs[event_types[i]]);
00536 }
00537 AST_RWDLLIST_UNLOCK(&ast_event_subs[event_types[i]]);
00538 if (sub) {
00539 break;
00540 }
00541 }
00542
00543 return sub ? AST_EVENT_SUB_EXISTS : AST_EVENT_SUB_NONE;
00544 }
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559 static int match_ie_val(const struct ast_event *event,
00560 const struct ast_event_ie_val *ie_val, const struct ast_event *event2)
00561 {
00562 switch (ie_val->ie_pltype) {
00563 case AST_EVENT_IE_PLTYPE_UINT:
00564 {
00565 uint32_t val = event2 ? ast_event_get_ie_uint(event2, ie_val->ie_type) : ie_val->payload.uint;
00566
00567 return (val == ast_event_get_ie_uint(event, ie_val->ie_type)) ? 1 : 0;
00568 }
00569
00570 case AST_EVENT_IE_PLTYPE_BITFLAGS:
00571 {
00572 uint32_t flags = event2 ? ast_event_get_ie_uint(event2, ie_val->ie_type) : ie_val->payload.uint;
00573
00574
00575
00576
00577
00578 return (flags & ast_event_get_ie_bitflags(event, ie_val->ie_type)) ? 1 : 0;
00579 }
00580
00581 case AST_EVENT_IE_PLTYPE_STR:
00582 {
00583 const char *str;
00584 uint32_t hash;
00585
00586 hash = event2 ? ast_event_get_ie_str_hash(event2, ie_val->ie_type) : ie_val->payload.hash;
00587 if (hash != ast_event_get_ie_str_hash(event, ie_val->ie_type)) {
00588 return 0;
00589 }
00590
00591 str = event2 ? ast_event_get_ie_str(event2, ie_val->ie_type) : ie_val->payload.str;
00592 if (str) {
00593 const char *e1str, *e2str;
00594 e1str = ast_event_get_ie_str(event, ie_val->ie_type);
00595 e2str = str;
00596
00597 if (ie_val->ie_type == AST_EVENT_IE_DEVICE) {
00598 e1str = ast_tech_to_upper(ast_strdupa(e1str));
00599 e2str = ast_tech_to_upper(ast_strdupa(e2str));
00600 }
00601
00602 if (!strcmp(e1str, e2str)) {
00603 return 1;
00604 }
00605 }
00606
00607 return 0;
00608 }
00609
00610 case AST_EVENT_IE_PLTYPE_RAW:
00611 {
00612 const void *buf = event2 ? ast_event_get_ie_raw(event2, ie_val->ie_type) : ie_val->payload.raw;
00613 uint16_t ie_payload_len = event2 ? ast_event_get_ie_raw_payload_len(event2, ie_val->ie_type) : ie_val->raw_datalen;
00614
00615 return (buf
00616 && ie_payload_len == ast_event_get_ie_raw_payload_len(event, ie_val->ie_type)
00617 && !memcmp(buf, ast_event_get_ie_raw(event, ie_val->ie_type), ie_payload_len)) ? 1 : 0;
00618 }
00619
00620 case AST_EVENT_IE_PLTYPE_EXISTS:
00621 {
00622 return ast_event_get_ie_raw(event, ie_val->ie_type) ? 1 : 0;
00623 }
00624
00625 case AST_EVENT_IE_PLTYPE_UNKNOWN:
00626 return 0;
00627 }
00628
00629 return 0;
00630 }
00631
00632 static int dump_cache_cb(void *obj, void *arg, int flags)
00633 {
00634 const struct ast_event_ref *event_ref = obj;
00635 const struct ast_event *event = event_ref->event;
00636 const struct ast_event_sub *event_sub = arg;
00637 struct ast_event_ie_val *ie_val = NULL;
00638
00639 AST_LIST_TRAVERSE(&event_sub->ie_vals, ie_val, entry) {
00640 if (!match_ie_val(event, ie_val, NULL)) {
00641 break;
00642 }
00643 }
00644
00645 if (!ie_val) {
00646
00647 event_sub->cb(event, event_sub->userdata);
00648 }
00649
00650 return 0;
00651 }
00652
00653
00654 void ast_event_dump_cache(const struct ast_event_sub *event_sub)
00655 {
00656 ao2_callback(ast_event_cache[event_sub->type].container, OBJ_NODATA,
00657 dump_cache_cb, (void *) event_sub);
00658 }
00659
00660 static struct ast_event *gen_sub_event(struct ast_event_sub *sub)
00661 {
00662 struct ast_event_ie_val *ie_val;
00663 struct ast_event *event;
00664
00665 event = ast_event_new(AST_EVENT_SUB,
00666 AST_EVENT_IE_UNIQUEID, AST_EVENT_IE_PLTYPE_UINT, sub->uniqueid,
00667 AST_EVENT_IE_EVENTTYPE, AST_EVENT_IE_PLTYPE_UINT, sub->type,
00668 AST_EVENT_IE_DESCRIPTION, AST_EVENT_IE_PLTYPE_STR, sub->description,
00669 AST_EVENT_IE_END);
00670 if (!event)
00671 return NULL;
00672
00673 AST_LIST_TRAVERSE(&sub->ie_vals, ie_val, entry) {
00674 switch (ie_val->ie_pltype) {
00675 case AST_EVENT_IE_PLTYPE_UNKNOWN:
00676 break;
00677 case AST_EVENT_IE_PLTYPE_EXISTS:
00678 ast_event_append_ie_uint(&event, AST_EVENT_IE_EXISTS, ie_val->ie_type);
00679 break;
00680 case AST_EVENT_IE_PLTYPE_UINT:
00681 ast_event_append_ie_uint(&event, ie_val->ie_type, ie_val->payload.uint);
00682 break;
00683 case AST_EVENT_IE_PLTYPE_BITFLAGS:
00684 ast_event_append_ie_bitflags(&event, ie_val->ie_type, ie_val->payload.uint);
00685 break;
00686 case AST_EVENT_IE_PLTYPE_STR:
00687 ast_event_append_ie_str(&event, ie_val->ie_type, ie_val->payload.str);
00688 break;
00689 case AST_EVENT_IE_PLTYPE_RAW:
00690 ast_event_append_ie_raw(&event, ie_val->ie_type, ie_val->payload.raw, ie_val->raw_datalen);
00691 break;
00692 }
00693 if (!event)
00694 break;
00695 }
00696
00697 return event;
00698 }
00699
00700
00701 void ast_event_report_subs(const struct ast_event_sub *event_sub)
00702 {
00703 struct ast_event *event;
00704 struct ast_event_sub *sub;
00705 enum ast_event_type event_type = -1;
00706 struct ast_event_ie_val *ie_val;
00707
00708 if (event_sub->type != AST_EVENT_SUB)
00709 return;
00710
00711 AST_LIST_TRAVERSE(&event_sub->ie_vals, ie_val, entry) {
00712 if (ie_val->ie_type == AST_EVENT_IE_EVENTTYPE) {
00713 event_type = ie_val->payload.uint;
00714 break;
00715 }
00716 }
00717
00718 if (event_type == -1)
00719 return;
00720
00721 AST_RWDLLIST_RDLOCK(&ast_event_subs[event_type]);
00722 AST_RWDLLIST_TRAVERSE(&ast_event_subs[event_type], sub, entry) {
00723 if (event_sub == sub) {
00724 continue;
00725 }
00726
00727 event = gen_sub_event(sub);
00728 if (!event) {
00729 continue;
00730 }
00731
00732 event_sub->cb(event, event_sub->userdata);
00733
00734 ast_event_destroy(event);
00735 }
00736 AST_RWDLLIST_UNLOCK(&ast_event_subs[event_type]);
00737 }
00738
00739 struct ast_event_sub *ast_event_subscribe_new(enum ast_event_type type,
00740 ast_event_cb_t cb, void *userdata)
00741 {
00742 struct ast_event_sub *sub;
00743
00744 if (type < 0 || type >= AST_EVENT_TOTAL) {
00745 ast_log(LOG_ERROR, "%u is an invalid type!\n", type);
00746 return NULL;
00747 }
00748
00749 if (!(sub = ast_calloc(1, sizeof(*sub)))) {
00750 return NULL;
00751 }
00752
00753 sub->type = type;
00754 sub->cb = cb;
00755 sub->userdata = userdata;
00756 sub->uniqueid = ast_atomic_fetchadd_int((int *) &sub_uniqueid, 1);
00757
00758 return sub;
00759 }
00760
00761 int ast_event_sub_append_ie_uint(struct ast_event_sub *sub,
00762 enum ast_event_ie_type ie_type, uint32_t unsigned_int)
00763 {
00764 struct ast_event_ie_val *ie_val;
00765
00766 if (ie_type <= 0 || ie_type >= AST_EVENT_IE_TOTAL) {
00767 return -1;
00768 }
00769
00770 if (!(ie_val = ast_calloc(1, sizeof(*ie_val)))) {
00771 return -1;
00772 }
00773
00774 ie_val->ie_type = ie_type;
00775 ie_val->payload.uint = unsigned_int;
00776 ie_val->ie_pltype = AST_EVENT_IE_PLTYPE_UINT;
00777
00778 AST_LIST_INSERT_TAIL(&sub->ie_vals, ie_val, entry);
00779
00780 return 0;
00781 }
00782
00783 int ast_event_sub_append_ie_bitflags(struct ast_event_sub *sub,
00784 enum ast_event_ie_type ie_type, uint32_t flags)
00785 {
00786 struct ast_event_ie_val *ie_val;
00787
00788 if (ie_type <= 0 || ie_type >= AST_EVENT_IE_TOTAL) {
00789 return -1;
00790 }
00791
00792 if (!(ie_val = ast_calloc(1, sizeof(*ie_val)))) {
00793 return -1;
00794 }
00795
00796 ie_val->ie_type = ie_type;
00797 ie_val->payload.uint = flags;
00798 ie_val->ie_pltype = AST_EVENT_IE_PLTYPE_BITFLAGS;
00799
00800 AST_LIST_INSERT_TAIL(&sub->ie_vals, ie_val, entry);
00801
00802 return 0;
00803 }
00804
00805 int ast_event_sub_append_ie_exists(struct ast_event_sub *sub,
00806 enum ast_event_ie_type ie_type)
00807 {
00808 struct ast_event_ie_val *ie_val;
00809
00810 if (ie_type <= 0 || ie_type >= AST_EVENT_IE_TOTAL) {
00811 return -1;
00812 }
00813
00814 if (!(ie_val = ast_calloc(1, sizeof(*ie_val)))) {
00815 return -1;
00816 }
00817
00818 ie_val->ie_type = ie_type;
00819 ie_val->ie_pltype = AST_EVENT_IE_PLTYPE_EXISTS;
00820
00821 AST_LIST_INSERT_TAIL(&sub->ie_vals, ie_val, entry);
00822
00823 return 0;
00824 }
00825
00826 int ast_event_sub_append_ie_str(struct ast_event_sub *sub,
00827 enum ast_event_ie_type ie_type, const char *str)
00828 {
00829 struct ast_event_ie_val *ie_val;
00830
00831 if (ie_type <= 0 || ie_type >= AST_EVENT_IE_TOTAL) {
00832 return -1;
00833 }
00834
00835 if (!(ie_val = ast_calloc(1, sizeof(*ie_val)))) {
00836 return -1;
00837 }
00838
00839 ie_val->ie_type = ie_type;
00840 ie_val->ie_pltype = AST_EVENT_IE_PLTYPE_STR;
00841
00842 if (!(ie_val->payload.str = ast_strdup(str))) {
00843 ast_free(ie_val);
00844 return -1;
00845 }
00846
00847 if (ie_type == AST_EVENT_IE_DEVICE) {
00848 char *uppertech = ast_strdupa(str);
00849 ast_tech_to_upper(uppertech);
00850 ie_val->payload.hash = ast_str_hash(uppertech);
00851 } else {
00852 ie_val->payload.hash = ast_str_hash(str);
00853 }
00854
00855 AST_LIST_INSERT_TAIL(&sub->ie_vals, ie_val, entry);
00856
00857 return 0;
00858 }
00859
00860 int ast_event_sub_append_ie_raw(struct ast_event_sub *sub,
00861 enum ast_event_ie_type ie_type, void *data, size_t raw_datalen)
00862 {
00863 struct ast_event_ie_val *ie_val;
00864
00865 if (ie_type <= 0 || ie_type >= AST_EVENT_IE_TOTAL) {
00866 return -1;
00867 }
00868
00869 if (!(ie_val = ast_calloc(1, sizeof(*ie_val)))) {
00870 return -1;
00871 }
00872
00873 ie_val->ie_type = ie_type;
00874 ie_val->ie_pltype = AST_EVENT_IE_PLTYPE_RAW;
00875 ie_val->raw_datalen = raw_datalen;
00876
00877 if (!(ie_val->payload.raw = ast_malloc(raw_datalen))) {
00878 ast_free(ie_val);
00879 return -1;
00880 }
00881
00882 memcpy(ie_val->payload.raw, data, raw_datalen);
00883
00884 AST_LIST_INSERT_TAIL(&sub->ie_vals, ie_val, entry);
00885
00886 return 0;
00887 }
00888
00889 int ast_event_sub_activate(struct ast_event_sub *sub)
00890 {
00891 if (ast_event_check_subscriber(AST_EVENT_SUB,
00892 AST_EVENT_IE_EVENTTYPE, AST_EVENT_IE_PLTYPE_UINT, sub->type,
00893 AST_EVENT_IE_END) != AST_EVENT_SUB_NONE) {
00894 struct ast_event *event;
00895
00896 event = gen_sub_event(sub);
00897 if (event && ast_event_queue(event)) {
00898 ast_event_destroy(event);
00899 }
00900 }
00901
00902 AST_RWDLLIST_WRLOCK(&ast_event_subs[sub->type]);
00903 AST_RWDLLIST_INSERT_TAIL(&ast_event_subs[sub->type], sub, entry);
00904 AST_RWDLLIST_UNLOCK(&ast_event_subs[sub->type]);
00905
00906 return 0;
00907 }
00908
00909 struct ast_event_sub *ast_event_subscribe(enum ast_event_type type, ast_event_cb_t cb,
00910 const char *description, void *userdata, ...)
00911 {
00912 va_list ap;
00913 enum ast_event_ie_type ie_type;
00914 struct ast_event_sub *sub;
00915
00916 if (!(sub = ast_event_subscribe_new(type, cb, userdata))) {
00917 return NULL;
00918 }
00919
00920 ast_copy_string(sub->description, description, sizeof(sub->description));
00921
00922 va_start(ap, userdata);
00923 for (ie_type = va_arg(ap, enum ast_event_ie_type);
00924 ie_type != AST_EVENT_IE_END;
00925 ie_type = va_arg(ap, enum ast_event_ie_type))
00926 {
00927 enum ast_event_ie_pltype ie_pltype;
00928
00929 ie_pltype = va_arg(ap, enum ast_event_ie_pltype);
00930
00931 switch (ie_pltype) {
00932 case AST_EVENT_IE_PLTYPE_UNKNOWN:
00933 break;
00934 case AST_EVENT_IE_PLTYPE_UINT:
00935 {
00936 uint32_t unsigned_int = va_arg(ap, uint32_t);
00937 ast_event_sub_append_ie_uint(sub, ie_type, unsigned_int);
00938 break;
00939 }
00940 case AST_EVENT_IE_PLTYPE_BITFLAGS:
00941 {
00942 uint32_t unsigned_int = va_arg(ap, uint32_t);
00943 ast_event_sub_append_ie_bitflags(sub, ie_type, unsigned_int);
00944 break;
00945 }
00946 case AST_EVENT_IE_PLTYPE_STR:
00947 {
00948 const char *str = va_arg(ap, const char *);
00949 ast_event_sub_append_ie_str(sub, ie_type, str);
00950 break;
00951 }
00952 case AST_EVENT_IE_PLTYPE_RAW:
00953 {
00954 void *data = va_arg(ap, void *);
00955 size_t data_len = va_arg(ap, size_t);
00956 ast_event_sub_append_ie_raw(sub, ie_type, data, data_len);
00957 break;
00958 }
00959 case AST_EVENT_IE_PLTYPE_EXISTS:
00960 ast_event_sub_append_ie_exists(sub, ie_type);
00961 break;
00962 }
00963 }
00964 va_end(ap);
00965
00966 ast_event_sub_activate(sub);
00967
00968 return sub;
00969 }
00970
00971 void ast_event_sub_destroy(struct ast_event_sub *sub)
00972 {
00973 struct ast_event_ie_val *ie_val;
00974
00975 while ((ie_val = AST_LIST_REMOVE_HEAD(&sub->ie_vals, entry))) {
00976 ast_event_ie_val_destroy(ie_val);
00977 }
00978
00979 ast_free(sub);
00980 }
00981
00982 const char *ast_event_subscriber_get_description(struct ast_event_sub *sub)
00983 {
00984 return sub ? sub->description : NULL;
00985 }
00986
00987 struct ast_event_sub *ast_event_unsubscribe(struct ast_event_sub *sub)
00988 {
00989 struct ast_event *event;
00990
00991 AST_RWDLLIST_WRLOCK(&ast_event_subs[sub->type]);
00992 AST_DLLIST_REMOVE(&ast_event_subs[sub->type], sub, entry);
00993 AST_RWDLLIST_UNLOCK(&ast_event_subs[sub->type]);
00994
00995 if (ast_event_check_subscriber(AST_EVENT_UNSUB,
00996 AST_EVENT_IE_EVENTTYPE, AST_EVENT_IE_PLTYPE_UINT, sub->type,
00997 AST_EVENT_IE_END) != AST_EVENT_SUB_NONE) {
00998
00999 event = ast_event_new(AST_EVENT_UNSUB,
01000 AST_EVENT_IE_UNIQUEID, AST_EVENT_IE_PLTYPE_UINT, sub->uniqueid,
01001 AST_EVENT_IE_EVENTTYPE, AST_EVENT_IE_PLTYPE_UINT, sub->type,
01002 AST_EVENT_IE_DESCRIPTION, AST_EVENT_IE_PLTYPE_STR, sub->description,
01003 AST_EVENT_IE_END);
01004 if (event && ast_event_queue(event)) {
01005 ast_event_destroy(event);
01006 }
01007 }
01008
01009 ast_event_sub_destroy(sub);
01010
01011 return NULL;
01012 }
01013
01014 int ast_event_iterator_init(struct ast_event_iterator *iterator, const struct ast_event *event)
01015 {
01016 int res = 0;
01017
01018 iterator->event_len = ast_event_get_size(event);
01019 iterator->event = event;
01020 if (iterator->event_len >= sizeof(*event) + sizeof(struct ast_event_ie)) {
01021 iterator->ie = (struct ast_event_ie *) ( ((char *) event) + sizeof(*event) );
01022 } else {
01023 iterator->ie = NULL;
01024 res = -1;
01025 }
01026
01027 return res;
01028 }
01029
01030 int ast_event_iterator_next(struct ast_event_iterator *iterator)
01031 {
01032 iterator->ie = (struct ast_event_ie *) ( ((char *) iterator->ie) + sizeof(*iterator->ie) + ntohs(iterator->ie->ie_payload_len));
01033 return ((iterator->event_len <= (((char *) iterator->ie) - ((char *) iterator->event))) ? -1 : 0);
01034 }
01035
01036 enum ast_event_ie_type ast_event_iterator_get_ie_type(struct ast_event_iterator *iterator)
01037 {
01038 return ntohs(iterator->ie->ie_type);
01039 }
01040
01041 uint32_t ast_event_iterator_get_ie_uint(struct ast_event_iterator *iterator)
01042 {
01043 return ntohl(get_unaligned_uint32(iterator->ie->ie_payload));
01044 }
01045
01046 uint32_t ast_event_iterator_get_ie_bitflags(struct ast_event_iterator *iterator)
01047 {
01048 return ntohl(get_unaligned_uint32(iterator->ie->ie_payload));
01049 }
01050
01051 const char *ast_event_iterator_get_ie_str(struct ast_event_iterator *iterator)
01052 {
01053 const struct ast_event_ie_str_payload *str_payload;
01054
01055 str_payload = (struct ast_event_ie_str_payload *) iterator->ie->ie_payload;
01056
01057 return str_payload ? str_payload->str : NULL;
01058 }
01059
01060 void *ast_event_iterator_get_ie_raw(struct ast_event_iterator *iterator)
01061 {
01062 return iterator->ie->ie_payload;
01063 }
01064
01065 uint16_t ast_event_iterator_get_ie_raw_payload_len(struct ast_event_iterator *iterator)
01066 {
01067 return ntohs(iterator->ie->ie_payload_len);
01068 }
01069
01070 enum ast_event_type ast_event_get_type(const struct ast_event *event)
01071 {
01072 return ntohs(event->type);
01073 }
01074
01075 uint32_t ast_event_get_ie_uint(const struct ast_event *event, enum ast_event_ie_type ie_type)
01076 {
01077 const uint32_t *ie_val;
01078
01079 ie_val = ast_event_get_ie_raw(event, ie_type);
01080
01081 return ie_val ? ntohl(get_unaligned_uint32(ie_val)) : 0;
01082 }
01083
01084 uint32_t ast_event_get_ie_bitflags(const struct ast_event *event, enum ast_event_ie_type ie_type)
01085 {
01086 const uint32_t *ie_val;
01087
01088 ie_val = ast_event_get_ie_raw(event, ie_type);
01089
01090 return ie_val ? ntohl(get_unaligned_uint32(ie_val)) : 0;
01091 }
01092
01093 uint32_t ast_event_get_ie_str_hash(const struct ast_event *event, enum ast_event_ie_type ie_type)
01094 {
01095 const struct ast_event_ie_str_payload *str_payload;
01096
01097 str_payload = ast_event_get_ie_raw(event, ie_type);
01098
01099 return str_payload ? str_payload->hash : 0;
01100 }
01101
01102 const char *ast_event_get_ie_str(const struct ast_event *event, enum ast_event_ie_type ie_type)
01103 {
01104 const struct ast_event_ie_str_payload *str_payload;
01105
01106 str_payload = ast_event_get_ie_raw(event, ie_type);
01107
01108 return str_payload ? str_payload->str : NULL;
01109 }
01110
01111 const void *ast_event_get_ie_raw(const struct ast_event *event, enum ast_event_ie_type ie_type)
01112 {
01113 struct ast_event_iterator iterator;
01114 int res;
01115
01116 for (res = ast_event_iterator_init(&iterator, event); !res; res = ast_event_iterator_next(&iterator)) {
01117 if (ast_event_iterator_get_ie_type(&iterator) == ie_type) {
01118 return ast_event_iterator_get_ie_raw(&iterator);
01119 }
01120 }
01121
01122 return NULL;
01123 }
01124
01125 uint16_t ast_event_get_ie_raw_payload_len(const struct ast_event *event, enum ast_event_ie_type ie_type)
01126 {
01127 struct ast_event_iterator iterator;
01128 int res;
01129
01130 for (res = ast_event_iterator_init(&iterator, event); !res; res = ast_event_iterator_next(&iterator)) {
01131 if (ast_event_iterator_get_ie_type(&iterator) == ie_type) {
01132 return ast_event_iterator_get_ie_raw_payload_len(&iterator);
01133 }
01134 }
01135
01136 return 0;
01137 }
01138
01139 int ast_event_append_ie_str(struct ast_event **event, enum ast_event_ie_type ie_type,
01140 const char *str)
01141 {
01142 struct ast_event_ie_str_payload *str_payload;
01143 size_t payload_len;
01144
01145 payload_len = sizeof(*str_payload) + strlen(str);
01146 str_payload = ast_alloca(payload_len);
01147
01148 strcpy(str_payload->str, str);
01149 if (ie_type == AST_EVENT_IE_DEVICE) {
01150 char *uppertech = ast_strdupa(str);
01151 ast_tech_to_upper(uppertech);
01152 str_payload->hash = ast_str_hash(uppertech);
01153 } else {
01154 str_payload->hash = ast_str_hash(str);
01155 }
01156
01157 return ast_event_append_ie_raw(event, ie_type, str_payload, payload_len);
01158 }
01159
01160 int ast_event_append_ie_uint(struct ast_event **event, enum ast_event_ie_type ie_type,
01161 uint32_t data)
01162 {
01163 data = htonl(data);
01164 return ast_event_append_ie_raw(event, ie_type, &data, sizeof(data));
01165 }
01166
01167 int ast_event_append_ie_bitflags(struct ast_event **event, enum ast_event_ie_type ie_type,
01168 uint32_t flags)
01169 {
01170 flags = htonl(flags);
01171 return ast_event_append_ie_raw(event, ie_type, &flags, sizeof(flags));
01172 }
01173
01174 int ast_event_append_ie_raw(struct ast_event **event, enum ast_event_ie_type ie_type,
01175 const void *data, size_t data_len)
01176 {
01177 struct ast_event_ie *ie;
01178 struct ast_event *old_event;
01179 unsigned int extra_len;
01180 uint16_t event_len;
01181
01182 event_len = ntohs((*event)->event_len);
01183 extra_len = sizeof(*ie) + data_len;
01184
01185 old_event = *event;
01186 *event = ast_realloc(*event, event_len + extra_len);
01187 if (!*event) {
01188 ast_free(old_event);
01189 return -1;
01190 }
01191
01192 ie = (struct ast_event_ie *) ( ((char *) *event) + event_len );
01193 ie->ie_type = htons(ie_type);
01194 ie->ie_payload_len = htons(data_len);
01195 memcpy(ie->ie_payload, data, data_len);
01196
01197 (*event)->event_len = htons(event_len + extra_len);
01198
01199 return 0;
01200 }
01201
01202 struct ast_event *ast_event_new(enum ast_event_type type, ...)
01203 {
01204 va_list ap;
01205 struct ast_event *event;
01206 enum ast_event_ie_type ie_type;
01207 struct ast_event_ie_val *ie_val;
01208 int has_ie = 0;
01209 AST_LIST_HEAD_NOLOCK_STATIC(ie_vals, ast_event_ie_val);
01210
01211
01212 if (type >= AST_EVENT_TOTAL) {
01213 ast_log(LOG_WARNING, "Someone tried to create an event of invalid "
01214 "type '%u'!\n", type);
01215 return NULL;
01216 }
01217
01218 va_start(ap, type);
01219 for (ie_type = va_arg(ap, enum ast_event_ie_type);
01220 ie_type != AST_EVENT_IE_END;
01221 ie_type = va_arg(ap, enum ast_event_ie_type))
01222 {
01223 struct ast_event_ie_val *ie_value = ast_alloca(sizeof(*ie_value));
01224 int insert = 0;
01225
01226 memset(ie_value, 0, sizeof(*ie_value));
01227 ie_value->ie_type = ie_type;
01228 ie_value->ie_pltype = va_arg(ap, enum ast_event_ie_pltype);
01229 switch (ie_value->ie_pltype) {
01230 case AST_EVENT_IE_PLTYPE_UINT:
01231 ie_value->payload.uint = va_arg(ap, uint32_t);
01232 insert = 1;
01233 break;
01234 case AST_EVENT_IE_PLTYPE_BITFLAGS:
01235 ie_value->payload.uint = va_arg(ap, uint32_t);
01236 insert = 1;
01237 break;
01238 case AST_EVENT_IE_PLTYPE_STR:
01239 ie_value->payload.str = va_arg(ap, const char *);
01240 insert = 1;
01241 break;
01242 case AST_EVENT_IE_PLTYPE_RAW:
01243 {
01244 void *data = va_arg(ap, void *);
01245 size_t datalen = va_arg(ap, size_t);
01246 ie_value->payload.raw = ast_alloca(datalen);
01247 memcpy(ie_value->payload.raw, data, datalen);
01248 ie_value->raw_datalen = datalen;
01249 insert = 1;
01250 break;
01251 }
01252 case AST_EVENT_IE_PLTYPE_UNKNOWN:
01253 case AST_EVENT_IE_PLTYPE_EXISTS:
01254 break;
01255 }
01256
01257 if (insert) {
01258 AST_LIST_INSERT_TAIL(&ie_vals, ie_value, entry);
01259 has_ie = 1;
01260 } else {
01261 ast_log(LOG_WARNING, "Unsupported PLTYPE(%d)\n", ie_value->ie_pltype);
01262 }
01263 }
01264 va_end(ap);
01265
01266 if (!(event = ast_calloc(1, sizeof(*event)))) {
01267 return NULL;
01268 }
01269
01270 event->type = htons(type);
01271 event->event_len = htons(sizeof(*event));
01272
01273 AST_LIST_TRAVERSE(&ie_vals, ie_val, entry) {
01274 switch (ie_val->ie_pltype) {
01275 case AST_EVENT_IE_PLTYPE_STR:
01276 ast_event_append_ie_str(&event, ie_val->ie_type, ie_val->payload.str);
01277 break;
01278 case AST_EVENT_IE_PLTYPE_UINT:
01279 ast_event_append_ie_uint(&event, ie_val->ie_type, ie_val->payload.uint);
01280 break;
01281 case AST_EVENT_IE_PLTYPE_BITFLAGS:
01282 ast_event_append_ie_bitflags(&event, ie_val->ie_type, ie_val->payload.uint);
01283 break;
01284 case AST_EVENT_IE_PLTYPE_RAW:
01285 ast_event_append_ie_raw(&event, ie_val->ie_type,
01286 ie_val->payload.raw, ie_val->raw_datalen);
01287 break;
01288 case AST_EVENT_IE_PLTYPE_EXISTS:
01289 case AST_EVENT_IE_PLTYPE_UNKNOWN:
01290 break;
01291 }
01292
01293
01294 if (!event) {
01295 return NULL;
01296 }
01297 }
01298
01299 if (has_ie && !ast_event_get_ie_raw(event, AST_EVENT_IE_EID)) {
01300
01301
01302 ast_event_append_eid(&event);
01303 }
01304
01305 return event;
01306 }
01307
01308 int ast_event_append_eid(struct ast_event **event)
01309 {
01310 return ast_event_append_ie_raw(event, AST_EVENT_IE_EID,
01311 &ast_eid_default, sizeof(ast_eid_default));
01312 }
01313
01314 void ast_event_destroy(struct ast_event *event)
01315 {
01316 ast_free(event);
01317 }
01318
01319 static void ast_event_ref_destroy(void *obj)
01320 {
01321 struct ast_event_ref *event_ref = obj;
01322
01323 ast_event_destroy(event_ref->event);
01324 }
01325
01326 static struct ast_event *ast_event_dup(const struct ast_event *event)
01327 {
01328 struct ast_event *dup_event;
01329 uint16_t event_len;
01330
01331 event_len = ast_event_get_size(event);
01332
01333 if (!(dup_event = ast_calloc(1, event_len))) {
01334 return NULL;
01335 }
01336
01337 memcpy(dup_event, event, event_len);
01338
01339 return dup_event;
01340 }
01341
01342 struct ast_event *ast_event_get_cached(enum ast_event_type type, ...)
01343 {
01344 va_list ap;
01345 enum ast_event_ie_type ie_type;
01346 struct ast_event *dup_event = NULL;
01347 struct ast_event_ref *cached_event_ref;
01348 struct ast_event *cache_arg_event;
01349 struct ast_event_ref tmp_event_ref = {
01350 .event = NULL,
01351 };
01352 struct ao2_container *container = NULL;
01353
01354 if (type >= AST_EVENT_TOTAL) {
01355 ast_log(LOG_ERROR, "%u is an invalid type!\n", type);
01356 return NULL;
01357 }
01358
01359 if (!(container = ast_event_cache[type].container)) {
01360 ast_log(LOG_ERROR, "%u is not a cached event type\n", type);
01361 return NULL;
01362 }
01363
01364 if (!(cache_arg_event = ast_event_new(type, AST_EVENT_IE_END))) {
01365 return NULL;
01366 }
01367
01368 va_start(ap, type);
01369 for (ie_type = va_arg(ap, enum ast_event_ie_type);
01370 ie_type != AST_EVENT_IE_END;
01371 ie_type = va_arg(ap, enum ast_event_ie_type))
01372 {
01373 enum ast_event_ie_pltype ie_pltype;
01374
01375 ie_pltype = va_arg(ap, enum ast_event_ie_pltype);
01376
01377 switch (ie_pltype) {
01378 case AST_EVENT_IE_PLTYPE_UINT:
01379 ast_event_append_ie_uint(&cache_arg_event, ie_type, va_arg(ap, uint32_t));
01380 break;
01381 case AST_EVENT_IE_PLTYPE_BITFLAGS:
01382 ast_event_append_ie_bitflags(&cache_arg_event, ie_type, va_arg(ap, uint32_t));
01383 break;
01384 case AST_EVENT_IE_PLTYPE_STR:
01385 ast_event_append_ie_str(&cache_arg_event, ie_type, va_arg(ap, const char *));
01386 break;
01387 case AST_EVENT_IE_PLTYPE_RAW:
01388 {
01389 void *data = va_arg(ap, void *);
01390 size_t datalen = va_arg(ap, size_t);
01391 ast_event_append_ie_raw(&cache_arg_event, ie_type, data, datalen);
01392 break;
01393 }
01394 case AST_EVENT_IE_PLTYPE_EXISTS:
01395 ast_log(LOG_WARNING, "PLTYPE_EXISTS not supported by this function\n");
01396 break;
01397 case AST_EVENT_IE_PLTYPE_UNKNOWN:
01398 break;
01399 }
01400 }
01401 va_end(ap);
01402
01403 tmp_event_ref.event = cache_arg_event;
01404
01405 cached_event_ref = ao2_find(container, &tmp_event_ref, OBJ_POINTER);
01406
01407 ast_event_destroy(cache_arg_event);
01408 cache_arg_event = NULL;
01409
01410 if (cached_event_ref) {
01411 dup_event = ast_event_dup(cached_event_ref->event);
01412 ao2_ref(cached_event_ref, -1);
01413 cached_event_ref = NULL;
01414 }
01415
01416 return dup_event;
01417 }
01418
01419 static struct ast_event_ref *alloc_event_ref(void)
01420 {
01421 return ao2_alloc(sizeof(struct ast_event_ref), ast_event_ref_destroy);
01422 }
01423
01424
01425
01426
01427
01428
01429
01430
01431
01432
01433
01434 static void event_update_cache(struct ao2_container *cache, struct ast_event *event)
01435 {
01436 struct ast_event_ref tmp_event_ref = {
01437 .event = event,
01438 };
01439 struct ast_event *dup_event;
01440 struct ast_event_ref *event_ref;
01441
01442
01443 ao2_lock(cache);
01444
01445
01446 ao2_callback(cache, OBJ_POINTER | OBJ_UNLINK | OBJ_MULTIPLE | OBJ_NODATA,
01447 ast_event_cmp, &tmp_event_ref);
01448
01449
01450 dup_event = ast_event_dup(event);
01451 if (dup_event) {
01452 event_ref = alloc_event_ref();
01453 if (event_ref) {
01454 event_ref->event = dup_event;
01455 ao2_link(cache, event_ref);
01456 ao2_ref(event_ref, -1);
01457 } else {
01458 ast_event_destroy(dup_event);
01459 }
01460 }
01461
01462 ao2_unlock(cache);
01463 }
01464
01465 int ast_event_queue_and_cache(struct ast_event *event)
01466 {
01467 struct ao2_container *container;
01468
01469 container = ast_event_cache[ast_event_get_type(event)].container;
01470 if (!container) {
01471 ast_log(LOG_WARNING, "cache requested for non-cached event type\n");
01472 } else {
01473 event_update_cache(container, event);
01474 }
01475
01476 if (ast_event_queue(event)) {
01477 ast_event_destroy(event);
01478 }
01479 return 0;
01480 }
01481
01482 static int handle_event(void *data)
01483 {
01484 struct ast_event_ref *event_ref = data;
01485 struct ast_event_sub *sub;
01486 const enum ast_event_type event_types[] = {
01487 ntohs(event_ref->event->type),
01488 AST_EVENT_ALL
01489 };
01490 int i;
01491
01492 for (i = 0; i < ARRAY_LEN(event_types); i++) {
01493 AST_RWDLLIST_RDLOCK(&ast_event_subs[event_types[i]]);
01494 AST_RWDLLIST_TRAVERSE(&ast_event_subs[event_types[i]], sub, entry) {
01495 struct ast_event_ie_val *ie_val;
01496
01497 AST_LIST_TRAVERSE(&sub->ie_vals, ie_val, entry) {
01498 if (!match_ie_val(event_ref->event, ie_val, NULL)) {
01499
01500 break;
01501 }
01502 }
01503 if (ie_val) {
01504
01505 continue;
01506 }
01507 sub->cb(event_ref->event, sub->userdata);
01508 }
01509 AST_RWDLLIST_UNLOCK(&ast_event_subs[event_types[i]]);
01510 }
01511
01512 ao2_ref(event_ref, -1);
01513
01514 return 0;
01515 }
01516
01517 int ast_event_queue(struct ast_event *event)
01518 {
01519 struct ast_event_ref *event_ref;
01520 uint16_t host_event_type;
01521 int res;
01522
01523 host_event_type = ntohs(event->type);
01524
01525
01526 if (host_event_type >= AST_EVENT_TOTAL) {
01527 ast_log(LOG_WARNING, "Someone tried to queue an event of invalid "
01528 "type '%d'!\n", host_event_type);
01529 return -1;
01530 }
01531
01532
01533 if (ast_event_check_subscriber(host_event_type, AST_EVENT_IE_END)
01534 == AST_EVENT_SUB_NONE) {
01535 ast_event_destroy(event);
01536 return 0;
01537 }
01538
01539 if (!(event_ref = alloc_event_ref())) {
01540 return -1;
01541 }
01542
01543 event_ref->event = event;
01544
01545 res = ast_taskprocessor_push(event_dispatcher, handle_event, event_ref);
01546 if (res) {
01547 event_ref->event = NULL;
01548 ao2_ref(event_ref, -1);
01549 }
01550 return res;
01551 }
01552
01553 static int ast_event_hash_mwi(const void *obj, const int flags)
01554 {
01555 const struct ast_event *event = obj;
01556 const char *mailbox = ast_event_get_ie_str(event, AST_EVENT_IE_MAILBOX);
01557 const char *context = ast_event_get_ie_str(event, AST_EVENT_IE_CONTEXT);
01558
01559 return ast_str_hash_add(context, ast_str_hash(mailbox));
01560 }
01561
01562
01563
01564
01565
01566
01567
01568
01569
01570
01571 static int ast_event_hash_devstate(const void *obj, const int flags)
01572 {
01573 const struct ast_event *event = obj;
01574
01575 return ast_str_hash(ast_event_get_ie_str(event, AST_EVENT_IE_DEVICE));
01576 }
01577
01578
01579
01580
01581
01582
01583
01584
01585
01586
01587 static int ast_event_hash_devstate_change(const void *obj, const int flags)
01588 {
01589 const struct ast_event *event = obj;
01590
01591 return ast_str_hash(ast_event_get_ie_str(event, AST_EVENT_IE_DEVICE));
01592 }
01593
01594 static int ast_event_hash(const void *obj, const int flags)
01595 {
01596 const struct ast_event_ref *event_ref;
01597 const struct ast_event *event;
01598 ao2_hash_fn *hash_fn;
01599
01600 event_ref = obj;
01601 event = event_ref->event;
01602
01603 if (!(hash_fn = ast_event_cache[ast_event_get_type(event)].hash_fn)) {
01604 return 0;
01605 }
01606
01607 return hash_fn(event, flags);
01608 }
01609
01610
01611
01612
01613
01614
01615
01616
01617
01618
01619
01620
01621
01622
01623
01624
01625
01626
01627
01628 static int ast_event_cmp(void *obj, void *arg, int flags)
01629 {
01630 struct ast_event_ref *event_ref, *event_ref2;
01631 struct ast_event *event, *event2;
01632 int res = CMP_MATCH;
01633 int i;
01634 enum ast_event_ie_type *cache_args;
01635
01636 event_ref = obj;
01637 event = event_ref->event;
01638
01639 event_ref2 = arg;
01640 event2 = event_ref2->event;
01641
01642 cache_args = ast_event_cache[ast_event_get_type(event)].cache_args;
01643
01644 for (i = 0; i < ARRAY_LEN(ast_event_cache[0].cache_args) && cache_args[i]; i++) {
01645 struct ast_event_ie_val ie_val = {
01646 .ie_pltype = ast_event_get_ie_pltype(cache_args[i]),
01647 .ie_type = cache_args[i],
01648 };
01649
01650 if (!match_ie_val(event, &ie_val, event2)) {
01651 res = 0;
01652 break;
01653 }
01654 }
01655
01656 return res;
01657 }
01658
01659 static void dump_raw_ie(struct ast_event_iterator *i, struct ast_cli_args *a)
01660 {
01661 char eid_buf[32];
01662 enum ast_event_ie_type ie_type;
01663 const char *ie_type_name;
01664
01665 ie_type = ast_event_iterator_get_ie_type(i);
01666 ie_type_name = ast_event_get_ie_type_name(ie_type);
01667
01668 switch (ie_type) {
01669 case AST_EVENT_IE_EID:
01670 ast_eid_to_str(eid_buf, sizeof(eid_buf), ast_event_iterator_get_ie_raw(i));
01671 ast_cli(a->fd, "%.30s: %s\n", ie_type_name, eid_buf);
01672 break;
01673 default:
01674 ast_cli(a->fd, "%s\n", ie_type_name);
01675 break;
01676 }
01677 }
01678
01679 static int event_dump_cli(void *obj, void *arg, int flags)
01680 {
01681 const struct ast_event_ref *event_ref = obj;
01682 const struct ast_event *event = event_ref->event;
01683 struct ast_cli_args *a = arg;
01684 struct ast_event_iterator i;
01685
01686 if (ast_event_iterator_init(&i, event)) {
01687 ast_cli(a->fd, "Failed to initialize event iterator. :-(\n");
01688 return 0;
01689 }
01690
01691 ast_cli(a->fd, "Event: %s\n", ast_event_get_type_name(event));
01692
01693 do {
01694 enum ast_event_ie_type ie_type;
01695 enum ast_event_ie_pltype ie_pltype;
01696 const char *ie_type_name;
01697
01698 ie_type = ast_event_iterator_get_ie_type(&i);
01699 ie_type_name = ast_event_get_ie_type_name(ie_type);
01700 ie_pltype = ast_event_get_ie_pltype(ie_type);
01701
01702 switch (ie_pltype) {
01703 case AST_EVENT_IE_PLTYPE_UNKNOWN:
01704 case AST_EVENT_IE_PLTYPE_EXISTS:
01705 ast_cli(a->fd, "%s\n", ie_type_name);
01706 break;
01707 case AST_EVENT_IE_PLTYPE_STR:
01708 ast_cli(a->fd, "%.30s: %s\n", ie_type_name,
01709 ast_event_iterator_get_ie_str(&i));
01710 break;
01711 case AST_EVENT_IE_PLTYPE_UINT:
01712 ast_cli(a->fd, "%.30s: %u\n", ie_type_name,
01713 ast_event_iterator_get_ie_uint(&i));
01714 break;
01715 case AST_EVENT_IE_PLTYPE_BITFLAGS:
01716 ast_cli(a->fd, "%.30s: %u\n", ie_type_name,
01717 ast_event_iterator_get_ie_bitflags(&i));
01718 break;
01719 case AST_EVENT_IE_PLTYPE_RAW:
01720 dump_raw_ie(&i, a);
01721 break;
01722 }
01723 } while (!ast_event_iterator_next(&i));
01724
01725 ast_cli(a->fd, "\n");
01726
01727 return 0;
01728 }
01729
01730 static char *event_dump_cache(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
01731 {
01732 enum ast_event_type event_type;
01733 enum ast_event_ie_type *cache_args;
01734 int i;
01735
01736 switch (cmd) {
01737 case CLI_INIT:
01738 e->command = "event dump cache";
01739 e->usage =
01740 "Usage: event dump cache <event type>\n"
01741 " Dump all of the cached events for the given event type.\n"
01742 " This is primarily intended for debugging.\n";
01743 return NULL;
01744 case CLI_GENERATE:
01745 if (a->pos == 3) {
01746 return ast_cli_complete(a->word, cached_event_types, a->n);
01747 }
01748 return NULL;
01749 case CLI_HANDLER:
01750 break;
01751 }
01752
01753 if (a->argc != e->args + 1) {
01754 return CLI_SHOWUSAGE;
01755 }
01756
01757 if (ast_event_str_to_event_type(a->argv[e->args], &event_type)) {
01758 ast_cli(a->fd, "Invalid cached event type: '%s'\n", a->argv[e->args]);
01759 return CLI_SHOWUSAGE;
01760 }
01761
01762 if (!ast_event_cache[event_type].container) {
01763 ast_cli(a->fd, "Event type '%s' has no cache.\n", a->argv[e->args]);
01764 return CLI_SUCCESS;
01765 }
01766
01767 ast_cli(a->fd, "Event Type: %s\n", a->argv[e->args]);
01768 ast_cli(a->fd, "Cache Unique Keys:\n");
01769 cache_args = ast_event_cache[event_type].cache_args;
01770 for (i = 0; i < ARRAY_LEN(ast_event_cache[0].cache_args) && cache_args[i]; i++) {
01771 ast_cli(a->fd, "--> %s\n", ast_event_get_ie_type_name(cache_args[i]));
01772 }
01773
01774 ast_cli(a->fd, "\n--- Begin Cache Dump ---\n\n");
01775 ao2_callback(ast_event_cache[event_type].container, OBJ_NODATA, event_dump_cli, a);
01776 ast_cli(a->fd, "--- End Cache Dump ---\n\n");
01777
01778 return CLI_SUCCESS;
01779 }
01780
01781 static struct ast_cli_entry event_cli[] = {
01782 AST_CLI_DEFINE(event_dump_cache, "Dump the internal event cache (for debugging)"),
01783 };
01784
01785
01786 static void event_shutdown(void)
01787 {
01788 struct ast_event_sub *sub;
01789 int i;
01790
01791 ast_cli_unregister_multiple(event_cli, ARRAY_LEN(event_cli));
01792
01793 if (event_dispatcher) {
01794 event_dispatcher = ast_taskprocessor_unreference(event_dispatcher);
01795 }
01796
01797
01798
01799
01800 for (i = 0; i < AST_EVENT_TOTAL; i++) {
01801 AST_RWDLLIST_WRLOCK(&ast_event_subs[i]);
01802 while ((sub = AST_RWDLLIST_REMOVE_HEAD(&ast_event_subs[i], entry))) {
01803 ast_event_sub_destroy(sub);
01804 }
01805 AST_RWDLLIST_UNLOCK(&ast_event_subs[i]);
01806 AST_RWDLLIST_HEAD_DESTROY(&ast_event_subs[i]);
01807 }
01808
01809 for (i = 0; i < AST_EVENT_TOTAL; i++) {
01810 if (!ast_event_cache[i].hash_fn) {
01811 continue;
01812 }
01813 if (ast_event_cache[i].container) {
01814 ao2_ref(ast_event_cache[i].container, -1);
01815 }
01816 }
01817 }
01818
01819 int ast_event_init(void)
01820 {
01821 int i;
01822
01823 for (i = 0; i < AST_EVENT_TOTAL; i++) {
01824 AST_RWDLLIST_HEAD_INIT(&ast_event_subs[i]);
01825 }
01826
01827 for (i = 0; i < AST_EVENT_TOTAL; i++) {
01828 if (!ast_event_cache[i].hash_fn) {
01829
01830 continue;
01831 }
01832
01833 if (!(ast_event_cache[i].container = ao2_container_alloc(NUM_CACHE_BUCKETS,
01834 ast_event_hash, ast_event_cmp))) {
01835 goto event_init_cleanup;
01836 }
01837 }
01838
01839 if (!(event_dispatcher = ast_taskprocessor_get("core_event_dispatcher", 0))) {
01840 goto event_init_cleanup;
01841 }
01842
01843 ast_cli_register_multiple(event_cli, ARRAY_LEN(event_cli));
01844
01845 ast_register_atexit(event_shutdown);
01846
01847 return 0;
01848
01849 event_init_cleanup:
01850 event_shutdown();
01851 return -1;
01852 }
01853
01854 size_t ast_event_minimum_length(void)
01855 {
01856 return sizeof(struct ast_event);
01857 }