Address JSON thread safety issues.
[asterisk/asterisk.git] / main / cel.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2007 - 2009, Digium, Inc.
5  *
6  * See http://www.asterisk.org for more information about
7  * the Asterisk project. Please do not directly contact
8  * any of the maintainers of this project for assistance;
9  * the project provides a web site, mailing lists and IRC
10  * channels for your use.
11  *
12  * This program is free software, distributed under the terms of
13  * the GNU General Public License Version 2. See the LICENSE file
14  * at the top of the source tree.
15  */
16
17 /*!
18  * \file
19  *
20  * \brief Channel Event Logging API
21  *
22  * \author Steve Murphy <murf@digium.com>
23  * \author Russell Bryant <russell@digium.com>
24  *
25  * \todo Do thorough testing of all transfer methods to ensure that BLINDTRANSFER,
26  *       ATTENDEDTRANSFER, BRIDGE_START, and BRIDGE_END events are all reported
27  *       as expected.
28  */
29
30 /*! \li \ref cel.c uses the configuration file \ref cel.conf
31  * \addtogroup configuration_file Configuration Files
32  */
33
34 /*!
35  * \page cel.conf cel.conf
36  * \verbinclude cel.conf.sample
37  */
38
39 /*** MODULEINFO
40         <support_level>core</support_level>
41  ***/
42
43 #include "asterisk.h"
44
45 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
46
47 #include "asterisk/_private.h"
48
49 #include "asterisk/channel.h"
50 #include "asterisk/pbx.h"
51 #include "asterisk/cel.h"
52 #include "asterisk/logger.h"
53 #include "asterisk/linkedlists.h"
54 #include "asterisk/utils.h"
55 #include "asterisk/config.h"
56 #include "asterisk/config_options.h"
57 #include "asterisk/cli.h"
58 #include "asterisk/astobj2.h"
59 #include "asterisk/stasis_message_router.h"
60 #include "asterisk/stasis_channels.h"
61 #include "asterisk/stasis_bridges.h"
62 #include "asterisk/bridge.h"
63 #include "asterisk/parking.h"
64 #include "asterisk/pickup.h"
65 #include "asterisk/core_local.h"
66
67 /*** DOCUMENTATION
68         <configInfo name="cel" language="en_US">
69                 <configFile name="cel.conf">
70                         <configObject name="general">
71                                 <synopsis>Options that apply globally to Channel Event Logging (CEL)</synopsis>
72                                 <configOption name="enable">
73                                         <synopsis>Determines whether CEL is enabled</synopsis>
74                                 </configOption>
75                                 <configOption name="dateformat">
76                                         <synopsis>The format to be used for dates when logging</synopsis>
77                                 </configOption>
78                                 <configOption name="apps">
79                                         <synopsis>List of apps for CEL to track</synopsis>
80                                         <description><para>A case-insensitive, comma-separated list of applications
81                                         to track when one or both of APP_START and APP_END events are flagged for
82                                         tracking</para></description>
83                                 </configOption>
84                                 <configOption name="events">
85                                         <synopsis>List of events for CEL to track</synopsis>
86                                         <description><para>A case-sensitive, comma-separated list of event names
87                                         to track. These event names do not include the leading <literal>AST_CEL</literal>.
88                                         </para>
89                                         <enumlist>
90                                                 <enum name="ALL">
91                                                         <para>Special value which tracks all events.</para>
92                                                 </enum>
93                                                 <enum name="CHAN_START"/>
94                                                 <enum name="CHAN_END"/>
95                                                 <enum name="ANSWER"/>
96                                                 <enum name="HANGUP"/>
97                                                 <enum name="APP_START"/>
98                                                 <enum name="APP_END"/>
99                                                 <enum name="BRIDGE_START"/>
100                                                 <enum name="BRIDGE_END"/>
101                                                 <enum name="BRIDGE_TO_CONF"/>
102                                                 <enum name="CONF_START"/>
103                                                 <enum name="CONF_END"/>
104                                                 <enum name="PARK_START"/>
105                                                 <enum name="PARK_END"/>
106                                                 <enum name="USER_DEFINED"/>
107                                                 <enum name="CONF_ENTER"/>
108                                                 <enum name="CONF_EXIT"/>
109                                                 <enum name="BLINDTRANSFER"/>
110                                                 <enum name="ATTENDEDTRANSFER"/>
111                                                 <enum name="PICKUP"/>
112                                                 <enum name="FORWARD"/>
113                                                 <enum name="3WAY_START"/>
114                                                 <enum name="3WAY_END"/>
115                                                 <enum name="HOOKFLASH"/>
116                                                 <enum name="LINKEDID_END"/>
117                                                 <enum name="LOCAL_OPTIMIZE"/>
118                                         </enumlist>
119                                         </description>
120                                 </configOption>
121                         </configObject>
122                 </configFile>
123         </configInfo>
124  ***/
125
126 /*! Message router for state that CEL needs to know about */
127 static struct stasis_message_router *cel_state_router;
128
129 /*! Topic for CEL-specific messages */
130 static struct stasis_topic *cel_topic;
131
132 /*! Aggregation topic for all topics CEL needs to know about */
133 static struct stasis_topic *cel_aggregation_topic;
134
135 /*! Subscription for forwarding the channel caching topic */
136 static struct stasis_subscription *cel_channel_forwarder;
137
138 /*! Subscription for forwarding the channel caching topic */
139 static struct stasis_subscription *cel_bridge_forwarder;
140
141 /*! Subscription for forwarding the parking topic */
142 static struct stasis_subscription *cel_parking_forwarder;
143
144 /*! Subscription for forwarding the CEL-specific topic */
145 static struct stasis_subscription *cel_cel_forwarder;
146
147 /*! Container for primary channel/bridge ID listing for 2 party bridges */
148 static struct ao2_container *bridge_primaries;
149
150 struct stasis_message_type *cel_generic_type(void);
151 STASIS_MESSAGE_TYPE_DEFN(cel_generic_type);
152
153 /*! The number of buckets into which primary channel uniqueids will be hashed */
154 #define BRIDGE_PRIMARY_BUCKETS 251
155
156 /*! Container for dial end multichannel blobs for holding on to dial statuses */
157 static struct ao2_container *cel_dialstatus_store;
158
159 /*!
160  * \brief Maximum possible CEL event IDs
161  * \note This limit is currently imposed by the eventset definition
162  */
163 #define CEL_MAX_EVENT_IDS 64
164
165 /*!
166  * \brief Number of buckets for the appset container
167  */
168 #define NUM_APP_BUCKETS         97
169
170 /*!
171  * \brief Number of buckets for the dialstatus container
172  */
173 #define NUM_DIALSTATUS_BUCKETS  251
174
175 /*!
176  * \brief Container of Asterisk application names
177  *
178  * The apps in this container are the applications that were specified
179  * in the configuration as applications that CEL events should be generated
180  * for when they start and end on a channel.
181  */
182 static struct ao2_container *linkedids;
183
184 /*! \brief Destructor for cel_config */
185 static void cel_general_config_dtor(void *obj)
186 {
187         struct ast_cel_general_config *cfg = obj;
188         ast_string_field_free_memory(cfg);
189         ao2_cleanup(cfg->apps);
190         cfg->apps = NULL;
191 }
192
193 void *ast_cel_general_config_alloc(void)
194 {
195         RAII_VAR(struct ast_cel_general_config *, cfg, NULL, ao2_cleanup);
196
197         if (!(cfg = ao2_alloc(sizeof(*cfg), cel_general_config_dtor))) {
198                 return NULL;
199         }
200
201         if (ast_string_field_init(cfg, 64)) {
202                 return NULL;
203         }
204
205         if (!(cfg->apps = ast_str_container_alloc(NUM_APP_BUCKETS))) {
206                 return NULL;
207         }
208
209         ao2_ref(cfg, +1);
210         return cfg;
211 }
212
213 /*! \brief A container that holds all config-related information */
214 struct cel_config {
215         struct ast_cel_general_config *general;
216 };
217
218
219 static AO2_GLOBAL_OBJ_STATIC(cel_configs);
220
221 /*! \brief Destructor for cel_config */
222 static void cel_config_dtor(void *obj)
223 {
224         struct cel_config *cfg = obj;
225         ao2_cleanup(cfg->general);
226         cfg->general = NULL;
227 }
228
229 static void *cel_config_alloc(void)
230 {
231         RAII_VAR(struct cel_config *, cfg, NULL, ao2_cleanup);
232
233         if (!(cfg = ao2_alloc(sizeof(*cfg), cel_config_dtor))) {
234                 return NULL;
235         }
236
237         if (!(cfg->general = ast_cel_general_config_alloc())) {
238                 return NULL;
239         }
240
241         ao2_ref(cfg, +1);
242         return cfg;
243 }
244
245 /*! \brief An aco_type structure to link the "general" category to the ast_cel_general_config type */
246 static struct aco_type general_option = {
247         .type = ACO_GLOBAL,
248         .name = "general",
249         .item_offset = offsetof(struct cel_config, general),
250         .category_match = ACO_WHITELIST,
251         .category = "^general$",
252 };
253
254 /*! \brief The config file to be processed for the module. */
255 static struct aco_file cel_conf = {
256         .filename = "cel.conf",                  /*!< The name of the config file */
257         .types = ACO_TYPES(&general_option),     /*!< The mapping object types to be processed */
258         .skip_category = "(^manager$|^radius$)", /*!< Config sections used by existing modules. Do not add to this list. */
259 };
260
261 static int cel_pre_apply_config(void);
262
263 CONFIG_INFO_CORE("cel", cel_cfg_info, cel_configs, cel_config_alloc,
264         .files = ACO_FILES(&cel_conf),
265         .pre_apply_config = cel_pre_apply_config,
266 );
267
268 static int cel_pre_apply_config(void)
269 {
270         struct cel_config *cfg = aco_pending_config(&cel_cfg_info);
271
272         if (!cfg->general) {
273                 return -1;
274         }
275
276         if (!ao2_container_count(cfg->general->apps)) {
277                 return 0;
278         }
279
280         if (cfg->general->events & ((int64_t) 1 << AST_CEL_APP_START)) {
281                 return 0;
282         }
283
284         if (cfg->general->events & ((int64_t) 1 << AST_CEL_APP_END)) {
285                 return 0;
286         }
287
288         ast_log(LOG_ERROR, "Applications are listed to be tracked, but APP events are not tracked\n");
289         return -1;
290 }
291
292 static struct aco_type *general_options[] = ACO_TYPES(&general_option);
293
294 /*!
295  * \brief Map of ast_cel_event_type to strings
296  */
297 static const char * const cel_event_types[CEL_MAX_EVENT_IDS] = {
298         [0]                        = "ALL",
299         [AST_CEL_CHANNEL_START]    = "CHAN_START",
300         [AST_CEL_CHANNEL_END]      = "CHAN_END",
301         [AST_CEL_ANSWER]           = "ANSWER",
302         [AST_CEL_HANGUP]           = "HANGUP",
303         [AST_CEL_APP_START]        = "APP_START",
304         [AST_CEL_APP_END]          = "APP_END",
305         [AST_CEL_BRIDGE_START]     = "BRIDGE_START",
306         [AST_CEL_BRIDGE_END]       = "BRIDGE_END",
307         [AST_CEL_BRIDGE_TO_CONF]   = "BRIDGE_TO_CONF",
308         [AST_CEL_CONF_START]       = "CONF_START",
309         [AST_CEL_CONF_END]         = "CONF_END",
310         [AST_CEL_PARK_START]       = "PARK_START",
311         [AST_CEL_PARK_END]         = "PARK_END",
312         [AST_CEL_USER_DEFINED]     = "USER_DEFINED",
313         [AST_CEL_CONF_ENTER]       = "CONF_ENTER",
314         [AST_CEL_CONF_EXIT]        = "CONF_EXIT",
315         [AST_CEL_BLINDTRANSFER]    = "BLINDTRANSFER",
316         [AST_CEL_ATTENDEDTRANSFER] = "ATTENDEDTRANSFER",
317         [AST_CEL_PICKUP]           = "PICKUP",
318         [AST_CEL_FORWARD]          = "FORWARD",
319         [AST_CEL_3WAY_START]       = "3WAY_START",
320         [AST_CEL_3WAY_END]         = "3WAY_END",
321         [AST_CEL_HOOKFLASH]        = "HOOKFLASH",
322         [AST_CEL_LINKEDID_END]     = "LINKEDID_END",
323         [AST_CEL_LOCAL_OPTIMIZE]   = "LOCAL_OPTIMIZE",
324 };
325
326 struct bridge_assoc {
327         AST_DECLARE_STRING_FIELDS(
328                 AST_STRING_FIELD(bridge_id);           /*!< UniqueID of the bridge */
329                 AST_STRING_FIELD(secondary_name);      /*!< UniqueID of the secondary/dialed channel */
330         );
331         struct ast_channel_snapshot *primary_snapshot; /*!< The snapshot for the initiating channel in the bridge */
332         int track_as_conf;                             /*!< Whether this bridge will be treated like a conference in CEL terms */
333 };
334
335 static void bridge_assoc_dtor(void *obj)
336 {
337         struct bridge_assoc *assoc = obj;
338         ast_string_field_free_memory(assoc);
339         ao2_cleanup(assoc->primary_snapshot);
340         assoc->primary_snapshot = NULL;
341 }
342
343 static struct bridge_assoc *bridge_assoc_alloc(struct ast_channel_snapshot *primary, const char *bridge_id, const char *secondary_name)
344 {
345         RAII_VAR(struct bridge_assoc *, assoc, ao2_alloc(sizeof(*assoc), bridge_assoc_dtor), ao2_cleanup);
346         if (!primary || !assoc || ast_string_field_init(assoc, 64)) {
347                 return NULL;
348         }
349
350         ast_string_field_set(assoc, bridge_id, bridge_id);
351         ast_string_field_set(assoc, secondary_name, secondary_name);
352
353         assoc->primary_snapshot = primary;
354         ao2_ref(primary, +1);
355
356         ao2_ref(assoc, +1);
357         return assoc;
358 }
359
360 static int add_bridge_primary(struct ast_channel_snapshot *primary, const char *bridge_id, const char *secondary_name)
361 {
362         RAII_VAR(struct bridge_assoc *, assoc, bridge_assoc_alloc(primary, bridge_id, secondary_name), ao2_cleanup);
363         if (!assoc) {
364                 return -1;
365         }
366
367         ao2_link(bridge_primaries, assoc);
368         return 0;
369 }
370
371 static void remove_bridge_primary(const char *channel_id)
372 {
373         ao2_find(bridge_primaries, channel_id, OBJ_NODATA | OBJ_MULTIPLE | OBJ_UNLINK | OBJ_KEY);
374 }
375
376 /*! \brief Hashing function for bridge_assoc */
377 static int bridge_assoc_hash(const void *obj, int flags)
378 {
379         const struct bridge_assoc *assoc = obj;
380         const char *uniqueid = obj;
381         if (!(flags & OBJ_KEY)) {
382                 uniqueid = assoc->primary_snapshot->uniqueid;
383         }
384
385         return ast_str_hash(uniqueid);
386 }
387
388 /*! \brief Comparator function for bridge_assoc */
389 static int bridge_assoc_cmp(void *obj, void *arg, int flags)
390 {
391         struct bridge_assoc *assoc1 = obj, *assoc2 = arg;
392         const char *assoc2_id = arg, *assoc1_id = assoc1->primary_snapshot->uniqueid;
393         if (!(flags & OBJ_KEY)) {
394                 assoc2_id = assoc2->primary_snapshot->uniqueid;
395         }
396
397         return !strcmp(assoc1_id, assoc2_id) ? CMP_MATCH | CMP_STOP : 0;
398 }
399
400 static const char *get_caller_uniqueid(struct ast_multi_channel_blob *blob)
401 {
402         struct ast_channel_snapshot *caller = ast_multi_channel_blob_get_channel(blob, "caller");
403         if (!caller) {
404                 return NULL;
405         }
406
407         return caller->uniqueid;
408 }
409
410 /*! \brief Hashing function for dialstatus container */
411 static int dialstatus_hash(const void *obj, int flags)
412 {
413         struct ast_multi_channel_blob *blob = (void *) obj;
414         const char *uniqueid = obj;
415         if (!(flags & OBJ_KEY)) {
416                 uniqueid = get_caller_uniqueid(blob);
417         }
418
419         return ast_str_hash(uniqueid);
420 }
421
422 /*! \brief Comparator function for dialstatus container */
423 static int dialstatus_cmp(void *obj, void *arg, int flags)
424 {
425         struct ast_multi_channel_blob *blob1 = obj, *blob2 = arg;
426         const char *blob2_id = arg, *blob1_id = get_caller_uniqueid(blob1);
427         if (!(flags & OBJ_KEY)) {
428                 blob2_id = get_caller_uniqueid(blob2);
429         }
430
431         return !strcmp(blob1_id, blob2_id) ? CMP_MATCH | CMP_STOP : 0;
432 }
433
434 unsigned int ast_cel_check_enabled(void)
435 {
436         RAII_VAR(struct cel_config *, cfg, ao2_global_obj_ref(cel_configs), ao2_cleanup);
437
438         if (!cfg || !cfg->general) {
439                 return 0;
440         }
441
442         return cfg->general->enable;
443 }
444
445 static int print_app(void *obj, void *arg, int flags)
446 {
447         struct ast_cli_args *a = arg;
448
449         ast_cli(a->fd, "CEL Tracking Application: %s\n", (const char *) obj);
450
451         return 0;
452 }
453
454 static void print_cel_sub(const struct ast_event *event, void *data)
455 {
456         struct ast_cli_args *a = data;
457
458         ast_cli(a->fd, "CEL Event Subscriber: %s\n",
459                         ast_event_get_ie_str(event, AST_EVENT_IE_DESCRIPTION));
460 }
461
462 static char *handle_cli_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
463 {
464         unsigned int i;
465         struct ast_event_sub *sub;
466         RAII_VAR(struct cel_config *, cfg, ao2_global_obj_ref(cel_configs), ao2_cleanup);
467
468         switch (cmd) {
469         case CLI_INIT:
470                 e->command = "cel show status";
471                 e->usage =
472                         "Usage: cel show status\n"
473                         "       Displays the Channel Event Logging system status.\n";
474                 return NULL;
475         case CLI_GENERATE:
476                 return NULL;
477         case CLI_HANDLER:
478                 break;
479         }
480
481         if (a->argc > 3) {
482                 return CLI_SHOWUSAGE;
483         }
484
485         ast_cli(a->fd, "CEL Logging: %s\n", ast_cel_check_enabled() ? "Enabled" : "Disabled");
486
487         if (!cfg || !cfg->general) {
488                 return CLI_SUCCESS;
489         }
490
491         if (!cfg->general->enable) {
492                 return CLI_SUCCESS;
493         }
494
495         for (i = 0; i < (sizeof(cfg->general->events) * 8); i++) {
496                 const char *name;
497
498                 if (!(cfg->general->events & ((int64_t) 1 << i))) {
499                         continue;
500                 }
501
502                 name = ast_cel_get_type_name(i);
503                 if (strcasecmp(name, "Unknown")) {
504                         ast_cli(a->fd, "CEL Tracking Event: %s\n", name);
505                 }
506         }
507
508         ao2_callback(cfg->general->apps, OBJ_NODATA, print_app, a);
509
510         if (!(sub = ast_event_subscribe_new(AST_EVENT_SUB, print_cel_sub, a))) {
511                 return CLI_FAILURE;
512         }
513         ast_event_sub_append_ie_uint(sub, AST_EVENT_IE_EVENTTYPE, AST_EVENT_CEL);
514         ast_event_report_subs(sub);
515         ast_event_sub_destroy(sub);
516         sub = NULL;
517
518         return CLI_SUCCESS;
519 }
520
521 static struct ast_cli_entry cli_status = AST_CLI_DEFINE(handle_cli_status, "Display the CEL status");
522
523 enum ast_cel_event_type ast_cel_str_to_event_type(const char *name)
524 {
525         unsigned int i;
526
527         for (i = 0; i < ARRAY_LEN(cel_event_types); i++) {
528                 if (!cel_event_types[i]) {
529                         continue;
530                 }
531
532                 if (!strcasecmp(name, cel_event_types[i])) {
533                         return i;
534                 }
535         }
536
537         return -1;
538 }
539
540 static int ast_cel_track_event(enum ast_cel_event_type et)
541 {
542         RAII_VAR(struct cel_config *, cfg, ao2_global_obj_ref(cel_configs), ao2_cleanup);
543
544         if (!cfg || !cfg->general) {
545                 return 0;
546         }
547
548         return (cfg->general->events & ((int64_t) 1 << et));
549 }
550
551 static int events_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
552 {
553         struct ast_cel_general_config *cfg = obj;
554         char *events = ast_strdupa(var->value);
555         char *cur_event;
556
557         while ((cur_event = strsep(&events, ","))) {
558                 enum ast_cel_event_type event_type;
559
560                 cur_event = ast_strip(cur_event);
561                 if (ast_strlen_zero(cur_event)) {
562                         continue;
563                 }
564
565                 event_type = ast_cel_str_to_event_type(cur_event);
566
567                 if (event_type == 0) {
568                         /* All events */
569                         cfg->events = (int64_t) -1;
570                 } else if (event_type == -1) {
571                         ast_log(LOG_ERROR, "Unknown event name '%s'\n", cur_event);
572                         return -1;
573                 } else {
574                         cfg->events |= ((int64_t) 1 << event_type);
575                 }
576         }
577
578         return 0;
579 }
580
581 static int apps_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
582 {
583         struct ast_cel_general_config *cfg = obj;
584         char *apps = ast_strdupa(var->value);
585         char *cur_app;
586
587         while ((cur_app = strsep(&apps, ","))) {
588                 cur_app = ast_strip(cur_app);
589                 if (ast_strlen_zero(cur_app)) {
590                         continue;
591                 }
592
593                 cur_app = ast_str_to_lower(cur_app);
594                 ast_str_container_add(cfg->apps, cur_app);
595         }
596
597         return 0;
598 }
599
600 static int do_reload(void)
601 {
602         if (aco_process_config(&cel_cfg_info, 1) == ACO_PROCESS_ERROR) {
603                 return -1;
604         }
605
606         ast_verb(3, "CEL logging %sabled.\n", ast_cel_check_enabled() ? "en" : "dis");
607
608         return 0;
609 }
610
611 const char *ast_cel_get_type_name(enum ast_cel_event_type type)
612 {
613         return S_OR(cel_event_types[type], "Unknown");
614 }
615
616 static int cel_track_app(const char *const_app)
617 {
618         RAII_VAR(struct cel_config *, cfg, ao2_global_obj_ref(cel_configs), ao2_cleanup);
619         RAII_VAR(char *, app, NULL, ao2_cleanup);
620         char *app_lower;
621
622         if (!cfg || !cfg->general) {
623                 return 0;
624         }
625
626         app_lower = ast_str_to_lower(ast_strdupa(const_app));
627         app = ao2_find(cfg->general->apps, app_lower, OBJ_KEY);
628         if (!app) {
629                 return 0;
630         }
631
632         return 1;
633 }
634
635 static int cel_linkedid_ref(const char *linkedid);
636 struct ast_event *ast_cel_create_event(struct ast_channel_snapshot *snapshot,
637                 enum ast_cel_event_type event_type, const char *userdefevname,
638                 struct ast_json *extra, const char *peer_name)
639 {
640         struct timeval eventtime = ast_tvnow();
641         RAII_VAR(char *, extra_txt, NULL, ast_json_free);
642         if (extra) {
643                 extra_txt = ast_json_dump_string(extra);
644         }
645         return ast_event_new(AST_EVENT_CEL,
646                 AST_EVENT_IE_CEL_EVENT_TYPE, AST_EVENT_IE_PLTYPE_UINT, event_type,
647                 AST_EVENT_IE_CEL_EVENT_TIME, AST_EVENT_IE_PLTYPE_UINT, eventtime.tv_sec,
648                 AST_EVENT_IE_CEL_EVENT_TIME_USEC, AST_EVENT_IE_PLTYPE_UINT, eventtime.tv_usec,
649                 AST_EVENT_IE_CEL_USEREVENT_NAME, AST_EVENT_IE_PLTYPE_STR, S_OR(userdefevname, ""),
650                 AST_EVENT_IE_CEL_CIDNAME, AST_EVENT_IE_PLTYPE_STR, snapshot->caller_name,
651                 AST_EVENT_IE_CEL_CIDNUM, AST_EVENT_IE_PLTYPE_STR, snapshot->caller_number,
652                 AST_EVENT_IE_CEL_CIDANI, AST_EVENT_IE_PLTYPE_STR, snapshot->caller_ani,
653                 AST_EVENT_IE_CEL_CIDRDNIS, AST_EVENT_IE_PLTYPE_STR, snapshot->caller_rdnis,
654                 AST_EVENT_IE_CEL_CIDDNID, AST_EVENT_IE_PLTYPE_STR, snapshot->caller_dnid,
655                 AST_EVENT_IE_CEL_EXTEN, AST_EVENT_IE_PLTYPE_STR, snapshot->exten,
656                 AST_EVENT_IE_CEL_CONTEXT, AST_EVENT_IE_PLTYPE_STR, snapshot->context,
657                 AST_EVENT_IE_CEL_CHANNAME, AST_EVENT_IE_PLTYPE_STR, snapshot->name,
658                 AST_EVENT_IE_CEL_APPNAME, AST_EVENT_IE_PLTYPE_STR, snapshot->appl,
659                 AST_EVENT_IE_CEL_APPDATA, AST_EVENT_IE_PLTYPE_STR, snapshot->data,
660                 AST_EVENT_IE_CEL_AMAFLAGS, AST_EVENT_IE_PLTYPE_UINT, snapshot->amaflags,
661                 AST_EVENT_IE_CEL_ACCTCODE, AST_EVENT_IE_PLTYPE_STR, snapshot->accountcode,
662                 AST_EVENT_IE_CEL_PEERACCT, AST_EVENT_IE_PLTYPE_STR, snapshot->peeraccount,
663                 AST_EVENT_IE_CEL_UNIQUEID, AST_EVENT_IE_PLTYPE_STR, snapshot->uniqueid,
664                 AST_EVENT_IE_CEL_LINKEDID, AST_EVENT_IE_PLTYPE_STR, snapshot->linkedid,
665                 AST_EVENT_IE_CEL_USERFIELD, AST_EVENT_IE_PLTYPE_STR, snapshot->userfield,
666                 AST_EVENT_IE_CEL_EXTRA, AST_EVENT_IE_PLTYPE_STR, S_OR(extra_txt, ""),
667                 AST_EVENT_IE_CEL_PEER, AST_EVENT_IE_PLTYPE_STR, S_OR(peer_name, ""),
668                 AST_EVENT_IE_END);
669 }
670
671 static int cel_report_event(struct ast_channel_snapshot *snapshot,
672                 enum ast_cel_event_type event_type, const char *userdefevname,
673                 struct ast_json *extra, const char *peer2_name)
674 {
675         struct ast_event *ev;
676         char *linkedid = ast_strdupa(snapshot->linkedid);
677         const char *peer_name = peer2_name;
678         RAII_VAR(struct bridge_assoc *, assoc, NULL, ao2_cleanup);
679         RAII_VAR(struct cel_config *, cfg, ao2_global_obj_ref(cel_configs), ao2_cleanup);
680
681         if (!cfg || !cfg->general) {
682                 return 0;
683         }
684
685         if (!cfg->general->enable) {
686                 return 0;
687         }
688
689         if (ast_strlen_zero(peer_name)) {
690                 assoc = ao2_find(bridge_primaries, snapshot->uniqueid, OBJ_KEY);
691                 if (assoc) {
692                         peer_name = assoc->secondary_name;
693                 }
694         }
695
696         /* Record the linkedid of new channels if we are tracking LINKEDID_END even if we aren't
697          * reporting on CHANNEL_START so we can track when to send LINKEDID_END */
698         if (ast_cel_track_event(AST_CEL_LINKEDID_END) && event_type == AST_CEL_CHANNEL_START && linkedid) {
699                 if (cel_linkedid_ref(linkedid)) {
700                         return -1;
701                 }
702         }
703
704         if (!ast_cel_track_event(event_type)) {
705                 return 0;
706         }
707
708         if ((event_type == AST_CEL_APP_START || event_type == AST_CEL_APP_END)
709                 && !cel_track_app(snapshot->appl)) {
710                 return 0;
711         }
712
713         ev = ast_cel_create_event(snapshot, event_type, userdefevname, extra, peer_name);
714         if (ev && ast_event_queue(ev)) {
715                 ast_event_destroy(ev);
716                 return -1;
717         }
718
719         return 0;
720 }
721
722 /* called whenever a channel is destroyed or a linkedid is changed to
723  * potentially emit a CEL_LINKEDID_END event */
724 static void check_retire_linkedid(struct ast_channel_snapshot *snapshot)
725 {
726         char *lid;
727
728         /* make sure we need to do all this work */
729
730         if (ast_strlen_zero(snapshot->linkedid) || !ast_cel_track_event(AST_CEL_LINKEDID_END)) {
731                 return;
732         }
733
734         if (!(lid = ao2_find(linkedids, (void *) snapshot->linkedid, OBJ_POINTER))) {
735                 ast_log(LOG_ERROR, "Something weird happened, couldn't find linkedid %s\n", snapshot->linkedid);
736                 return;
737         }
738
739         /* We have a ref for each channel with this linkedid, the link and the above find, so if
740          * before unreffing the channel we have a refcount of 3, we're done. Unlink and report. */
741         if (ao2_ref(lid, -1) == 3) {
742                 ast_str_container_remove(linkedids, lid);
743                 cel_report_event(snapshot, AST_CEL_LINKEDID_END, NULL, NULL, NULL);
744         }
745         ao2_ref(lid, -1);
746 }
747
748 /* Note that no 'chan_fixup' function is provided for this datastore type,
749  * because the channels that will use it will never be involved in masquerades.
750  */
751 static const struct ast_datastore_info fabricated_channel_datastore = {
752         .type = "CEL fabricated channel",
753         .destroy = ast_free_ptr,
754 };
755
756 struct ast_channel *ast_cel_fabricate_channel_from_event(const struct ast_event *event)
757 {
758         struct varshead *headp;
759         struct ast_var_t *newvariable;
760         const char *mixed_name;
761         char timebuf[30];
762         struct ast_channel *tchan;
763         struct ast_cel_event_record record = {
764                 .version = AST_CEL_EVENT_RECORD_VERSION,
765         };
766         struct ast_datastore *datastore;
767         char *app_data;
768         RAII_VAR(struct cel_config *, cfg, ao2_global_obj_ref(cel_configs), ao2_cleanup);
769
770         if (!cfg || !cfg->general) {
771                 return NULL;
772         }
773
774         /* do not call ast_channel_alloc because this is not really a real channel */
775         if (!(tchan = ast_dummy_channel_alloc())) {
776                 return NULL;
777         }
778
779         headp = ast_channel_varshead(tchan);
780
781         /* first, get the variables from the event */
782         if (ast_cel_fill_record(event, &record)) {
783                 ast_channel_unref(tchan);
784                 return NULL;
785         }
786
787         /* next, fill the channel with their data */
788         mixed_name = (record.event_type == AST_CEL_USER_DEFINED)
789                 ? record.user_defined_name : record.event_name;
790         if ((newvariable = ast_var_assign("eventtype", mixed_name))) {
791                 AST_LIST_INSERT_HEAD(headp, newvariable, entries);
792         }
793
794         if (ast_strlen_zero(cfg->general->date_format)) {
795                 snprintf(timebuf, sizeof(timebuf), "%ld.%06ld", (long) record.event_time.tv_sec,
796                                 (long) record.event_time.tv_usec);
797         } else {
798                 struct ast_tm tm;
799                 ast_localtime(&record.event_time, &tm, NULL);
800                 ast_strftime(timebuf, sizeof(timebuf), cfg->general->date_format, &tm);
801         }
802
803         if ((newvariable = ast_var_assign("eventtime", timebuf))) {
804                 AST_LIST_INSERT_HEAD(headp, newvariable, entries);
805         }
806
807         if ((newvariable = ast_var_assign("eventenum", record.event_name))) {
808                 AST_LIST_INSERT_HEAD(headp, newvariable, entries);
809         }
810         if ((newvariable = ast_var_assign("userdeftype", record.user_defined_name))) {
811                 AST_LIST_INSERT_HEAD(headp, newvariable, entries);
812         }
813         if ((newvariable = ast_var_assign("eventextra", record.extra))) {
814                 AST_LIST_INSERT_HEAD(headp, newvariable, entries);
815         }
816
817         ast_channel_caller(tchan)->id.name.valid = 1;
818         ast_channel_caller(tchan)->id.name.str = ast_strdup(record.caller_id_name);
819         ast_channel_caller(tchan)->id.number.valid = 1;
820         ast_channel_caller(tchan)->id.number.str = ast_strdup(record.caller_id_num);
821         ast_channel_caller(tchan)->ani.number.valid = 1;
822         ast_channel_caller(tchan)->ani.number.str = ast_strdup(record.caller_id_ani);
823         ast_channel_redirecting(tchan)->from.number.valid = 1;
824         ast_channel_redirecting(tchan)->from.number.str = ast_strdup(record.caller_id_rdnis);
825         ast_channel_dialed(tchan)->number.str = ast_strdup(record.caller_id_dnid);
826
827         ast_channel_exten_set(tchan, record.extension);
828         ast_channel_context_set(tchan, record.context);
829         ast_channel_name_set(tchan, record.channel_name);
830         ast_channel_uniqueid_set(tchan, record.unique_id);
831         ast_channel_linkedid_set(tchan, record.linked_id);
832         ast_channel_accountcode_set(tchan, record.account_code);
833         ast_channel_peeraccount_set(tchan, record.peer_account);
834         ast_channel_userfield_set(tchan, record.user_field);
835
836         if ((newvariable = ast_var_assign("BRIDGEPEER", record.peer))) {
837                 AST_LIST_INSERT_HEAD(headp, newvariable, entries);
838         }
839
840         ast_channel_amaflags_set(tchan, record.amaflag);
841
842         /* We need to store an 'application name' and 'application
843          * data' on the channel for logging purposes, but the channel
844          * structure only provides a place to store pointers, and it
845          * expects these pointers to be pointing to data that does not
846          * need to be freed. This means that the channel's destructor
847          * does not attempt to free any storage that these pointers
848          * point to. However, we can't provide data in that form directly for
849          * these structure members. In order to ensure that these data
850          * elements have a lifetime that matches the channel's
851          * lifetime, we'll put them in a datastore attached to the
852          * channel, and set's the channel's pointers to point into the
853          * datastore.  The datastore will then be automatically destroyed
854          * when the channel is destroyed.
855          */
856
857         if (!(datastore = ast_datastore_alloc(&fabricated_channel_datastore, NULL))) {
858                 ast_channel_unref(tchan);
859                 return NULL;
860         }
861
862         if (!(app_data = ast_malloc(strlen(record.application_name) + strlen(record.application_data) + 2))) {
863                 ast_datastore_free(datastore);
864                 ast_channel_unref(tchan);
865                 return NULL;
866         }
867
868         ast_channel_appl_set(tchan, strcpy(app_data, record.application_name));
869         ast_channel_data_set(tchan, strcpy(app_data + strlen(record.application_name) + 1,
870                 record.application_data));
871
872         datastore->data = app_data;
873         ast_channel_datastore_add(tchan, datastore);
874
875         return tchan;
876 }
877
878 static int cel_linkedid_ref(const char *linkedid)
879 {
880         char *lid;
881
882         if (ast_strlen_zero(linkedid)) {
883                 ast_log(LOG_ERROR, "The linkedid should never be empty\n");
884                 return -1;
885         }
886
887         if (!(lid = ao2_find(linkedids, (void *) linkedid, OBJ_POINTER))) {
888                 if (!(lid = ao2_alloc(strlen(linkedid) + 1, NULL))) {
889                         return -1;
890                 }
891                 strcpy(lid, linkedid);
892                 if (!ao2_link(linkedids, lid)) {
893                         ao2_ref(lid, -1);
894                         return -1;
895                 }
896                 /* Leave both the link and the alloc refs to show a count of 1 + the link */
897         }
898         /* If we've found, go ahead and keep the ref to increment count of how many channels
899          * have this linkedid. We'll clean it up in check_retire */
900         return 0;
901 }
902
903 int ast_cel_fill_record(const struct ast_event *e, struct ast_cel_event_record *r)
904 {
905         if (r->version != AST_CEL_EVENT_RECORD_VERSION) {
906                 ast_log(LOG_ERROR, "Module ABI mismatch for ast_cel_event_record.  "
907                                 "Please ensure all modules were compiled for "
908                                 "this version of Asterisk.\n");
909                 return -1;
910         }
911
912         r->event_type = ast_event_get_ie_uint(e, AST_EVENT_IE_CEL_EVENT_TYPE);
913
914         r->event_time.tv_sec = ast_event_get_ie_uint(e, AST_EVENT_IE_CEL_EVENT_TIME);
915         r->event_time.tv_usec = ast_event_get_ie_uint(e, AST_EVENT_IE_CEL_EVENT_TIME_USEC);
916
917         r->event_name = ast_cel_get_type_name(r->event_type);
918         if (r->event_type == AST_CEL_USER_DEFINED) {
919                 r->user_defined_name = ast_event_get_ie_str(e, AST_EVENT_IE_CEL_USEREVENT_NAME);
920         } else {
921                 r->user_defined_name = "";
922         }
923
924         r->caller_id_name   = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_CIDNAME), "");
925         r->caller_id_num    = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_CIDNUM), "");
926         r->caller_id_ani    = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_CIDANI), "");
927         r->caller_id_rdnis  = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_CIDRDNIS), "");
928         r->caller_id_dnid   = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_CIDDNID), "");
929         r->extension        = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_EXTEN), "");
930         r->context          = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_CONTEXT), "");
931         r->channel_name     = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_CHANNAME), "");
932         r->application_name = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_APPNAME), "");
933         r->application_data = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_APPDATA), "");
934         r->account_code     = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_ACCTCODE), "");
935         r->peer_account     = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_ACCTCODE), "");
936         r->unique_id        = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_UNIQUEID), "");
937         r->linked_id        = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_LINKEDID), "");
938         r->amaflag          = ast_event_get_ie_uint(e, AST_EVENT_IE_CEL_AMAFLAGS);
939         r->user_field       = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_USERFIELD), "");
940         r->peer             = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_PEER), "");
941         r->extra            = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_EXTRA), "");
942
943         return 0;
944 }
945
946 /*! \brief Typedef for callbacks that get called on channel snapshot updates */
947 typedef void (*cel_channel_snapshot_monitor)(
948         struct ast_channel_snapshot *old_snapshot,
949         struct ast_channel_snapshot *new_snapshot);
950
951 static struct ast_multi_channel_blob *get_dialstatus_blob(const char *uniqueid)
952 {
953         return ao2_find(cel_dialstatus_store, uniqueid, OBJ_KEY | OBJ_UNLINK);
954 }
955
956 static const char *get_blob_variable(struct ast_multi_channel_blob *blob, const char *varname)
957 {
958         struct ast_json *json = ast_multi_channel_blob_get_json(blob);
959         if (!json) {
960                 return NULL;
961         }
962
963         json = ast_json_object_get(json, varname);
964         if (!json) {
965                 return NULL;
966         }
967
968         return ast_json_string_get(json);
969 }
970
971 /*! \brief Handle channel state changes */
972 static void cel_channel_state_change(
973         struct ast_channel_snapshot *old_snapshot,
974         struct ast_channel_snapshot *new_snapshot)
975 {
976         int is_hungup, was_hungup;
977
978         if (!new_snapshot) {
979                 cel_report_event(old_snapshot, AST_CEL_CHANNEL_END, NULL, NULL, NULL);
980                 check_retire_linkedid(old_snapshot);
981                 return;
982         }
983
984         if (!old_snapshot) {
985                 cel_report_event(new_snapshot, AST_CEL_CHANNEL_START, NULL, NULL, NULL);
986                 return;
987         }
988
989         was_hungup = ast_test_flag(&old_snapshot->flags, AST_FLAG_DEAD) ? 1 : 0;
990         is_hungup = ast_test_flag(&new_snapshot->flags, AST_FLAG_DEAD) ? 1 : 0;
991
992         if (!was_hungup && is_hungup) {
993                 RAII_VAR(struct ast_json *, extra, NULL, ast_json_unref);
994                 RAII_VAR(struct ast_multi_channel_blob *, blob, get_dialstatus_blob(new_snapshot->uniqueid), ao2_cleanup);
995                 const char *dialstatus = "";
996                 if (blob && !ast_strlen_zero(get_blob_variable(blob, "dialstatus"))) {
997                         dialstatus = get_blob_variable(blob, "dialstatus");
998                 }
999                 extra = ast_json_pack("{s: i, s: s, s: s}",
1000                         "hangupcause", new_snapshot->hangupcause,
1001                         "hangupsource", new_snapshot->hangupsource,
1002                         "dialstatus", dialstatus);
1003                 cel_report_event(new_snapshot, AST_CEL_HANGUP, NULL, extra, NULL);
1004                 return;
1005         }
1006
1007         if (old_snapshot->state != new_snapshot->state && new_snapshot->state == AST_STATE_UP) {
1008                 cel_report_event(new_snapshot, AST_CEL_ANSWER, NULL, NULL, NULL);
1009                 return;
1010         }
1011 }
1012
1013 static void cel_channel_linkedid_change(
1014         struct ast_channel_snapshot *old_snapshot,
1015         struct ast_channel_snapshot *new_snapshot)
1016 {
1017         if (!old_snapshot || !new_snapshot) {
1018                 return;
1019         }
1020
1021         ast_assert(!ast_strlen_zero(new_snapshot->linkedid));
1022         ast_assert(!ast_strlen_zero(old_snapshot->linkedid));
1023
1024         if (strcmp(old_snapshot->linkedid, new_snapshot->linkedid)) {
1025                 cel_linkedid_ref(new_snapshot->linkedid);
1026                 check_retire_linkedid(old_snapshot);
1027         }
1028 }
1029
1030 static void cel_channel_app_change(
1031         struct ast_channel_snapshot *old_snapshot,
1032         struct ast_channel_snapshot *new_snapshot)
1033 {
1034         if (new_snapshot && old_snapshot
1035                 && !strcmp(old_snapshot->appl, new_snapshot->appl)) {
1036                 return;
1037         }
1038
1039         /* old snapshot has an application, end it */
1040         if (old_snapshot && !ast_strlen_zero(old_snapshot->appl)) {
1041                 cel_report_event(old_snapshot, AST_CEL_APP_END, NULL, NULL, NULL);
1042         }
1043
1044         /* new snapshot has an application, start it */
1045         if (new_snapshot && !ast_strlen_zero(new_snapshot->appl)) {
1046                 cel_report_event(new_snapshot, AST_CEL_APP_START, NULL, NULL, NULL);
1047         }
1048 }
1049
1050 /* \brief Handlers for channel snapshot changes.
1051  * \note Order of the handlers matters. Application changes must come before state
1052  * changes to ensure that hangup notifications occur after application changes.
1053  * Linkedid checking should always come last.
1054  */
1055 cel_channel_snapshot_monitor cel_channel_monitors[] = {
1056         cel_channel_app_change,
1057         cel_channel_state_change,
1058         cel_channel_linkedid_change,
1059 };
1060
1061 static void update_bridge_primary(struct ast_channel_snapshot *snapshot)
1062 {
1063         RAII_VAR(struct bridge_assoc *, assoc, NULL, ao2_cleanup);
1064
1065         if (!snapshot) {
1066                 return;
1067         }
1068
1069         assoc = ao2_find(bridge_primaries, snapshot->uniqueid, OBJ_KEY);
1070         if (!assoc) {
1071                 return;
1072         }
1073
1074         ao2_cleanup(assoc->primary_snapshot);
1075         ao2_ref(snapshot, +1);
1076         assoc->primary_snapshot = snapshot;
1077 }
1078
1079 static int bridge_match_cb(void *obj, void *arg, int flags)
1080 {
1081         struct bridge_assoc *assoc = obj;
1082         char *bridge_id = arg;
1083         if (!strcmp(bridge_id, assoc->bridge_id)) {
1084                 return CMP_MATCH;
1085         }
1086         return 0;
1087 }
1088
1089 static struct bridge_assoc *find_bridge_primary_by_bridge_id(const char *bridge_id)
1090 {
1091         char *dup_id = ast_strdupa(bridge_id);
1092         return ao2_callback(bridge_primaries, 0, bridge_match_cb, dup_id);
1093 }
1094
1095 static void clear_bridge_primary(const char *bridge_id)
1096 {
1097         char *dup_id = ast_strdupa(bridge_id);
1098         ao2_callback(bridge_primaries, OBJ_KEY | OBJ_NODATA | OBJ_UNLINK | OBJ_MULTIPLE, bridge_match_cb, dup_id);
1099 }
1100
1101 static int cel_filter_channel_snapshot(struct ast_channel_snapshot *snapshot)
1102 {
1103         if (!snapshot) {
1104                 return 0;
1105         }
1106         return snapshot->tech_properties & (AST_CHAN_TP_ANNOUNCER | AST_CHAN_TP_RECORDER);
1107 }
1108
1109 static void cel_snapshot_update_cb(void *data, struct stasis_subscription *sub,
1110         struct stasis_topic *topic,
1111         struct stasis_message *message)
1112 {
1113         struct stasis_cache_update *update = stasis_message_data(message);
1114         if (ast_channel_snapshot_type() == update->type) {
1115                 struct ast_channel_snapshot *old_snapshot;
1116                 struct ast_channel_snapshot *new_snapshot;
1117                 size_t i;
1118
1119                 old_snapshot = stasis_message_data(update->old_snapshot);
1120                 new_snapshot = stasis_message_data(update->new_snapshot);
1121
1122                 if (cel_filter_channel_snapshot(old_snapshot) || cel_filter_channel_snapshot(new_snapshot)) {
1123                         return;
1124                 }
1125
1126                 update_bridge_primary(new_snapshot);
1127
1128                 for (i = 0; i < ARRAY_LEN(cel_channel_monitors); ++i) {
1129                         cel_channel_monitors[i](old_snapshot, new_snapshot);
1130                 }
1131         } else if (ast_bridge_snapshot_type() == update->type) {
1132                 struct ast_bridge_snapshot *old_snapshot;
1133                 struct ast_bridge_snapshot *new_snapshot;
1134
1135                 old_snapshot = stasis_message_data(update->old_snapshot);
1136                 new_snapshot = stasis_message_data(update->new_snapshot);
1137
1138                 if (!old_snapshot) {
1139                         return;
1140                 }
1141
1142                 if (!new_snapshot) {
1143                         clear_bridge_primary(old_snapshot->uniqueid);
1144                         return;
1145                 }
1146         }
1147 }
1148
1149 static void cel_bridge_enter_cb(
1150         void *data, struct stasis_subscription *sub,
1151         struct stasis_topic *topic,
1152         struct stasis_message *message)
1153 {
1154         struct ast_bridge_blob *blob = stasis_message_data(message);
1155         struct ast_bridge_snapshot *snapshot = blob->bridge;
1156         struct ast_channel_snapshot *chan_snapshot = blob->channel;
1157         RAII_VAR(struct bridge_assoc *, assoc, find_bridge_primary_by_bridge_id(snapshot->uniqueid), ao2_cleanup);
1158
1159         if (cel_filter_channel_snapshot(chan_snapshot)) {
1160                 return;
1161         }
1162
1163         if (snapshot->capabilities & (AST_BRIDGE_CAPABILITY_1TO1MIX | AST_BRIDGE_CAPABILITY_NATIVE)) {
1164                 if (assoc && assoc->track_as_conf) {
1165                         RAII_VAR(struct ast_json *, extra, NULL, ast_json_unref);
1166                         extra = ast_json_pack("{s: s}", "bridge_id", snapshot->uniqueid);
1167                         if (extra) {
1168                                 cel_report_event(chan_snapshot, AST_CEL_CONF_ENTER, NULL, extra, NULL);
1169                         }
1170                         return;
1171                 }
1172
1173                 if (ao2_container_count(snapshot->channels) == 2) {
1174                         struct ao2_iterator i;
1175                         RAII_VAR(char *, channel_id, NULL, ao2_cleanup);
1176                         RAII_VAR(struct ast_channel_snapshot *, latest_primary, NULL, ao2_cleanup);
1177
1178                         /* get the name of the channel in the container we don't already know the name of */
1179                         i = ao2_iterator_init(snapshot->channels, 0);
1180                         while ((channel_id = ao2_iterator_next(&i))) {
1181                                 if (strcmp(channel_id, chan_snapshot->uniqueid)) {
1182                                         break;
1183                                 }
1184                                 ao2_cleanup(channel_id);
1185                                 channel_id = NULL;
1186                         }
1187                         ao2_iterator_destroy(&i);
1188
1189                         latest_primary = ast_channel_snapshot_get_latest(channel_id);
1190                         if (!latest_primary) {
1191                                 return;
1192                         }
1193
1194                         add_bridge_primary(latest_primary, snapshot->uniqueid, chan_snapshot->name);
1195                         cel_report_event(latest_primary, AST_CEL_BRIDGE_START, NULL, NULL, chan_snapshot->name);
1196                 } else if (ao2_container_count(snapshot->channels) > 2) {
1197                         if (!assoc) {
1198                                 ast_log(LOG_ERROR, "No association found for bridge %s\n", snapshot->uniqueid);
1199                                 return;
1200                         }
1201
1202                         /* this bridge will no longer be treated like a bridge, so mark the bridge_assoc as such */
1203                         if (!assoc->track_as_conf) {
1204                                 RAII_VAR(struct ast_json *, extra, NULL, ast_json_unref);
1205                                 assoc->track_as_conf = 1;
1206
1207                                 extra = ast_json_pack("{s: s, s: s}",
1208                                         "channel_name", chan_snapshot->name,
1209                                         "bridge_id", snapshot->uniqueid);
1210
1211                                 if (extra) {
1212                                         cel_report_event(assoc->primary_snapshot, AST_CEL_BRIDGE_TO_CONF, NULL,
1213                                                 extra, assoc->secondary_name);
1214                                 }
1215
1216                                 ast_string_field_set(assoc, secondary_name, "");
1217                         }
1218                 }
1219         } else if (snapshot->capabilities & AST_BRIDGE_CAPABILITY_MULTIMIX) {
1220                 RAII_VAR(struct ast_json *, extra, NULL, ast_json_unref);
1221                 if (!assoc) {
1222                         add_bridge_primary(chan_snapshot, snapshot->uniqueid, "");
1223                         return;
1224                 }
1225                 extra = ast_json_pack("{s: s}", "bridge_id", snapshot->uniqueid);
1226                 if (extra) {
1227                         cel_report_event(chan_snapshot, AST_CEL_CONF_ENTER, NULL, extra, NULL);
1228                 }
1229         }
1230 }
1231
1232 static void cel_bridge_leave_cb(
1233         void *data, struct stasis_subscription *sub,
1234         struct stasis_topic *topic,
1235         struct stasis_message *message)
1236 {
1237         struct ast_bridge_blob *blob = stasis_message_data(message);
1238         struct ast_bridge_snapshot *snapshot = blob->bridge;
1239         struct ast_channel_snapshot *chan_snapshot = blob->channel;
1240
1241         if (cel_filter_channel_snapshot(chan_snapshot)) {
1242                 return;
1243         }
1244
1245         if (snapshot->capabilities & (AST_BRIDGE_CAPABILITY_1TO1MIX | AST_BRIDGE_CAPABILITY_NATIVE)) {
1246                 RAII_VAR(struct bridge_assoc *, assoc,
1247                         find_bridge_primary_by_bridge_id(snapshot->uniqueid),
1248                         ao2_cleanup);
1249
1250                 if (!assoc) {
1251                         return;
1252                 }
1253
1254                 if (assoc->track_as_conf) {
1255                         RAII_VAR(struct ast_json *, extra, NULL, ast_json_unref);
1256                         extra = ast_json_pack("{s: s}", "bridge_id", snapshot->uniqueid);
1257                         if (extra) {
1258                                 cel_report_event(chan_snapshot, AST_CEL_CONF_EXIT, NULL, extra, NULL);
1259                         }
1260                         return;
1261                 }
1262
1263                 if (ao2_container_count(snapshot->channels) == 1) {
1264                         cel_report_event(assoc->primary_snapshot, AST_CEL_BRIDGE_END, NULL, NULL, assoc->secondary_name);
1265                         remove_bridge_primary(assoc->primary_snapshot->uniqueid);
1266                         return;
1267                 }
1268         } else if (snapshot->capabilities & AST_BRIDGE_CAPABILITY_MULTIMIX) {
1269                 RAII_VAR(struct ast_json *, extra, NULL, ast_json_unref);
1270                 extra = ast_json_pack("{s: s}", "bridge_id", snapshot->uniqueid);
1271                 if (extra) {
1272                         cel_report_event(chan_snapshot, AST_CEL_CONF_EXIT, NULL, extra, NULL);
1273                 }
1274         }
1275 }
1276
1277 static void cel_parking_cb(
1278         void *data, struct stasis_subscription *sub,
1279         struct stasis_topic *topic,
1280         struct stasis_message *message)
1281 {
1282         struct ast_parked_call_payload *parked_payload = stasis_message_data(message);
1283         RAII_VAR(struct ast_json *, extra, NULL, ast_json_unref);
1284         const char *reason = NULL;
1285
1286         switch (parked_payload->event_type) {
1287         case PARKED_CALL:
1288                 extra = ast_json_pack("{s: s, s: s}",
1289                         "parker_dial_string", parked_payload->parker_dial_string,
1290                         "parking_lot", parked_payload->parkinglot);
1291                 if (extra) {
1292                         cel_report_event(parked_payload->parkee, AST_CEL_PARK_START, NULL, extra, NULL);
1293                 }
1294                 return;
1295         case PARKED_CALL_TIMEOUT:
1296                 reason = "ParkedCallTimeOut";
1297                 break;
1298         case PARKED_CALL_GIVEUP:
1299                 reason = "ParkedCallGiveUp";
1300                 break;
1301         case PARKED_CALL_UNPARKED:
1302                 reason = "ParkedCallUnparked";
1303                 break;
1304         case PARKED_CALL_FAILED:
1305                 reason = "ParkedCallFailed";
1306                 break;
1307         case PARKED_CALL_SWAP:
1308                 reason = "ParkedCallSwap";
1309                 break;
1310         }
1311
1312         extra = ast_json_pack("{s: s}", "reason", reason);
1313         if (extra) {
1314                 cel_report_event(parked_payload->parkee, AST_CEL_PARK_END, NULL, extra, NULL);
1315         }
1316 }
1317
1318 static void save_dialstatus(struct ast_multi_channel_blob *blob)
1319 {
1320         ao2_link(cel_dialstatus_store, blob);
1321 }
1322
1323 static void cel_dial_cb(void *data, struct stasis_subscription *sub,
1324         struct stasis_topic *topic,
1325         struct stasis_message *message)
1326 {
1327         struct ast_multi_channel_blob *blob = stasis_message_data(message);
1328
1329         if (cel_filter_channel_snapshot(ast_multi_channel_blob_get_channel(blob, "caller"))) {
1330                 return;
1331         }
1332
1333         if (!get_caller_uniqueid(blob)) {
1334                 return;
1335         }
1336
1337         if (!ast_strlen_zero(get_blob_variable(blob, "forward"))) {
1338                 struct ast_channel_snapshot *caller = ast_multi_channel_blob_get_channel(blob, "caller");
1339                 RAII_VAR(struct ast_json *, extra, NULL, ast_json_unref);
1340                 if (!caller) {
1341                         return;
1342                 }
1343
1344                 extra = ast_json_pack("{s: s}", "forward", get_blob_variable(blob, "forward"));
1345                 if (extra) {
1346                         cel_report_event(caller, AST_CEL_FORWARD, NULL, extra, NULL);
1347                 }
1348         }
1349
1350         if (ast_strlen_zero(get_blob_variable(blob, "dialstatus"))) {
1351                 return;
1352         }
1353
1354         save_dialstatus(blob);
1355 }
1356
1357 static void cel_generic_cb(
1358         void *data, struct stasis_subscription *sub,
1359         struct stasis_topic *topic,
1360         struct stasis_message *message)
1361 {
1362         struct ast_channel_blob *obj = stasis_message_data(message);
1363         int event_type = ast_json_integer_get(ast_json_object_get(obj->blob, "event_type"));
1364         struct ast_json *event_details = ast_json_object_get(obj->blob, "event_details");
1365
1366         switch (event_type) {
1367         case AST_CEL_USER_DEFINED:
1368                 {
1369                         const char *event = ast_json_string_get(ast_json_object_get(event_details, "event"));
1370                         struct ast_json *extra = ast_json_object_get(event_details, "extra");
1371                         cel_report_event(obj->snapshot, event_type, event, extra, NULL);
1372                         break;
1373                 }
1374         default:
1375                 ast_log(LOG_ERROR, "Unhandled %s event blob\n", ast_cel_get_type_name(event_type));
1376                 break;
1377         }
1378 }
1379
1380 static void cel_blind_transfer_cb(
1381         void *data, struct stasis_subscription *sub,
1382         struct stasis_topic *topic,
1383         struct stasis_message *message)
1384 {
1385         struct ast_bridge_blob *obj = stasis_message_data(message);
1386         struct ast_channel_snapshot *chan_snapshot = obj->channel;
1387         struct ast_bridge_snapshot *bridge_snapshot = obj->bridge;
1388         struct ast_json *blob = obj->blob;
1389         struct ast_json *json_exten = ast_json_object_get(blob, "exten");
1390         struct ast_json *json_context = ast_json_object_get(blob, "context");
1391         RAII_VAR(struct ast_json *, extra, NULL, ast_json_unref);
1392         const char *exten, *context;
1393
1394         if (!json_exten || !json_context) {
1395                 return;
1396         }
1397
1398         exten = ast_json_string_get(json_exten);
1399         context = ast_json_string_get(json_context);
1400         if (!exten || !context) {
1401                 return;
1402         }
1403         extra = ast_json_pack("{s: s, s: s, s: s}",
1404                 "extension", exten,
1405                 "context", context,
1406                 "bridge_id", bridge_snapshot->uniqueid);
1407
1408         if (extra) {
1409                 cel_report_event(chan_snapshot, AST_CEL_BLINDTRANSFER, NULL, extra, NULL);
1410         }
1411 }
1412
1413 static void cel_attended_transfer_cb(
1414         void *data, struct stasis_subscription *sub,
1415         struct stasis_topic *topic,
1416         struct stasis_message *message)
1417 {
1418         struct ast_attended_transfer_message *xfer = stasis_message_data(message);
1419         RAII_VAR(struct ast_json *, extra, NULL, ast_json_unref);
1420         struct ast_bridge_snapshot *bridge1, *bridge2;
1421         struct ast_channel_snapshot *channel1, *channel2;
1422
1423         /* Make sure bridge1 is always non-NULL */
1424         if (!xfer->to_transferee.bridge_snapshot) {
1425                 bridge1 = xfer->to_transfer_target.bridge_snapshot;
1426                 bridge2 = xfer->to_transferee.bridge_snapshot;
1427                 channel1 = xfer->to_transfer_target.channel_snapshot;
1428                 channel2 = xfer->to_transferee.channel_snapshot;
1429         } else {
1430                 bridge1 = xfer->to_transferee.bridge_snapshot;
1431                 bridge2 = xfer->to_transfer_target.bridge_snapshot;
1432                 channel1 = xfer->to_transferee.channel_snapshot;
1433                 channel2 = xfer->to_transfer_target.channel_snapshot;
1434         }
1435
1436         switch (xfer->dest_type) {
1437         case AST_ATTENDED_TRANSFER_DEST_FAIL:
1438                 return;
1439                 /* handle these three the same */
1440         case AST_ATTENDED_TRANSFER_DEST_BRIDGE_MERGE:
1441         case AST_ATTENDED_TRANSFER_DEST_LINK:
1442         case AST_ATTENDED_TRANSFER_DEST_THREEWAY:
1443                 extra = ast_json_pack("{s: s, s: s, s: s}",
1444                         "bridge1_id", bridge1->uniqueid,
1445                         "channel2_name", channel2->name,
1446                         "bridge2_id", bridge2->uniqueid);
1447
1448                 if (!extra) {
1449                         return;
1450                 }
1451                 break;
1452         case AST_ATTENDED_TRANSFER_DEST_APP:
1453                 extra = ast_json_pack("{s: s, s: s, s: s}",
1454                         "bridge1_id", bridge1->uniqueid,
1455                         "channel2_name", channel2->name,
1456                         "app", xfer->dest.app);
1457
1458                 if (!extra) {
1459                         return;
1460                 }
1461                 break;
1462         }
1463         cel_report_event(channel1, AST_CEL_ATTENDEDTRANSFER, NULL, extra, NULL);
1464 }
1465
1466 static void cel_pickup_cb(
1467         void *data, struct stasis_subscription *sub,
1468         struct stasis_topic *topic,
1469         struct stasis_message *message)
1470 {
1471         struct ast_multi_channel_blob *obj = stasis_message_data(message);
1472         struct ast_channel_snapshot *channel = ast_multi_channel_blob_get_channel(obj, "channel");
1473         struct ast_channel_snapshot *target = ast_multi_channel_blob_get_channel(obj, "target");
1474
1475         if (!channel || !target) {
1476                 return;
1477         }
1478
1479         cel_report_event(target, AST_CEL_PICKUP, NULL, NULL, channel->name);
1480 }
1481
1482 static void cel_local_cb(
1483         void *data, struct stasis_subscription *sub,
1484         struct stasis_topic *topic,
1485         struct stasis_message *message)
1486 {
1487         struct ast_multi_channel_blob *obj = stasis_message_data(message);
1488         struct ast_channel_snapshot *localone = ast_multi_channel_blob_get_channel(obj, "1");
1489         struct ast_channel_snapshot *localtwo = ast_multi_channel_blob_get_channel(obj, "2");
1490
1491         if (!localone || !localtwo) {
1492                 return;
1493         }
1494
1495         cel_report_event(localone, AST_CEL_LOCAL_OPTIMIZE, NULL, NULL, localtwo->name);
1496 }
1497
1498 static void ast_cel_engine_term(void)
1499 {
1500         aco_info_destroy(&cel_cfg_info);
1501         ao2_global_obj_release(cel_configs);
1502         stasis_message_router_unsubscribe_and_join(cel_state_router);
1503         cel_state_router = NULL;
1504         ao2_cleanup(cel_aggregation_topic);
1505         cel_aggregation_topic = NULL;
1506         ao2_cleanup(cel_topic);
1507         cel_topic = NULL;
1508         cel_channel_forwarder = stasis_unsubscribe_and_join(cel_channel_forwarder);
1509         cel_bridge_forwarder = stasis_unsubscribe_and_join(cel_bridge_forwarder);
1510         cel_parking_forwarder = stasis_unsubscribe_and_join(cel_parking_forwarder);
1511         cel_cel_forwarder = stasis_unsubscribe_and_join(cel_cel_forwarder);
1512         ao2_cleanup(bridge_primaries);
1513         bridge_primaries = NULL;
1514         ast_cli_unregister(&cli_status);
1515         ao2_cleanup(cel_dialstatus_store);
1516         cel_dialstatus_store = NULL;
1517         ao2_cleanup(linkedids);
1518         linkedids = NULL;
1519         STASIS_MESSAGE_TYPE_CLEANUP(cel_generic_type);
1520 }
1521
1522 int ast_cel_engine_init(void)
1523 {
1524         int ret = 0;
1525         if (!(linkedids = ast_str_container_alloc(NUM_APP_BUCKETS))) {
1526                 return -1;
1527         }
1528
1529         if (!(cel_dialstatus_store = ao2_container_alloc(NUM_DIALSTATUS_BUCKETS, dialstatus_hash, dialstatus_cmp))) {
1530                 return -1;
1531         }
1532
1533         if (STASIS_MESSAGE_TYPE_INIT(cel_generic_type)) {
1534                 return -1;
1535         }
1536
1537         if (ast_cli_register(&cli_status)) {
1538                 return -1;
1539         }
1540
1541         bridge_primaries = ao2_container_alloc(BRIDGE_PRIMARY_BUCKETS, bridge_assoc_hash, bridge_assoc_cmp);
1542         if (!bridge_primaries) {
1543                 return -1;
1544         }
1545
1546         cel_aggregation_topic = stasis_topic_create("cel_aggregation_topic");
1547         if (!cel_aggregation_topic) {
1548                 return -1;
1549         }
1550
1551         cel_topic = stasis_topic_create("cel_topic");
1552         if (!cel_topic) {
1553                 return -1;
1554         }
1555
1556         cel_channel_forwarder = stasis_forward_all(
1557                 ast_channel_topic_all_cached(),
1558                 cel_aggregation_topic);
1559         if (!cel_channel_forwarder) {
1560                 return -1;
1561         }
1562
1563         cel_bridge_forwarder = stasis_forward_all(
1564                 ast_bridge_topic_all_cached(),
1565                 cel_aggregation_topic);
1566         if (!cel_bridge_forwarder) {
1567                 return -1;
1568         }
1569
1570         cel_parking_forwarder = stasis_forward_all(
1571                 ast_parking_topic(),
1572                 cel_aggregation_topic);
1573         if (!cel_parking_forwarder) {
1574                 return -1;
1575         }
1576
1577         cel_cel_forwarder = stasis_forward_all(
1578                 ast_cel_topic(),
1579                 cel_aggregation_topic);
1580         if (!cel_cel_forwarder) {
1581                 return -1;
1582         }
1583
1584         cel_state_router = stasis_message_router_create(cel_aggregation_topic);
1585         if (!cel_state_router) {
1586                 return -1;
1587         }
1588
1589         ret |= stasis_message_router_add(cel_state_router,
1590                 stasis_cache_update_type(),
1591                 cel_snapshot_update_cb,
1592                 NULL);
1593
1594         ret |= stasis_message_router_add(cel_state_router,
1595                 ast_channel_dial_type(),
1596                 cel_dial_cb,
1597                 NULL);
1598
1599         ret |= stasis_message_router_add(cel_state_router,
1600                 ast_channel_entered_bridge_type(),
1601                 cel_bridge_enter_cb,
1602                 NULL);
1603
1604         ret |= stasis_message_router_add(cel_state_router,
1605                 ast_channel_left_bridge_type(),
1606                 cel_bridge_leave_cb,
1607                 NULL);
1608
1609         ret |= stasis_message_router_add(cel_state_router,
1610                 ast_parked_call_type(),
1611                 cel_parking_cb,
1612                 NULL);
1613
1614         ret |= stasis_message_router_add(cel_state_router,
1615                 cel_generic_type(),
1616                 cel_generic_cb,
1617                 NULL);
1618
1619         ret |= stasis_message_router_add(cel_state_router,
1620                 ast_blind_transfer_type(),
1621                 cel_blind_transfer_cb,
1622                 NULL);
1623
1624         ret |= stasis_message_router_add(cel_state_router,
1625                 ast_attended_transfer_type(),
1626                 cel_attended_transfer_cb,
1627                 NULL);
1628
1629         ret |= stasis_message_router_add(cel_state_router,
1630                 ast_call_pickup_type(),
1631                 cel_pickup_cb,
1632                 NULL);
1633
1634         ret |= stasis_message_router_add(cel_state_router,
1635                 ast_local_optimization_end_type(),
1636                 cel_local_cb,
1637                 NULL);
1638
1639         /* If somehow we failed to add any routes, just shut down the whole
1640          * thing and fail it.
1641          */
1642         if (ret) {
1643                 ast_cel_engine_term();
1644                 return -1;
1645         }
1646
1647         if (aco_info_init(&cel_cfg_info)) {
1648                 return -1;
1649         }
1650
1651         aco_option_register(&cel_cfg_info, "enable", ACO_EXACT, general_options, "no", OPT_BOOL_T, 1, FLDSET(struct ast_cel_general_config, enable));
1652         aco_option_register(&cel_cfg_info, "dateformat", ACO_EXACT, general_options, "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_cel_general_config, date_format));
1653         aco_option_register_custom(&cel_cfg_info, "apps", ACO_EXACT, general_options, "", apps_handler, 0);
1654         aco_option_register_custom(&cel_cfg_info, "events", ACO_EXACT, general_options, "", events_handler, 0);
1655
1656         aco_process_config(&cel_cfg_info, 0);
1657
1658         ast_register_cleanup(ast_cel_engine_term);
1659
1660         return 0;
1661 }
1662
1663 int ast_cel_engine_reload(void)
1664 {
1665         return do_reload();
1666 }
1667
1668 void ast_cel_publish_event(struct ast_channel *chan,
1669         enum ast_cel_event_type event_type,
1670         struct ast_json *blob)
1671 {
1672         RAII_VAR(struct ast_channel_blob *, obj, NULL, ao2_cleanup);
1673         RAII_VAR(struct ast_json *, cel_blob, NULL, ast_json_unref);
1674         RAII_VAR(struct stasis_message *, message, NULL, ao2_cleanup);
1675         cel_blob = ast_json_pack("{s: i, s: O}",
1676                 "event_type", event_type,
1677                 "event_details", blob);
1678
1679         message = ast_channel_blob_create(chan, cel_generic_type(), cel_blob);
1680         if (message) {
1681                 stasis_publish(ast_cel_topic(), message);
1682         }
1683 }
1684
1685 struct stasis_topic *ast_cel_topic(void)
1686 {
1687         return cel_topic;
1688 }
1689
1690 struct ast_cel_general_config *ast_cel_get_config(void)
1691 {
1692         RAII_VAR(struct cel_config *, mod_cfg, ao2_global_obj_ref(cel_configs), ao2_cleanup);
1693         ao2_ref(mod_cfg->general, +1);
1694         return mod_cfg->general;
1695 }
1696
1697 void ast_cel_set_config(struct ast_cel_general_config *config)
1698 {
1699         RAII_VAR(struct cel_config *, mod_cfg, ao2_global_obj_ref(cel_configs), ao2_cleanup);
1700         ao2_cleanup(mod_cfg->general);
1701         mod_cfg->general = config;
1702         ao2_ref(mod_cfg->general, +1);
1703 }
1704