Wed Jan 8 2020 09:49:43

Asterisk developer's documentation


cel.c
Go to the documentation of this file.
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 /*** MODULEINFO
31  <support_level>core</support_level>
32  ***/
33 
34 #include "asterisk.h"
35 
36 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 413586 $")
37 
38 #include "asterisk/_private.h"
39 
40 #include "asterisk/channel.h"
41 #include "asterisk/pbx.h"
42 #include "asterisk/cel.h"
43 #include "asterisk/logger.h"
44 #include "asterisk/linkedlists.h"
45 #include "asterisk/utils.h"
46 #include "asterisk/config.h"
47 #include "asterisk/cli.h"
48 #include "asterisk/astobj2.h"
49 
50 /*! Config file to load for the CEL feature. */
51 static const char cel_conf_file[] = "cel.conf";
52 
53 /*! Is the CEL subsystem enabled ? */
54 static unsigned char cel_enabled;
55 
56 /*! \brief CEL is off by default */
57 #define CEL_ENABLED_DEFAULT 0
58 
59 /*!
60  * \brief which events we want to track
61  *
62  * \note bit field, up to 64 events
63  */
64 static int64_t eventset;
65 
66 /*!
67  * \brief Maximum possible CEL event IDs
68  * \note This limit is currently imposed by the eventset definition
69  */
70 #define CEL_MAX_EVENT_IDS 64
71 
72 /*!
73  * \brief Track no events by default.
74  */
75 #define CEL_DEFAULT_EVENTS 0
76 
77 /*!
78  * \brief Number of buckets for the appset container
79  */
80 #define NUM_APP_BUCKETS 97
81 
82 /*!
83  * \brief Lock protecting CEL.
84  *
85  * \note It protects during reloads, shutdown, and accesses to
86  * the appset and linkedids containers.
87  */
89 
90 /*!
91  * \brief Container of Asterisk application names
92  *
93  * The apps in this container are the applications that were specified
94  * in the configuration as applications that CEL events should be generated
95  * for when they start and end on a channel.
96  *
97  * \note Accesses to the appset container must be done while
98  * holding the reload_lock.
99  */
100 static struct ao2_container *appset;
101 
102 struct cel_linkedid {
103  /*! Linkedid stored after struct. */
104  const char *id;
105  /*! Number of channels with this linkedid. */
106  unsigned int count;
107 };
108 
109 /*!
110  * \brief Container of channel references to a linkedid for CEL purposes.
111  *
112  * \note Accesses to the linkedids container must be done while
113  * holding the reload_lock.
114  */
115 static struct ao2_container *linkedids;
116 
117 /*!
118  * \brief Configured date format for event timestamps
119  */
120 static char cel_dateformat[256];
121 
122 /*!
123  * \brief Map of ast_cel_event_type to strings
124  */
125 static const char * const cel_event_types[CEL_MAX_EVENT_IDS] = {
126  [0] = "ALL",
127  [AST_CEL_CHANNEL_START] = "CHAN_START",
128  [AST_CEL_CHANNEL_END] = "CHAN_END",
129  [AST_CEL_ANSWER] = "ANSWER",
130  [AST_CEL_HANGUP] = "HANGUP",
131  [AST_CEL_APP_START] = "APP_START",
132  [AST_CEL_APP_END] = "APP_END",
133  [AST_CEL_BRIDGE_START] = "BRIDGE_START",
134  [AST_CEL_BRIDGE_END] = "BRIDGE_END",
135  [AST_CEL_BRIDGE_UPDATE] = "BRIDGE_UPDATE",
136  [AST_CEL_CONF_START] = "CONF_START",
137  [AST_CEL_CONF_END] = "CONF_END",
138  [AST_CEL_PARK_START] = "PARK_START",
139  [AST_CEL_PARK_END] = "PARK_END",
140  [AST_CEL_TRANSFER] = "TRANSFER",
141  [AST_CEL_USER_DEFINED] = "USER_DEFINED",
142  [AST_CEL_CONF_ENTER] = "CONF_ENTER",
143  [AST_CEL_CONF_EXIT] = "CONF_EXIT",
144  [AST_CEL_BLINDTRANSFER] = "BLINDTRANSFER",
145  [AST_CEL_ATTENDEDTRANSFER] = "ATTENDEDTRANSFER",
146  [AST_CEL_PICKUP] = "PICKUP",
147  [AST_CEL_FORWARD] = "FORWARD",
148  [AST_CEL_3WAY_START] = "3WAY_START",
149  [AST_CEL_3WAY_END] = "3WAY_END",
150  [AST_CEL_HOOKFLASH] = "HOOKFLASH",
151  [AST_CEL_LINKEDID_END] = "LINKEDID_END",
152 };
153 
154 /*!
155  * \brief Map of ast_cel_ama_flags to strings
156  */
157 static const char * const cel_ama_flags[AST_CEL_AMA_FLAG_TOTAL] = {
158  [AST_CEL_AMA_FLAG_NONE] = "NONE",
159  [AST_CEL_AMA_FLAG_OMIT] = "OMIT",
160  [AST_CEL_AMA_FLAG_BILLING] = "BILLING",
161  [AST_CEL_AMA_FLAG_DOCUMENTATION] = "DOCUMENTATION",
162 };
163 
164 unsigned int ast_cel_check_enabled(void)
165 {
166  return cel_enabled;
167 }
168 
169 static void print_cel_sub(const struct ast_event *event, void *data)
170 {
171  struct ast_cli_args *a = data;
172 
173  ast_cli(a->fd, "CEL Event Subscriber: %s\n",
175 }
176 
177 static char *handle_cli_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
178 {
179  unsigned int i;
180  struct ast_event_sub *sub;
181 
182  switch (cmd) {
183  case CLI_INIT:
184  e->command = "cel show status";
185  e->usage =
186  "Usage: cel show status\n"
187  " Displays the Channel Event Logging system status.\n";
188  return NULL;
189  case CLI_GENERATE:
190  return NULL;
191  case CLI_HANDLER:
192  break;
193  }
194 
195  if (a->argc > 3) {
196  return CLI_SHOWUSAGE;
197  }
198 
199  ast_cli(a->fd, "CEL Logging: %s\n", cel_enabled ? "Enabled" : "Disabled");
200 
201  if (!cel_enabled) {
202  return CLI_SUCCESS;
203  }
204 
205  for (i = 0; i < (sizeof(eventset) * 8); i++) {
206  const char *name;
207 
208  if (!(eventset & ((int64_t) 1 << i))) {
209  continue;
210  }
211 
212  name = ast_cel_get_type_name(i);
213  if (strcasecmp(name, "Unknown")) {
214  ast_cli(a->fd, "CEL Tracking Event: %s\n", name);
215  }
216  }
217 
218  /* Accesses to the appset container must be done while holding the reload_lock. */
220  if (appset) {
221  struct ao2_iterator iter;
222  char *app;
223 
224  iter = ao2_iterator_init(appset, 0);
225  for (;;) {
226  app = ao2_iterator_next(&iter);
227  if (!app) {
228  break;
229  }
231 
232  ast_cli(a->fd, "CEL Tracking Application: %s\n", app);
233 
234  ao2_ref(app, -1);
236  }
237  ao2_iterator_destroy(&iter);
238  }
240 
242  return CLI_FAILURE;
243  }
247  sub = NULL;
248 
249  return CLI_SUCCESS;
250 }
251 
252 static struct ast_cli_entry cli_status = AST_CLI_DEFINE(handle_cli_status, "Display the CEL status");
253 
255 {
256  unsigned int i;
257 
258  for (i = 0; i < ARRAY_LEN(cel_event_types); i++) {
259  if (!cel_event_types[i]) {
260  continue;
261  }
262 
263  if (!strcasecmp(name, cel_event_types[i])) {
264  return i;
265  }
266  }
267 
268  return -1;
269 }
270 
272 {
273  return (eventset & ((int64_t) 1 << et));
274 }
275 
276 static void parse_events(const char *val)
277 {
278  char *events = ast_strdupa(val);
279  char *cur_event;
280 
281  while ((cur_event = strsep(&events, ","))) {
282  enum ast_cel_event_type event_type;
283 
284  cur_event = ast_strip(cur_event);
285  if (ast_strlen_zero(cur_event)) {
286  continue;
287  }
288 
289  event_type = ast_cel_str_to_event_type(cur_event);
290 
291  if (event_type == 0) {
292  /* All events */
293  eventset = (int64_t) -1;
294  } else if (event_type == -1) {
295  ast_log(LOG_WARNING, "Unknown event name '%s'\n",
296  cur_event);
297  } else {
298  eventset |= ((int64_t) 1 << event_type);
299  }
300  }
301 }
302 
303 static void parse_apps(const char *val)
304 {
305  char *apps = ast_strdupa(val);
306  char *cur_app;
307 
309  ast_log(LOG_WARNING, "An apps= config line, but not tracking APP events\n");
310  return;
311  }
312 
313  while ((cur_app = strsep(&apps, ","))) {
314  char *app;
315 
316  cur_app = ast_strip(cur_app);
317  if (ast_strlen_zero(cur_app)) {
318  continue;
319  }
320 
321  /* The app object is immutable so it doesn't need a lock of its own. */
322  app = ao2_alloc(strlen(cur_app) + 1, NULL);
323  if (!app) {
324  continue;
325  }
326  strcpy(app, cur_app);/* Safe */
327 
328  ao2_link(appset, app);
329  ao2_ref(app, -1);
330  app = NULL;
331  }
332 }
333 
334 static void set_defaults(void)
335 {
336  cel_enabled = CEL_ENABLED_DEFAULT;
337  eventset = CEL_DEFAULT_EVENTS;
338  *cel_dateformat = '\0';
339  ao2_callback(appset, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, NULL, NULL);
340 }
341 
342 static int do_reload(int is_reload)
343 {
344  struct ast_config *config;
345  const char *enabled_value;
346  const char *val;
347  int res = 0;
348  struct ast_flags config_flags = { 0, };
349  const char *s;
350 
352 
353  if (!is_reload) {
354  /* Initialize all settings before first configuration load. */
355  set_defaults();
356  }
357 
358  /*
359  * Unfortunately we have to always load the config file because
360  * other modules read the same file.
361  */
362  config = ast_config_load2(cel_conf_file, "cel", config_flags);
363  if (!config || config == CONFIG_STATUS_FILEINVALID) {
364  ast_log(LOG_WARNING, "Could not load %s\n", cel_conf_file);
365  config = NULL;
366  goto return_cleanup;
367  }
368  if (config == CONFIG_STATUS_FILEUNCHANGED) {
369  /* This should never happen because we always load the config file. */
370  config = NULL;
371  goto return_cleanup;
372  }
373 
374  if (is_reload) {
375  /* Reset all settings before reloading configuration */
376  set_defaults();
377  }
378 
379  if ((enabled_value = ast_variable_retrieve(config, "general", "enable"))) {
380  cel_enabled = ast_true(enabled_value);
381  }
382 
383  if (!cel_enabled) {
384  goto return_cleanup;
385  }
386 
387  /* get the date format for logging */
388  if ((s = ast_variable_retrieve(config, "general", "dateformat"))) {
389  ast_copy_string(cel_dateformat, s, sizeof(cel_dateformat));
390  }
391 
392  if ((val = ast_variable_retrieve(config, "general", "events"))) {
393  parse_events(val);
394  }
395 
396  if ((val = ast_variable_retrieve(config, "general", "apps"))) {
397  parse_apps(val);
398  }
399 
400 return_cleanup:
401  ast_verb(3, "CEL logging %sabled.\n", cel_enabled ? "en" : "dis");
402 
404 
405  if (config) {
406  ast_config_destroy(config);
407  }
408 
409  return res;
410 }
411 
413 {
414  return S_OR(cel_event_types[type], "Unknown");
415 }
416 
418 {
419  if (flag < 0 || flag >= ARRAY_LEN(cel_ama_flags)) {
420  ast_log(LOG_WARNING, "Invalid AMA flag: %u\n", flag);
421  return "Unknown";
422  }
423 
424  return S_OR(cel_ama_flags[flag], "Unknown");
425 }
426 
427 /* called whenever a channel is destroyed or a linkedid is changed to
428  * potentially emit a CEL_LINKEDID_END event */
430 {
431  const char *linkedid = chan->linkedid;
432  struct cel_linkedid *lid;
433  struct cel_linkedid find_lid;
434 
435  if (ast_strlen_zero(linkedid)) {
436  return;
437  }
438 
439  /* Get the lock in case any CEL events are still in flight when we shutdown. */
441 
442  if (!cel_enabled || !ast_cel_track_event(AST_CEL_LINKEDID_END)
443  || !linkedids) {
444  /*
445  * CEL is disabled or we are not tracking linkedids
446  * or the CEL module is shutdown.
447  */
449  return;
450  }
451 
452  find_lid.id = linkedid;
453  lid = ao2_find(linkedids, &find_lid, OBJ_POINTER);
454  if (!lid) {
456 
457  /*
458  * The user may have done a reload to start tracking linkedids
459  * when a call was already in progress. This is an unusual kind
460  * of change to make after starting Asterisk.
461  */
462  ast_log(LOG_ERROR, "Something weird happened, couldn't find linkedid %s\n", linkedid);
463  return;
464  }
465 
466  if (!--lid->count) {
467  /* No channels use this linkedid anymore. */
468  ao2_unlink(linkedids, lid);
470 
471  ast_cel_report_event(chan, AST_CEL_LINKEDID_END, NULL, NULL, NULL);
472  } else {
474  }
475  ao2_ref(lid, -1);
476 }
477 
478 /* Note that no 'chan_fixup' function is provided for this datastore type,
479  * because the channels that will use it will never be involved in masquerades.
480  */
482  .type = "CEL fabricated channel",
483  .destroy = ast_free_ptr,
484 };
485 
487 {
488  struct varshead *headp;
489  struct ast_var_t *newvariable;
490  char timebuf[30];
491  struct ast_channel *tchan;
492  struct ast_cel_event_record record = {
494  };
495  struct ast_datastore *datastore;
496  char *app_data;
497 
498  /* do not call ast_channel_alloc because this is not really a real channel */
499  if (!(tchan = ast_dummy_channel_alloc())) {
500  return NULL;
501  }
502 
503  headp = &tchan->varshead;
504 
505  /* first, get the variables from the event */
506  if (ast_cel_fill_record(event, &record)) {
507  ast_channel_unref(tchan);
508  return NULL;
509  }
510 
511  /* next, fill the channel with their data */
512  if ((newvariable = ast_var_assign("eventtype", record.event_name))) {
513  AST_LIST_INSERT_HEAD(headp, newvariable, entries);
514  }
515 
516  if (ast_strlen_zero(cel_dateformat)) {
517  snprintf(timebuf, sizeof(timebuf), "%ld.%06ld", (long) record.event_time.tv_sec,
518  (long) record.event_time.tv_usec);
519  } else {
520  struct ast_tm tm;
521  ast_localtime(&record.event_time, &tm, NULL);
522  ast_strftime(timebuf, sizeof(timebuf), cel_dateformat, &tm);
523  }
524 
525  if ((newvariable = ast_var_assign("eventtime", timebuf))) {
526  AST_LIST_INSERT_HEAD(headp, newvariable, entries);
527  }
528 
529  if ((newvariable = ast_var_assign("userdeftype", record.user_defined_name))) {
530  AST_LIST_INSERT_HEAD(headp, newvariable, entries);
531  }
532  if ((newvariable = ast_var_assign("eventextra", record.extra))) {
533  AST_LIST_INSERT_HEAD(headp, newvariable, entries);
534  }
535 
536  tchan->caller.id.name.valid = 1;
537  tchan->caller.id.name.str = ast_strdup(record.caller_id_name);
538  tchan->caller.id.number.valid = 1;
539  tchan->caller.id.number.str = ast_strdup(record.caller_id_num);
540  tchan->caller.ani.number.valid = 1;
541  tchan->caller.ani.number.str = ast_strdup(record.caller_id_ani);
542  tchan->redirecting.from.number.valid = 1;
544  tchan->dialed.number.str = ast_strdup(record.caller_id_dnid);
545 
546  ast_copy_string(tchan->exten, record.extension, sizeof(tchan->exten));
547  ast_copy_string(tchan->context, record.context, sizeof(tchan->context));
548  ast_string_field_set(tchan, name, record.channel_name);
549  ast_string_field_set(tchan, uniqueid, record.unique_id);
550  ast_string_field_set(tchan, linkedid, record.linked_id);
552  ast_string_field_set(tchan, peeraccount, record.peer_account);
553  ast_string_field_set(tchan, userfield, record.user_field);
554 
555  if ((newvariable = ast_var_assign("BRIDGEPEER", record.peer))) {
556  AST_LIST_INSERT_HEAD(headp, newvariable, entries);
557  }
558 
559  tchan->amaflags = record.amaflag;
560 
561  /* We need to store an 'application name' and 'application
562  * data' on the channel for logging purposes, but the channel
563  * structure only provides a place to store pointers, and it
564  * expects these pointers to be pointing to data that does not
565  * need to be freed. This means that the channel's destructor
566  * does not attempt to free any storage that these pointers
567  * point to. However, we can't provide data in that form directly for
568  * these structure members. In order to ensure that these data
569  * elements have a lifetime that matches the channel's
570  * lifetime, we'll put them in a datastore attached to the
571  * channel, and set's the channel's pointers to point into the
572  * datastore. The datastore will then be automatically destroyed
573  * when the channel is destroyed.
574  */
575 
576  if (!(datastore = ast_datastore_alloc(&fabricated_channel_datastore, NULL))) {
577  ast_channel_unref(tchan);
578  return NULL;
579  }
580 
581  if (!(app_data = ast_malloc(strlen(record.application_name) + strlen(record.application_data) + 2))) {
582  ast_datastore_free(datastore);
583  ast_channel_unref(tchan);
584  return NULL;
585  }
586 
587  tchan->appl = strcpy(app_data, record.application_name);
588  tchan->data = strcpy(app_data + strlen(record.application_name) + 1,
589  record.application_data);
590 
591  datastore->data = app_data;
592  ast_channel_datastore_add(tchan, datastore);
593 
594  return tchan;
595 }
596 
597 int ast_cel_linkedid_ref(const char *linkedid)
598 {
599  struct cel_linkedid *lid;
600  struct cel_linkedid find_lid;
601 
602  if (ast_strlen_zero(linkedid)) {
603  ast_log(LOG_ERROR, "The linkedid should never be empty\n");
604  return -1;
605  }
606 
607  /* Get the lock in case any CEL events are still in flight when we shutdown. */
609 
610  if (!cel_enabled || !ast_cel_track_event(AST_CEL_LINKEDID_END)) {
611  /* CEL is disabled or we are not tracking linkedids. */
613  return 0;
614  }
615  if (!linkedids) {
616  /* The CEL module is shutdown. Abort. */
618  return -1;
619  }
620 
621  find_lid.id = linkedid;
622  lid = ao2_find(linkedids, &find_lid, OBJ_POINTER);
623  if (!lid) {
624  /*
625  * Changes to the lid->count member are protected by the
626  * reload_lock so the lid object does not need its own lock.
627  */
628  lid = ao2_alloc(sizeof(*lid) + strlen(linkedid) + 1, NULL);
629  if (!lid) {
631  return -1;
632  }
633  lid->id = (char *) (lid + 1);
634  strcpy((char *) lid->id, linkedid);/* Safe */
635 
636  ao2_link(linkedids, lid);
637  }
638  ++lid->count;
640  ao2_ref(lid, -1);
641 
642  return 0;
643 }
644 
645 int ast_cel_report_event(struct ast_channel *chan, enum ast_cel_event_type event_type,
646  const char *userdefevname, const char *extra, struct ast_channel *peer2)
647 {
648  struct timeval eventtime;
649  struct ast_event *ev;
650  const char *peername = "";
651  struct ast_channel *peer;
652 
653  /* Make sure a reload is not occurring while we're checking to see if this
654  * is an event that we care about. We could lose an important event in this
655  * process otherwise. */
657 
658  if (!appset) {
659  /* The CEL module is shutdown. Abort. */
661  return -1;
662  }
663 
664  /* Record the linkedid of new channels if we are tracking LINKEDID_END even if we aren't
665  * reporting on CHANNEL_START so we can track when to send LINKEDID_END */
666  if (cel_enabled && ast_cel_track_event(AST_CEL_LINKEDID_END) && event_type == AST_CEL_CHANNEL_START && chan->linkedid) {
667  if (ast_cel_linkedid_ref(chan->linkedid)) {
669  return -1;
670  }
671  }
672 
673  if (!cel_enabled || !ast_cel_track_event(event_type)) {
675  return 0;
676  }
677 
678  if (event_type == AST_CEL_APP_START || event_type == AST_CEL_APP_END) {
679  char *app;
680  if (!(app = ao2_find(appset, (char *) chan->appl, OBJ_POINTER))) {
682  return 0;
683  }
684  ao2_ref(app, -1);
685  }
686 
688 
689  ast_channel_lock(chan);
690  peer = ast_bridged_channel(chan);
691  if (peer) {
692  ast_channel_ref(peer);
693  }
694  ast_channel_unlock(chan);
695 
696  if (peer) {
697  ast_channel_lock(peer);
698  peername = ast_strdupa(peer->name);
699  ast_channel_unlock(peer);
700  } else if (peer2) {
701  ast_channel_lock(peer2);
702  peername = ast_strdupa(peer2->name);
703  ast_channel_unlock(peer2);
704  }
705 
706  if (!userdefevname) {
707  userdefevname = "";
708  }
709 
710  if (!extra) {
711  extra = "";
712  }
713 
714  eventtime = ast_tvnow();
715 
716  ast_channel_lock(chan);
717 
724  S_COR(chan->caller.id.name.valid, chan->caller.id.name.str, ""),
726  S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, ""),
728  S_COR(chan->caller.ani.number.valid, chan->caller.ani.number.str, ""),
732  S_OR(chan->dialed.number.str, ""),
747 
748  ast_channel_unlock(chan);
749 
750  if (peer) {
751  peer = ast_channel_unref(peer);
752  }
753 
754  if (ev && ast_event_queue(ev)) {
755  ast_event_destroy(ev);
756  return -1;
757  }
758 
759  return 0;
760 }
761 
762 int ast_cel_fill_record(const struct ast_event *e, struct ast_cel_event_record *r)
763 {
765  ast_log(LOG_ERROR, "Module ABI mismatch for ast_cel_event_record. "
766  "Please ensure all modules were compiled for "
767  "this version of Asterisk.\n");
768  return -1;
769  }
770 
772 
775 
776  r->user_defined_name = "";
777 
778  if (r->event_type == AST_CEL_USER_DEFINED) {
781  } else {
783  }
784 
803 
804  return 0;
805 }
806 
807 static int app_hash(const void *obj, const int flags)
808 {
809  return ast_str_case_hash((const char *) obj);
810 }
811 
812 static int app_cmp(void *obj, void *arg, int flags)
813 {
814  const char *app1 = obj;
815  const char *app2 = arg;
816 
817  return !strcasecmp(app1, app2) ? CMP_MATCH : 0;
818 }
819 
820 static int lid_hash(const void *obj, const int flags)
821 {
822  const struct cel_linkedid *lid = obj;
823  const char *key;
824 
825  key = lid->id;
826 
827  return ast_str_case_hash(key);
828 }
829 
830 static int lid_cmp(void *obj, void *arg, int flags)
831 {
832  struct cel_linkedid *lid1 = obj;
833  struct cel_linkedid *lid2 = arg;
834  const char *key;
835 
836  key = lid2->id;
837 
838  return !strcasecmp(lid1->id, key) ? CMP_MATCH : 0;
839 }
840 
841 static void ast_cel_engine_term(void)
842 {
843  /* Get the lock in case any CEL events are still in flight when we shutdown. */
845 
846  if (appset) {
847  ao2_ref(appset, -1);
848  appset = NULL;
849  }
850  if (linkedids) {
851  ao2_ref(linkedids, -1);
852  linkedids = NULL;
853  }
854 
856 
857  ast_cli_unregister(&cli_status);
858 }
859 
861 {
862  /*
863  * Accesses to the appset and linkedids containers have to be
864  * protected by the reload_lock so they don't need a lock of
865  * their own.
866  */
868  if (!appset) {
869  return -1;
870  }
872  if (!linkedids) {
874  return -1;
875  }
876 
877  if (do_reload(0) || ast_cli_register(&cli_status)) {
879  return -1;
880  }
881 
883 
884  return 0;
885 }
886 
888 {
889  return do_reload(1);
890 }
891 
const char * type
Definition: datastore.h:32
const ast_string_field peeraccount
Definition: channel.h:787
const char * account_code
Definition: cel.h:266
the last channel with the given linkedid is retired
Definition: cel.h:92
channel enters a conference
Definition: cel.h:86
const char * caller_id_name
Definition: cel.h:256
#define NUM_APP_BUCKETS
Number of buckets for the appset container.
Definition: cel.c:80
Helper struct for getting the fields out of a CEL event.
Definition: cel.h:241
static char accountcode[AST_MAX_ACCOUNT_CODE]
Definition: chan_iax2.c:383
Channel Event CID name Used by: AST_EVENT_CEL Payload type: STR.
Definition: event_defs.h:151
Channel Event app name Used by: AST_EVENT_CEL Payload type: STR.
Definition: event_defs.h:181
const char * linked_id
Definition: cel.h:269
#define ast_channel_lock(chan)
Definition: channel.h:2466
Main Channel structure associated with a channel.
Definition: channel.h:742
#define CEL_MAX_EVENT_IDS
Maximum possible CEL event IDs.
Definition: cel.c:70
#define AST_CLI_DEFINE(fn, txt,...)
Definition: cli.h:191
An event.
Definition: event.c:85
char * str
Subscriber phone number (Malloced)
Definition: channel.h:241
Asterisk main include file. File version handling, generic pbx functions.
#define ao2_link(arg1, arg2)
Definition: astobj2.h:785
static int do_reload(int is_reload)
Definition: cel.c:342
static int app_cmp(void *obj, void *arg, int flags)
Definition: cel.c:812
static struct ast_cli_entry cli_status
Definition: cel.c:252
const char * ast_variable_retrieve(const struct ast_config *config, const char *category, const char *variable)
Gets a variable.
Definition: config.c:625
static const char config[]
Definition: cdr_csv.c:57
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
char * str
Subscriber phone number (Malloced)
Definition: channel.h:336
struct ast_party_caller caller
Channel Caller ID information.
Definition: channel.h:804
char * strsep(char **str, const char *delims)
const ast_string_field uniqueid
Definition: channel.h:787
static int ast_cel_track_event(enum ast_cel_event_type et)
Definition: cel.c:271
int ast_cli_register(struct ast_cli_entry *e)
Registers a command or an array of commands.
Definition: cli.c:2159
#define ast_strdup(a)
Definition: astmm.h:109
Definition: ast_expr2.c:325
Channel Event extra data Used by: AST_EVENT_CEL Payload type: STR.
Definition: event_defs.h:253
void ast_cel_check_retire_linkedid(struct ast_channel *chan)
Check and potentially retire a Linked ID.
Definition: cel.c:429
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2502
Definition: pbx.c:1301
int ast_cel_engine_reload(void)
Definition: cel.c:887
Call Event Logging API.
struct ast_party_name name
Subscriber name.
Definition: channel.h:290
struct ast_party_id from
Who is redirecting the call (Sent to the party the call is redirected toward)
Definition: channel.h:449
static int app_hash(const void *obj, const int flags)
Definition: cel.c:807
struct ast_var_t * ast_var_assign(const char *name, const char *value)
Definition: chanvars.c:41
const char * user_defined_name
Definition: cel.h:255
char context[AST_MAX_CONTEXT]
Definition: channel.h:868
#define ao2_iterator_next(arg1)
Definition: astobj2.h:1126
void ast_event_report_subs(const struct ast_event_sub *sub)
Report current subscriptions to a subscription subscriber.
Definition: event.c:701
int ast_cli_unregister(struct ast_cli_entry *e)
Unregisters a command or an array of commands.
Definition: cli.c:2153
descriptor for a cli entry.
Definition: cli.h:165
const int argc
Definition: cli.h:154
#define LOG_WARNING
Definition: logger.h:144
int ast_cel_report_event(struct ast_channel *chan, enum ast_cel_event_type event_type, const char *userdefevname, const char *extra, struct ast_channel *peer2)
Report a channel event.
Definition: cel.c:645
static const char app1[]
const char * application_data
Definition: cel.h:265
a bridge is established
Definition: cel.h:62
#define ao2_callback(c, flags, cb_fn, arg)
Definition: astobj2.h:910
const char * application_name
Definition: cel.h:264
Channel Event channel name Used by: AST_EVENT_CEL Payload type: STR.
Definition: event_defs.h:175
struct ast_tm * ast_localtime(const struct timeval *timep, struct ast_tm *p_tm, const char *zone)
Timezone-independent version of localtime_r(3).
Definition: localtime.c:1570
Channel Event UniqueID Used by: AST_EVENT_CEL Payload type: STR.
Definition: event_defs.h:205
Channel Event context name Used by: AST_EVENT_CEL Payload type: STR.
Definition: event_defs.h:169
Channel Event app args/data Used by: AST_EVENT_CEL Payload type: STR.
Definition: event_defs.h:187
Channel Event peeraccount Used by: AST_EVENT_CEL Payload type: STR.
Definition: event_defs.h:247
Channel Event Time (micro-seconds) Used by: AST_EVENT_CEL Payload type: UINT.
Definition: event_defs.h:139
const char * extension
Definition: cel.h:261
Channel Event CID dnid Used by: AST_EVENT_CEL Payload type: STR.
Definition: event_defs.h:229
struct ast_party_redirecting redirecting
Redirecting/Diversion information.
Definition: channel.h:814
channel birth
Definition: cel.h:50
Definition: cli.h:146
Description Used by: AST_EVENT_SUB, AST_EVENT_UNSUB Payload type: STR.
Definition: event_defs.h:259
Structure for a data store type.
Definition: datastore.h:31
Configuration File Parser.
char * str
Subscriber name (Malloced)
Definition: channel.h:214
unsigned int ast_cel_check_enabled(void)
Check to see if CEL is enabled.
Definition: cel.c:164
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:142
const char * caller_id_num
Definition: cel.h:257
#define ast_mutex_lock(a)
Definition: lock.h:155
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags)
Create an iterator for a container.
Definition: astobj2.c:818
Structure for a data store object.
Definition: datastore.h:54
static const char *const cel_event_types[CEL_MAX_EVENT_IDS]
Map of ast_cel_event_type to strings.
Definition: cel.c:125
const char * data
Definition: channel.h:755
void ast_event_sub_destroy(struct ast_event_sub *sub)
Destroy an allocated subscription.
Definition: event.c:971
void ast_cli(int fd, const char *fmt,...)
Definition: cli.c:105
const ast_string_field linkedid
Definition: channel.h:787
const char * extra
Definition: cel.h:273
void ast_free_ptr(void *ptr)
struct ast_config * ast_config_load2(const char *filename, const char *who_asked, struct ast_flags flags)
Load a config file.
Definition: config.c:2499
#define ast_verb(level,...)
Definition: logger.h:243
void ast_config_destroy(struct ast_config *config)
Destroys a config.
Definition: config.c:1037
const char * appl
Definition: channel.h:754
Channel Event Type Used by: AST_EVENT_CEL Payload type: UINT.
Definition: event_defs.h:127
int ast_datastore_free(struct ast_datastore *datastore)
Free a data store object.
Definition: datastore.c:65
static void ast_cel_engine_term(void)
Definition: cel.c:841
static int64_t eventset
which events we want to track
Definition: cel.c:64
static ast_mutex_t reload_lock
Lock protecting CEL.
Definition: cel.c:88
static void print_cel_sub(const struct ast_event *event, void *data)
Definition: cel.c:169
Utility functions.
Channel Event Time (seconds) Used by: AST_EVENT_CEL Payload type: UINT.
Definition: event_defs.h:133
static struct ao2_container * appset
Container of Asterisk application names.
Definition: cel.c:100
Channel Event CID num Used by: AST_EVENT_CEL Payload type: STR.
Definition: event_defs.h:157
const char * ast_cel_get_type_name(enum ast_cel_event_type type)
Get the name of a CEL event type.
Definition: cel.c:412
int ast_cel_engine_init(void)
Definition: cel.c:860
unsigned int flags
Definition: channel.h:850
struct ast_party_id id
Caller party ID.
Definition: channel.h:370
#define CEL_ENABLED_DEFAULT
CEL is off by default.
Definition: cel.c:57
a masquerade happened to alter the participants on a bridge
Definition: cel.h:94
Channel Event extension name Used by: AST_EVENT_CEL Payload type: STR.
Definition: event_defs.h:163
int ast_event_queue(struct ast_event *event)
Queue an event.
Definition: event.c:1517
const char * ast_cel_get_ama_flag_name(enum ast_cel_ama_flag flag)
Convert AMA flag to printable string.
Definition: cel.c:417
static const char app[]
Definition: app_adsiprog.c:49
static char cel_dateformat[256]
Configured date format for event timestamps.
Definition: cel.c:120
struct ast_party_id ani
Automatic Number Identification (ANI)
Definition: channel.h:377
General Asterisk PBX channel definitions.
static void parse_apps(const char *val)
Definition: cel.c:303
struct ast_party_dialed::@155 number
Dialed/Called number.
const int fd
Definition: cli.h:153
static int lid_hash(const void *obj, const int flags)
Definition: cel.c:820
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
static const char *const cel_ama_flags[AST_CEL_AMA_FLAG_TOTAL]
Map of ast_cel_ama_flags to strings.
Definition: cel.c:157
an app ends
Definition: cel.h:60
char * ast_strip(char *s)
Strip leading/trailing whitespace from a string.
Definition: strings.h:155
const char * context
Definition: cel.h:262
#define ao2_ref(o, delta)
Definition: astobj2.h:472
#define S_COR(a, b, c)
returns the equivalent of logic or for strings, with an additional boolean check: second one if not e...
Definition: strings.h:83
int ast_register_atexit(void(*func)(void))
Register a function to be executed before Asterisk exits.
Definition: asterisk.c:998
uint32_t version
struct ABI version
Definition: cel.h:251
Channel Event Userfield Used by: AST_EVENT_CEL Payload type: STR.
Definition: event_defs.h:211
A set of macros to manage forward-linked lists.
hangup terminates connection
Definition: cel.h:54
int ast_cel_linkedid_ref(const char *linkedid)
Inform CEL that a new linkedid is being used.
Definition: cel.c:597
a transfer occurs
Definition: cel.h:78
Channel Event CID RDNIS field Used by: AST_EVENT_CEL Payload type: STR.
Definition: event_defs.h:223
a transfer occurs
Definition: cel.h:74
static const char cel_conf_file[]
Definition: cel.c:51
Core PBX routines and definitions.
a channel is parked
Definition: cel.h:70
a 3-way conference, usually part of a transfer
Definition: cel.h:80
Event type Used by: AST_EVENT_SUB, AST_EVENT_UNSUB Payload type: UINT.
Definition: event_defs.h:95
Must be final entry.
Definition: cel.h:42
a 3-way conference, usually part of a transfer
Definition: cel.h:82
enum ast_cel_event_type event_type
Definition: cel.h:252
struct ast_party_dialed dialed
Dialed/Called information.
Definition: channel.h:797
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: utils.h:663
a transfer occurs
Definition: cel.h:76
#define LOG_ERROR
Definition: logger.h:155
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is &quot;true&quot;. This function checks to see whether a string passed to it is an indication of an &quot;true&quot; value. It checks to see if the string is &quot;yes&quot;, &quot;true&quot;, &quot;y&quot;, &quot;t&quot;, &quot;on&quot; or &quot;1&quot;.
Definition: utils.c:1533
Channel Event User Event Name Used by: AST_EVENT_CEL Payload type: STR.
Definition: event_defs.h:145
#define CLI_SHOWUSAGE
Definition: cli.h:44
Event subscription.
Definition: event.c:124
static void parse_events(const char *val)
Definition: cel.c:276
const char * caller_id_rdnis
Definition: cel.h:259
static struct ast_datastore_info fabricated_channel_datastore
Definition: cel.c:481
const char * peer
Definition: cel.h:272
struct ast_channel * ast_bridged_channel(struct ast_channel *chan)
Find bridged channel.
Definition: channel.c:7160
a conference is started
Definition: cel.h:66
const ast_string_field name
Definition: channel.h:787
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:430
struct ast_datastore * ast_datastore_alloc(const struct ast_datastore_info *info, const char *uid)
Definition: datastore.c:98
const char * id
Definition: cel.c:104
static void set_defaults(void)
Definition: cel.c:334
unsigned int count
Definition: cel.c:106
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
Definition: linkedlists.h:696
#define ao2_find(arg1, arg2, arg3)
Definition: astobj2.h:964
#define ast_channel_unlock(chan)
Definition: channel.h:2467
#define CLI_FAILURE
Definition: cli.h:45
channel end
Definition: cel.h:52
a 3-way conference, usually part of a transfer
Definition: cel.h:84
static const char name[]
char * command
Definition: cli.h:180
static int lid_cmp(void *obj, void *arg, int flags)
Definition: cel.c:830
struct ast_channel * ast_cel_fabricate_channel_from_event(const struct ast_event *event)
Create a fake channel from data in a CEL event.
Definition: cel.c:486
static struct ao2_container * linkedids
Container of channel references to a linkedid for CEL purposes.
Definition: cel.c:115
Channel Event Peer – for Things involving multiple channels, like BRIDGE Used by: AST_EVENT_CEL Paylo...
Definition: event_defs.h:235
Channel Event CID ANI field Used by: AST_EVENT_CEL Payload type: STR.
Definition: event_defs.h:217
int ast_event_sub_append_ie_uint(struct ast_event_sub *sub, enum ast_event_ie_type ie_type, uint32_t uint)
Append a uint parameter to a subscription.
Definition: event.c:761
channel exits a conference
Definition: cel.h:88
int ast_strftime(char *buf, size_t len, const char *format, const struct ast_tm *tm)
Special version of strftime(3) that handles fractions of a second. Takes the same arguments as strfti...
Definition: localtime.c:2351
const ast_string_field userfield
Definition: channel.h:787
const char * caller_id_ani
Definition: cel.h:258
const char * user_field
Definition: cel.h:271
Channel Event AMA flags Used by: AST_EVENT_CEL Payload type: UINT.
Definition: event_defs.h:193
static const char type[]
Definition: chan_nbs.c:57
void ao2_iterator_destroy(struct ao2_iterator *i)
Destroy a container iterator.
Definition: astobj2.c:833
#define AST_CEL_EVENT_RECORD_VERSION
struct ABI version
Definition: cel.h:246
Structure used to handle boolean flags.
Definition: utils.h:200
Support for logging to various files, console and syslog Configuration in file logger.conf.
const char * usage
Definition: cli.h:171
uint32_t ast_event_get_ie_uint(const struct ast_event *event, enum ast_event_ie_type ie_type)
Get the value of an information element that has an integer payload.
Definition: event.c:1075
const char * peer_account
Definition: cel.h:267
#define CLI_SUCCESS
Definition: cli.h:43
void * data
Definition: datastore.h:56
enum ast_cel_event_type ast_cel_str_to_event_type(const char *name)
Get the event type from a string.
Definition: cel.c:254
Channel Event LinkedID Used by: AST_EVENT_CEL Payload type: STR.
Definition: event_defs.h:241
void ast_event_destroy(struct ast_event *event)
Destroy an event.
Definition: event.c:1314
#define ast_channel_ref(c)
Increase channel reference count.
Definition: channel.h:2491
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1053
Standard Command Line Interface.
struct ast_event * ast_event_new(enum ast_event_type event_type,...)
Create a new event.
Definition: event.c:1202
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
#define ao2_container_alloc(arg1, arg2, arg3)
Definition: astobj2.h:734
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:77
A ringing phone is answered.
Definition: cel.h:56
static const char app2[]
channel out of the park
Definition: cel.h:72
const char * unique_id
Definition: cel.h:268
const ast_string_field accountcode
Definition: channel.h:787
a user-defined event, the event name field should be set
Definition: cel.h:90
ast_cel_event_type
CEL event types.
Definition: cel.h:48
const char * caller_id_dnid
Definition: cel.h:260
const char * channel_name
Definition: cel.h:263
static struct adsi_event events[]
Definition: app_adsiprog.c:78
unsigned char valid
TRUE if the name information is valid/present.
Definition: channel.h:229
ast_cel_ama_flag
AMA Flags.
Definition: cel.h:36
#define CONFIG_STATUS_FILEINVALID
Definition: config.h:52
const char * event_name
Definition: cel.h:254
an app starts
Definition: cel.h:58
const char * ast_event_get_ie_str(const struct ast_event *event, enum ast_event_ie_type ie_type)
Get the value of an information element that has a string payload.
Definition: event.c:1102
struct ast_channel * ast_dummy_channel_alloc(void)
Create a fake channel structure.
Definition: channel.c:1391
#define CEL_DEFAULT_EVENTS
Track no events by default.
Definition: cel.c:75
#define ast_malloc(a)
Definition: astmm.h:91
static char * handle_cli_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: cel.c:177
static unsigned char cel_enabled
Definition: cel.c:54
int amaflags
Definition: channel.h:843
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
Definition: channel.c:2590
struct timeval event_time
Definition: cel.h:253
a directed pickup was performed on this channel
Definition: cel.h:96
unsigned char valid
TRUE if the number information is valid/present.
Definition: channel.h:247
struct ast_event_sub * ast_event_subscribe_new(enum ast_event_type type, ast_event_cb_t cb, void *userdata)
Allocate a subscription, but do not activate it.
Definition: event.c:739
#define ao2_unlink(arg1, arg2)
Definition: astobj2.h:817
this call was forwarded somewhere else
Definition: cel.h:98
struct varshead varshead
Definition: channel.h:817
char exten[AST_MAX_EXTENSION]
Definition: channel.h:869
#define AST_MUTEX_DEFINE_STATIC(mutex)
Definition: lock.h:526
static force_inline int attribute_pure ast_str_case_hash(const char *str)
Compute a hash value on a case-insensitive string.
Definition: strings.h:989
a bridge is torn down
Definition: cel.h:64
Channel Event AccountCode Used by: AST_EVENT_CEL Payload type: STR.
Definition: event_defs.h:199
#define ASTERISK_FILE_VERSION(file, version)
Register/unregister a source code file with the core.
Definition: asterisk.h:180
int ast_cel_fill_record(const struct ast_event *event, struct ast_cel_event_record *r)
Fill in an ast_cel_event_record from a CEL event.
Definition: cel.c:762
#define CONFIG_STATUS_FILEUNCHANGED
Definition: config.h:51
#define ast_mutex_unlock(a)
Definition: lock.h:156
a conference is ended
Definition: cel.h:68
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:344
struct ast_party_number number
Subscriber phone number.
Definition: channel.h:292