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: 378303 $")
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 - '%d'\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 unsigned int extra_len;
01179 uint16_t event_len;
01180
01181 event_len = ntohs((*event)->event_len);
01182 extra_len = sizeof(*ie) + data_len;
01183
01184 if (!(*event = ast_realloc(*event, event_len + extra_len))) {
01185 return -1;
01186 }
01187
01188 ie = (struct ast_event_ie *) ( ((char *) *event) + event_len );
01189 ie->ie_type = htons(ie_type);
01190 ie->ie_payload_len = htons(data_len);
01191 memcpy(ie->ie_payload, data, data_len);
01192
01193 (*event)->event_len = htons(event_len + extra_len);
01194
01195 return 0;
01196 }
01197
01198 struct ast_event *ast_event_new(enum ast_event_type type, ...)
01199 {
01200 va_list ap;
01201 struct ast_event *event;
01202 enum ast_event_ie_type ie_type;
01203 struct ast_event_ie_val *ie_val;
01204 int has_ie = 0;
01205 AST_LIST_HEAD_NOLOCK_STATIC(ie_vals, ast_event_ie_val);
01206
01207
01208 if (type >= AST_EVENT_TOTAL) {
01209 ast_log(LOG_WARNING, "Someone tried to create an event of invalid "
01210 "type '%d'!\n", type);
01211 return NULL;
01212 }
01213
01214 va_start(ap, type);
01215 for (ie_type = va_arg(ap, enum ast_event_ie_type);
01216 ie_type != AST_EVENT_IE_END;
01217 ie_type = va_arg(ap, enum ast_event_ie_type))
01218 {
01219 struct ast_event_ie_val *ie_value = ast_alloca(sizeof(*ie_value));
01220 int insert = 0;
01221
01222 memset(ie_value, 0, sizeof(*ie_value));
01223 ie_value->ie_type = ie_type;
01224 ie_value->ie_pltype = va_arg(ap, enum ast_event_ie_pltype);
01225 switch (ie_value->ie_pltype) {
01226 case AST_EVENT_IE_PLTYPE_UINT:
01227 ie_value->payload.uint = va_arg(ap, uint32_t);
01228 insert = 1;
01229 break;
01230 case AST_EVENT_IE_PLTYPE_BITFLAGS:
01231 ie_value->payload.uint = va_arg(ap, uint32_t);
01232 insert = 1;
01233 break;
01234 case AST_EVENT_IE_PLTYPE_STR:
01235 ie_value->payload.str = va_arg(ap, const char *);
01236 insert = 1;
01237 break;
01238 case AST_EVENT_IE_PLTYPE_RAW:
01239 {
01240 void *data = va_arg(ap, void *);
01241 size_t datalen = va_arg(ap, size_t);
01242 ie_value->payload.raw = ast_alloca(datalen);
01243 memcpy(ie_value->payload.raw, data, datalen);
01244 ie_value->raw_datalen = datalen;
01245 insert = 1;
01246 break;
01247 }
01248 case AST_EVENT_IE_PLTYPE_UNKNOWN:
01249 case AST_EVENT_IE_PLTYPE_EXISTS:
01250 break;
01251 }
01252
01253 if (insert) {
01254 AST_LIST_INSERT_TAIL(&ie_vals, ie_value, entry);
01255 has_ie = 1;
01256 } else {
01257 ast_log(LOG_WARNING, "Unsupported PLTYPE(%d)\n", ie_value->ie_pltype);
01258 }
01259 }
01260 va_end(ap);
01261
01262 if (!(event = ast_calloc(1, sizeof(*event)))) {
01263 return NULL;
01264 }
01265
01266 event->type = htons(type);
01267 event->event_len = htons(sizeof(*event));
01268
01269 AST_LIST_TRAVERSE(&ie_vals, ie_val, entry) {
01270 switch (ie_val->ie_pltype) {
01271 case AST_EVENT_IE_PLTYPE_STR:
01272 ast_event_append_ie_str(&event, ie_val->ie_type, ie_val->payload.str);
01273 break;
01274 case AST_EVENT_IE_PLTYPE_UINT:
01275 ast_event_append_ie_uint(&event, ie_val->ie_type, ie_val->payload.uint);
01276 break;
01277 case AST_EVENT_IE_PLTYPE_BITFLAGS:
01278 ast_event_append_ie_bitflags(&event, ie_val->ie_type, ie_val->payload.uint);
01279 break;
01280 case AST_EVENT_IE_PLTYPE_RAW:
01281 ast_event_append_ie_raw(&event, ie_val->ie_type,
01282 ie_val->payload.raw, ie_val->raw_datalen);
01283 break;
01284 case AST_EVENT_IE_PLTYPE_EXISTS:
01285 case AST_EVENT_IE_PLTYPE_UNKNOWN:
01286 break;
01287 }
01288
01289
01290 if (!event) {
01291 return NULL;
01292 }
01293 }
01294
01295 if (has_ie && !ast_event_get_ie_raw(event, AST_EVENT_IE_EID)) {
01296
01297
01298 ast_event_append_eid(&event);
01299 }
01300
01301 return event;
01302 }
01303
01304 int ast_event_append_eid(struct ast_event **event)
01305 {
01306 return ast_event_append_ie_raw(event, AST_EVENT_IE_EID,
01307 &ast_eid_default, sizeof(ast_eid_default));
01308 }
01309
01310 void ast_event_destroy(struct ast_event *event)
01311 {
01312 ast_free(event);
01313 }
01314
01315 static void ast_event_ref_destroy(void *obj)
01316 {
01317 struct ast_event_ref *event_ref = obj;
01318
01319 ast_event_destroy(event_ref->event);
01320 }
01321
01322 static struct ast_event *ast_event_dup(const struct ast_event *event)
01323 {
01324 struct ast_event *dup_event;
01325 uint16_t event_len;
01326
01327 event_len = ast_event_get_size(event);
01328
01329 if (!(dup_event = ast_calloc(1, event_len))) {
01330 return NULL;
01331 }
01332
01333 memcpy(dup_event, event, event_len);
01334
01335 return dup_event;
01336 }
01337
01338 struct ast_event *ast_event_get_cached(enum ast_event_type type, ...)
01339 {
01340 va_list ap;
01341 enum ast_event_ie_type ie_type;
01342 struct ast_event *dup_event = NULL;
01343 struct ast_event_ref *cached_event_ref;
01344 struct ast_event *cache_arg_event;
01345 struct ast_event_ref tmp_event_ref = {
01346 .event = NULL,
01347 };
01348 struct ao2_container *container = NULL;
01349
01350 if (type >= AST_EVENT_TOTAL) {
01351 ast_log(LOG_ERROR, "%u is an invalid type!\n", type);
01352 return NULL;
01353 }
01354
01355 if (!(container = ast_event_cache[type].container)) {
01356 ast_log(LOG_ERROR, "%u is not a cached event type\n", type);
01357 return NULL;
01358 }
01359
01360 if (!(cache_arg_event = ast_event_new(type, AST_EVENT_IE_END))) {
01361 return NULL;
01362 }
01363
01364 va_start(ap, type);
01365 for (ie_type = va_arg(ap, enum ast_event_ie_type);
01366 ie_type != AST_EVENT_IE_END;
01367 ie_type = va_arg(ap, enum ast_event_ie_type))
01368 {
01369 enum ast_event_ie_pltype ie_pltype;
01370
01371 ie_pltype = va_arg(ap, enum ast_event_ie_pltype);
01372
01373 switch (ie_pltype) {
01374 case AST_EVENT_IE_PLTYPE_UINT:
01375 ast_event_append_ie_uint(&cache_arg_event, ie_type, va_arg(ap, uint32_t));
01376 break;
01377 case AST_EVENT_IE_PLTYPE_BITFLAGS:
01378 ast_event_append_ie_bitflags(&cache_arg_event, ie_type, va_arg(ap, uint32_t));
01379 break;
01380 case AST_EVENT_IE_PLTYPE_STR:
01381 ast_event_append_ie_str(&cache_arg_event, ie_type, va_arg(ap, const char *));
01382 break;
01383 case AST_EVENT_IE_PLTYPE_RAW:
01384 {
01385 void *data = va_arg(ap, void *);
01386 size_t datalen = va_arg(ap, size_t);
01387 ast_event_append_ie_raw(&cache_arg_event, ie_type, data, datalen);
01388 break;
01389 }
01390 case AST_EVENT_IE_PLTYPE_EXISTS:
01391 ast_log(LOG_WARNING, "PLTYPE_EXISTS not supported by this function\n");
01392 break;
01393 case AST_EVENT_IE_PLTYPE_UNKNOWN:
01394 break;
01395 }
01396 }
01397 va_end(ap);
01398
01399 tmp_event_ref.event = cache_arg_event;
01400
01401 cached_event_ref = ao2_find(container, &tmp_event_ref, OBJ_POINTER);
01402
01403 ast_event_destroy(cache_arg_event);
01404 cache_arg_event = NULL;
01405
01406 if (cached_event_ref) {
01407 dup_event = ast_event_dup(cached_event_ref->event);
01408 ao2_ref(cached_event_ref, -1);
01409 cached_event_ref = NULL;
01410 }
01411
01412 return dup_event;
01413 }
01414
01415 static struct ast_event_ref *alloc_event_ref(void)
01416 {
01417 return ao2_alloc(sizeof(struct ast_event_ref), ast_event_ref_destroy);
01418 }
01419
01420
01421
01422
01423
01424
01425
01426
01427
01428
01429
01430 static void event_update_cache(struct ao2_container *cache, struct ast_event *event)
01431 {
01432 struct ast_event_ref tmp_event_ref = {
01433 .event = event,
01434 };
01435 struct ast_event *dup_event;
01436 struct ast_event_ref *event_ref;
01437
01438
01439 ao2_lock(cache);
01440
01441
01442 ao2_callback(cache, OBJ_POINTER | OBJ_UNLINK | OBJ_MULTIPLE | OBJ_NODATA,
01443 ast_event_cmp, &tmp_event_ref);
01444
01445
01446 dup_event = ast_event_dup(event);
01447 if (dup_event) {
01448 event_ref = alloc_event_ref();
01449 if (event_ref) {
01450 event_ref->event = dup_event;
01451 ao2_link(cache, event_ref);
01452 ao2_ref(event_ref, -1);
01453 } else {
01454 ast_event_destroy(dup_event);
01455 }
01456 }
01457
01458 ao2_unlock(cache);
01459 }
01460
01461 int ast_event_queue_and_cache(struct ast_event *event)
01462 {
01463 struct ao2_container *container;
01464
01465 container = ast_event_cache[ast_event_get_type(event)].container;
01466 if (!container) {
01467 ast_log(LOG_WARNING, "cache requested for non-cached event type\n");
01468 } else {
01469 event_update_cache(container, event);
01470 }
01471
01472 if (ast_event_queue(event)) {
01473 ast_event_destroy(event);
01474 }
01475 return 0;
01476 }
01477
01478 static int handle_event(void *data)
01479 {
01480 struct ast_event_ref *event_ref = data;
01481 struct ast_event_sub *sub;
01482 const enum ast_event_type event_types[] = {
01483 ntohs(event_ref->event->type),
01484 AST_EVENT_ALL
01485 };
01486 int i;
01487
01488 for (i = 0; i < ARRAY_LEN(event_types); i++) {
01489 AST_RWDLLIST_RDLOCK(&ast_event_subs[event_types[i]]);
01490 AST_RWDLLIST_TRAVERSE(&ast_event_subs[event_types[i]], sub, entry) {
01491 struct ast_event_ie_val *ie_val;
01492
01493 AST_LIST_TRAVERSE(&sub->ie_vals, ie_val, entry) {
01494 if (!match_ie_val(event_ref->event, ie_val, NULL)) {
01495
01496 break;
01497 }
01498 }
01499 if (ie_val) {
01500
01501 continue;
01502 }
01503 sub->cb(event_ref->event, sub->userdata);
01504 }
01505 AST_RWDLLIST_UNLOCK(&ast_event_subs[event_types[i]]);
01506 }
01507
01508 ao2_ref(event_ref, -1);
01509
01510 return 0;
01511 }
01512
01513 int ast_event_queue(struct ast_event *event)
01514 {
01515 struct ast_event_ref *event_ref;
01516 uint16_t host_event_type;
01517 int res;
01518
01519 host_event_type = ntohs(event->type);
01520
01521
01522 if (host_event_type >= AST_EVENT_TOTAL) {
01523 ast_log(LOG_WARNING, "Someone tried to queue an event of invalid "
01524 "type '%d'!\n", host_event_type);
01525 return -1;
01526 }
01527
01528
01529 if (ast_event_check_subscriber(host_event_type, AST_EVENT_IE_END)
01530 == AST_EVENT_SUB_NONE) {
01531 ast_event_destroy(event);
01532 return 0;
01533 }
01534
01535 if (!(event_ref = alloc_event_ref())) {
01536 return -1;
01537 }
01538
01539 event_ref->event = event;
01540
01541 res = ast_taskprocessor_push(event_dispatcher, handle_event, event_ref);
01542 if (res) {
01543 event_ref->event = NULL;
01544 ao2_ref(event_ref, -1);
01545 }
01546 return res;
01547 }
01548
01549 static int ast_event_hash_mwi(const void *obj, const int flags)
01550 {
01551 const struct ast_event *event = obj;
01552 const char *mailbox = ast_event_get_ie_str(event, AST_EVENT_IE_MAILBOX);
01553 const char *context = ast_event_get_ie_str(event, AST_EVENT_IE_CONTEXT);
01554
01555 return ast_str_hash_add(context, ast_str_hash(mailbox));
01556 }
01557
01558
01559
01560
01561
01562
01563
01564
01565
01566
01567 static int ast_event_hash_devstate(const void *obj, const int flags)
01568 {
01569 const struct ast_event *event = obj;
01570
01571 return ast_str_hash(ast_event_get_ie_str(event, AST_EVENT_IE_DEVICE));
01572 }
01573
01574
01575
01576
01577
01578
01579
01580
01581
01582
01583 static int ast_event_hash_devstate_change(const void *obj, const int flags)
01584 {
01585 const struct ast_event *event = obj;
01586
01587 return ast_str_hash(ast_event_get_ie_str(event, AST_EVENT_IE_DEVICE));
01588 }
01589
01590 static int ast_event_hash(const void *obj, const int flags)
01591 {
01592 const struct ast_event_ref *event_ref;
01593 const struct ast_event *event;
01594 ao2_hash_fn *hash_fn;
01595
01596 event_ref = obj;
01597 event = event_ref->event;
01598
01599 if (!(hash_fn = ast_event_cache[ast_event_get_type(event)].hash_fn)) {
01600 return 0;
01601 }
01602
01603 return hash_fn(event, flags);
01604 }
01605
01606
01607
01608
01609
01610
01611
01612
01613
01614
01615
01616
01617
01618
01619
01620
01621
01622
01623
01624 static int ast_event_cmp(void *obj, void *arg, int flags)
01625 {
01626 struct ast_event_ref *event_ref, *event_ref2;
01627 struct ast_event *event, *event2;
01628 int res = CMP_MATCH;
01629 int i;
01630 enum ast_event_ie_type *cache_args;
01631
01632 event_ref = obj;
01633 event = event_ref->event;
01634
01635 event_ref2 = arg;
01636 event2 = event_ref2->event;
01637
01638 cache_args = ast_event_cache[ast_event_get_type(event)].cache_args;
01639
01640 for (i = 0; i < ARRAY_LEN(ast_event_cache[0].cache_args) && cache_args[i]; i++) {
01641 struct ast_event_ie_val ie_val = {
01642 .ie_pltype = ast_event_get_ie_pltype(cache_args[i]),
01643 .ie_type = cache_args[i],
01644 };
01645
01646 if (!match_ie_val(event, &ie_val, event2)) {
01647 res = 0;
01648 break;
01649 }
01650 }
01651
01652 return res;
01653 }
01654
01655 static void dump_raw_ie(struct ast_event_iterator *i, struct ast_cli_args *a)
01656 {
01657 char eid_buf[32];
01658 enum ast_event_ie_type ie_type;
01659 const char *ie_type_name;
01660
01661 ie_type = ast_event_iterator_get_ie_type(i);
01662 ie_type_name = ast_event_get_ie_type_name(ie_type);
01663
01664 switch (ie_type) {
01665 case AST_EVENT_IE_EID:
01666 ast_eid_to_str(eid_buf, sizeof(eid_buf), ast_event_iterator_get_ie_raw(i));
01667 ast_cli(a->fd, "%.30s: %s\n", ie_type_name, eid_buf);
01668 break;
01669 default:
01670 ast_cli(a->fd, "%s\n", ie_type_name);
01671 break;
01672 }
01673 }
01674
01675 static int event_dump_cli(void *obj, void *arg, int flags)
01676 {
01677 const struct ast_event_ref *event_ref = obj;
01678 const struct ast_event *event = event_ref->event;
01679 struct ast_cli_args *a = arg;
01680 struct ast_event_iterator i;
01681
01682 if (ast_event_iterator_init(&i, event)) {
01683 ast_cli(a->fd, "Failed to initialize event iterator. :-(\n");
01684 return 0;
01685 }
01686
01687 ast_cli(a->fd, "Event: %s\n", ast_event_get_type_name(event));
01688
01689 do {
01690 enum ast_event_ie_type ie_type;
01691 enum ast_event_ie_pltype ie_pltype;
01692 const char *ie_type_name;
01693
01694 ie_type = ast_event_iterator_get_ie_type(&i);
01695 ie_type_name = ast_event_get_ie_type_name(ie_type);
01696 ie_pltype = ast_event_get_ie_pltype(ie_type);
01697
01698 switch (ie_pltype) {
01699 case AST_EVENT_IE_PLTYPE_UNKNOWN:
01700 case AST_EVENT_IE_PLTYPE_EXISTS:
01701 ast_cli(a->fd, "%s\n", ie_type_name);
01702 break;
01703 case AST_EVENT_IE_PLTYPE_STR:
01704 ast_cli(a->fd, "%.30s: %s\n", ie_type_name,
01705 ast_event_iterator_get_ie_str(&i));
01706 break;
01707 case AST_EVENT_IE_PLTYPE_UINT:
01708 ast_cli(a->fd, "%.30s: %u\n", ie_type_name,
01709 ast_event_iterator_get_ie_uint(&i));
01710 break;
01711 case AST_EVENT_IE_PLTYPE_BITFLAGS:
01712 ast_cli(a->fd, "%.30s: %u\n", ie_type_name,
01713 ast_event_iterator_get_ie_bitflags(&i));
01714 break;
01715 case AST_EVENT_IE_PLTYPE_RAW:
01716 dump_raw_ie(&i, a);
01717 break;
01718 }
01719 } while (!ast_event_iterator_next(&i));
01720
01721 ast_cli(a->fd, "\n");
01722
01723 return 0;
01724 }
01725
01726 static char *event_dump_cache(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
01727 {
01728 enum ast_event_type event_type;
01729 enum ast_event_ie_type *cache_args;
01730 int i;
01731
01732 switch (cmd) {
01733 case CLI_INIT:
01734 e->command = "event dump cache";
01735 e->usage =
01736 "Usage: event dump cache <event type>\n"
01737 " Dump all of the cached events for the given event type.\n"
01738 " This is primarily intended for debugging.\n";
01739 return NULL;
01740 case CLI_GENERATE:
01741 if (a->pos == 3) {
01742 return ast_cli_complete(a->word, cached_event_types, a->n);
01743 }
01744 return NULL;
01745 case CLI_HANDLER:
01746 break;
01747 }
01748
01749 if (a->argc != e->args + 1) {
01750 return CLI_SHOWUSAGE;
01751 }
01752
01753 if (ast_event_str_to_event_type(a->argv[e->args], &event_type)) {
01754 ast_cli(a->fd, "Invalid cached event type: '%s'\n", a->argv[e->args]);
01755 return CLI_SHOWUSAGE;
01756 }
01757
01758 if (!ast_event_cache[event_type].container) {
01759 ast_cli(a->fd, "Event type '%s' has no cache.\n", a->argv[e->args]);
01760 return CLI_SUCCESS;
01761 }
01762
01763 ast_cli(a->fd, "Event Type: %s\n", a->argv[e->args]);
01764 ast_cli(a->fd, "Cache Unique Keys:\n");
01765 cache_args = ast_event_cache[event_type].cache_args;
01766 for (i = 0; i < ARRAY_LEN(ast_event_cache[0].cache_args) && cache_args[i]; i++) {
01767 ast_cli(a->fd, "--> %s\n", ast_event_get_ie_type_name(cache_args[i]));
01768 }
01769
01770 ast_cli(a->fd, "\n--- Begin Cache Dump ---\n\n");
01771 ao2_callback(ast_event_cache[event_type].container, OBJ_NODATA, event_dump_cli, a);
01772 ast_cli(a->fd, "--- End Cache Dump ---\n\n");
01773
01774 return CLI_SUCCESS;
01775 }
01776
01777 static struct ast_cli_entry event_cli[] = {
01778 AST_CLI_DEFINE(event_dump_cache, "Dump the internal event cache (for debugging)"),
01779 };
01780
01781
01782 static void event_shutdown(void)
01783 {
01784 struct ast_event_sub *sub;
01785 int i;
01786
01787 ast_cli_unregister_multiple(event_cli, ARRAY_LEN(event_cli));
01788
01789 if (event_dispatcher) {
01790 event_dispatcher = ast_taskprocessor_unreference(event_dispatcher);
01791 }
01792
01793
01794
01795
01796 for (i = 0; i < AST_EVENT_TOTAL; i++) {
01797 AST_RWDLLIST_WRLOCK(&ast_event_subs[i]);
01798 while ((sub = AST_RWDLLIST_REMOVE_HEAD(&ast_event_subs[i], entry))) {
01799 ast_event_sub_destroy(sub);
01800 }
01801 AST_RWDLLIST_UNLOCK(&ast_event_subs[i]);
01802 AST_RWDLLIST_HEAD_DESTROY(&ast_event_subs[i]);
01803 }
01804
01805 for (i = 0; i < AST_EVENT_TOTAL; i++) {
01806 if (!ast_event_cache[i].hash_fn) {
01807 continue;
01808 }
01809 if (ast_event_cache[i].container) {
01810 ao2_ref(ast_event_cache[i].container, -1);
01811 }
01812 }
01813 }
01814
01815 int ast_event_init(void)
01816 {
01817 int i;
01818
01819 for (i = 0; i < AST_EVENT_TOTAL; i++) {
01820 AST_RWDLLIST_HEAD_INIT(&ast_event_subs[i]);
01821 }
01822
01823 for (i = 0; i < AST_EVENT_TOTAL; i++) {
01824 if (!ast_event_cache[i].hash_fn) {
01825
01826 continue;
01827 }
01828
01829 if (!(ast_event_cache[i].container = ao2_container_alloc(NUM_CACHE_BUCKETS,
01830 ast_event_hash, ast_event_cmp))) {
01831 goto event_init_cleanup;
01832 }
01833 }
01834
01835 if (!(event_dispatcher = ast_taskprocessor_get("core_event_dispatcher", 0))) {
01836 goto event_init_cleanup;
01837 }
01838
01839 ast_cli_register_multiple(event_cli, ARRAY_LEN(event_cli));
01840
01841 ast_register_atexit(event_shutdown);
01842
01843 return 0;
01844
01845 event_init_cleanup:
01846 event_shutdown();
01847 return -1;
01848 }
01849
01850 size_t ast_event_minimum_length(void)
01851 {
01852 return sizeof(struct ast_event);
01853 }