cel.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902
  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. * \file
  18. *
  19. * \brief Channel Event Logging API
  20. *
  21. * \author Steve Murphy <murf@digium.com>
  22. * \author Russell Bryant <russell@digium.com>
  23. *
  24. * \todo Do thorough testing of all transfer methods to ensure that BLINDTRANSFER,
  25. * ATTENDEDTRANSFER, BRIDGE_START, and BRIDGE_END events are all reported
  26. * as expected.
  27. */
  28. /*** MODULEINFO
  29. <support_level>core</support_level>
  30. ***/
  31. #include "asterisk.h"
  32. ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
  33. #include "asterisk/_private.h"
  34. #include "asterisk/channel.h"
  35. #include "asterisk/pbx.h"
  36. #include "asterisk/cel.h"
  37. #include "asterisk/logger.h"
  38. #include "asterisk/linkedlists.h"
  39. #include "asterisk/utils.h"
  40. #include "asterisk/config.h"
  41. #include "asterisk/cli.h"
  42. #include "asterisk/astobj2.h"
  43. /*! Config file to load for the CEL feature. */
  44. static const char cel_conf_file[] = "cel.conf";
  45. /*! Is the CEL subsystem enabled ? */
  46. static unsigned char cel_enabled;
  47. /*! \brief CEL is off by default */
  48. #define CEL_ENABLED_DEFAULT 0
  49. /*!
  50. * \brief which events we want to track
  51. *
  52. * \note bit field, up to 64 events
  53. */
  54. static int64_t eventset;
  55. /*!
  56. * \brief Maximum possible CEL event IDs
  57. * \note This limit is currently imposed by the eventset definition
  58. */
  59. #define CEL_MAX_EVENT_IDS 64
  60. /*!
  61. * \brief Track no events by default.
  62. */
  63. #define CEL_DEFAULT_EVENTS 0
  64. /*!
  65. * \brief Number of buckets for the appset container
  66. */
  67. #define NUM_APP_BUCKETS 97
  68. /*!
  69. * \brief Lock protecting CEL.
  70. *
  71. * \note It protects during reloads, shutdown, and accesses to
  72. * the appset and linkedids containers.
  73. */
  74. AST_MUTEX_DEFINE_STATIC(reload_lock);
  75. /*!
  76. * \brief Container of Asterisk application names
  77. *
  78. * The apps in this container are the applications that were specified
  79. * in the configuration as applications that CEL events should be generated
  80. * for when they start and end on a channel.
  81. *
  82. * \note Accesses to the appset container must be done while
  83. * holding the reload_lock.
  84. */
  85. static struct ao2_container *appset;
  86. struct cel_linkedid {
  87. /*! Number of channels with this linkedid. */
  88. unsigned int count;
  89. /*! Linkedid stored at end of struct. */
  90. char id[0];
  91. };
  92. /*!
  93. * \brief Container of channel references to a linkedid for CEL purposes.
  94. *
  95. * \note Accesses to the linkedids container must be done while
  96. * holding the reload_lock.
  97. */
  98. static struct ao2_container *linkedids;
  99. /*!
  100. * \brief Configured date format for event timestamps
  101. */
  102. static char cel_dateformat[256];
  103. /*!
  104. * \brief Map of ast_cel_event_type to strings
  105. */
  106. static const char * const cel_event_types[CEL_MAX_EVENT_IDS] = {
  107. [AST_CEL_ALL] = "ALL",
  108. [AST_CEL_CHANNEL_START] = "CHAN_START",
  109. [AST_CEL_CHANNEL_END] = "CHAN_END",
  110. [AST_CEL_ANSWER] = "ANSWER",
  111. [AST_CEL_HANGUP] = "HANGUP",
  112. [AST_CEL_APP_START] = "APP_START",
  113. [AST_CEL_APP_END] = "APP_END",
  114. [AST_CEL_BRIDGE_START] = "BRIDGE_START",
  115. [AST_CEL_BRIDGE_END] = "BRIDGE_END",
  116. [AST_CEL_BRIDGE_UPDATE] = "BRIDGE_UPDATE",
  117. [AST_CEL_CONF_START] = "CONF_START",
  118. [AST_CEL_CONF_END] = "CONF_END",
  119. [AST_CEL_PARK_START] = "PARK_START",
  120. [AST_CEL_PARK_END] = "PARK_END",
  121. [AST_CEL_TRANSFER] = "TRANSFER",
  122. [AST_CEL_USER_DEFINED] = "USER_DEFINED",
  123. [AST_CEL_CONF_ENTER] = "CONF_ENTER",
  124. [AST_CEL_CONF_EXIT] = "CONF_EXIT",
  125. [AST_CEL_BLINDTRANSFER] = "BLINDTRANSFER",
  126. [AST_CEL_ATTENDEDTRANSFER] = "ATTENDEDTRANSFER",
  127. [AST_CEL_PICKUP] = "PICKUP",
  128. [AST_CEL_FORWARD] = "FORWARD",
  129. [AST_CEL_3WAY_START] = "3WAY_START",
  130. [AST_CEL_3WAY_END] = "3WAY_END",
  131. [AST_CEL_HOOKFLASH] = "HOOKFLASH",
  132. [AST_CEL_LINKEDID_END] = "LINKEDID_END",
  133. };
  134. /*!
  135. * \brief Map of ast_cel_ama_flags to strings
  136. */
  137. static const char * const cel_ama_flags[AST_CEL_AMA_FLAG_TOTAL] = {
  138. [AST_CEL_AMA_FLAG_NONE] = "NONE",
  139. [AST_CEL_AMA_FLAG_OMIT] = "OMIT",
  140. [AST_CEL_AMA_FLAG_BILLING] = "BILLING",
  141. [AST_CEL_AMA_FLAG_DOCUMENTATION] = "DOCUMENTATION",
  142. };
  143. unsigned int ast_cel_check_enabled(void)
  144. {
  145. return cel_enabled;
  146. }
  147. static void print_cel_sub(const struct ast_event *event, void *data)
  148. {
  149. struct ast_cli_args *a = data;
  150. ast_cli(a->fd, "CEL Event Subscriber: %s\n",
  151. ast_event_get_ie_str(event, AST_EVENT_IE_DESCRIPTION));
  152. }
  153. static char *handle_cli_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
  154. {
  155. unsigned int i;
  156. struct ast_event_sub *sub;
  157. switch (cmd) {
  158. case CLI_INIT:
  159. e->command = "cel show status";
  160. e->usage =
  161. "Usage: cel show status\n"
  162. " Displays the Channel Event Logging system status.\n";
  163. return NULL;
  164. case CLI_GENERATE:
  165. return NULL;
  166. case CLI_HANDLER:
  167. break;
  168. }
  169. if (a->argc > 3) {
  170. return CLI_SHOWUSAGE;
  171. }
  172. ast_cli(a->fd, "CEL Logging: %s\n", cel_enabled ? "Enabled" : "Disabled");
  173. if (!cel_enabled) {
  174. return CLI_SUCCESS;
  175. }
  176. for (i = 0; i < (sizeof(eventset) * 8); i++) {
  177. const char *name;
  178. if (!(eventset & ((int64_t) 1 << i))) {
  179. continue;
  180. }
  181. name = ast_cel_get_type_name(i);
  182. if (strcasecmp(name, "Unknown")) {
  183. ast_cli(a->fd, "CEL Tracking Event: %s\n", name);
  184. }
  185. }
  186. /* Accesses to the appset container must be done while holding the reload_lock. */
  187. ast_mutex_lock(&reload_lock);
  188. if (appset) {
  189. struct ao2_iterator iter;
  190. char *app;
  191. iter = ao2_iterator_init(appset, 0);
  192. for (;;) {
  193. app = ao2_iterator_next(&iter);
  194. if (!app) {
  195. break;
  196. }
  197. ast_mutex_unlock(&reload_lock);
  198. ast_cli(a->fd, "CEL Tracking Application: %s\n", app);
  199. ao2_ref(app, -1);
  200. ast_mutex_lock(&reload_lock);
  201. }
  202. ao2_iterator_destroy(&iter);
  203. }
  204. ast_mutex_unlock(&reload_lock);
  205. if (!(sub = ast_event_subscribe_new(AST_EVENT_SUB, print_cel_sub, a))) {
  206. return CLI_FAILURE;
  207. }
  208. ast_event_sub_append_ie_uint(sub, AST_EVENT_IE_EVENTTYPE, AST_EVENT_CEL);
  209. ast_event_report_subs(sub);
  210. ast_event_sub_destroy(sub);
  211. sub = NULL;
  212. return CLI_SUCCESS;
  213. }
  214. static struct ast_cli_entry cli_status = AST_CLI_DEFINE(handle_cli_status, "Display the CEL status");
  215. enum ast_cel_event_type ast_cel_str_to_event_type(const char *name)
  216. {
  217. unsigned int i;
  218. for (i = 0; i < ARRAY_LEN(cel_event_types); i++) {
  219. if (cel_event_types[i] && !strcasecmp(name, cel_event_types[i])) {
  220. return i;
  221. }
  222. }
  223. ast_log(LOG_ERROR, "Unknown event name '%s'\n", name);
  224. return -1;
  225. }
  226. static int ast_cel_track_event(enum ast_cel_event_type et)
  227. {
  228. return (eventset & ((int64_t) 1 << et));
  229. }
  230. static void parse_events(const char *val)
  231. {
  232. char *events = ast_strdupa(val);
  233. char *cur_event;
  234. while ((cur_event = strsep(&events, ","))) {
  235. enum ast_cel_event_type event_type;
  236. cur_event = ast_strip(cur_event);
  237. if (ast_strlen_zero(cur_event)) {
  238. continue;
  239. }
  240. event_type = ast_cel_str_to_event_type(cur_event);
  241. if (event_type == AST_CEL_ALL) {
  242. /* All events */
  243. eventset = (int64_t) -1;
  244. } else if (event_type == AST_CEL_INVALID_VALUE) {
  245. ast_log(LOG_WARNING, "Unknown event name '%s'\n",
  246. cur_event);
  247. } else {
  248. eventset |= ((int64_t) 1 << event_type);
  249. }
  250. }
  251. }
  252. static void parse_apps(const char *val)
  253. {
  254. char *apps = ast_strdupa(val);
  255. char *cur_app;
  256. if (!ast_cel_track_event(AST_CEL_APP_START) && !ast_cel_track_event(AST_CEL_APP_END)) {
  257. ast_log(LOG_WARNING, "An apps= config line, but not tracking APP events\n");
  258. return;
  259. }
  260. while ((cur_app = strsep(&apps, ","))) {
  261. char *app;
  262. cur_app = ast_strip(cur_app);
  263. if (ast_strlen_zero(cur_app)) {
  264. continue;
  265. }
  266. /* The app object is immutable so it doesn't need a lock of its own. */
  267. app = ao2_alloc_options(strlen(cur_app) + 1, NULL, AO2_ALLOC_OPT_LOCK_NOLOCK);
  268. if (!app) {
  269. continue;
  270. }
  271. strcpy(app, cur_app);/* Safe */
  272. ao2_link(appset, app);
  273. ao2_ref(app, -1);
  274. app = NULL;
  275. }
  276. }
  277. static void set_defaults(void)
  278. {
  279. cel_enabled = CEL_ENABLED_DEFAULT;
  280. eventset = CEL_DEFAULT_EVENTS;
  281. *cel_dateformat = '\0';
  282. ao2_callback(appset, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, NULL, NULL);
  283. }
  284. static int do_reload(int is_reload)
  285. {
  286. struct ast_config *config;
  287. const char *enabled_value;
  288. const char *val;
  289. int res = 0;
  290. struct ast_flags config_flags = { 0, };
  291. const char *s;
  292. ast_mutex_lock(&reload_lock);
  293. if (!is_reload) {
  294. /* Initialize all settings before first configuration load. */
  295. set_defaults();
  296. }
  297. /*
  298. * Unfortunately we have to always load the config file because
  299. * other modules read the same file.
  300. */
  301. config = ast_config_load2(cel_conf_file, "cel", config_flags);
  302. if (!config || config == CONFIG_STATUS_FILEINVALID) {
  303. ast_log(LOG_WARNING, "Could not load %s\n", cel_conf_file);
  304. config = NULL;
  305. goto return_cleanup;
  306. }
  307. if (config == CONFIG_STATUS_FILEUNCHANGED) {
  308. /* This should never happen because we always load the config file. */
  309. config = NULL;
  310. goto return_cleanup;
  311. }
  312. if (is_reload) {
  313. /* Reset all settings before reloading configuration */
  314. set_defaults();
  315. }
  316. if ((enabled_value = ast_variable_retrieve(config, "general", "enable"))) {
  317. cel_enabled = ast_true(enabled_value);
  318. }
  319. if (!cel_enabled) {
  320. goto return_cleanup;
  321. }
  322. /* get the date format for logging */
  323. if ((s = ast_variable_retrieve(config, "general", "dateformat"))) {
  324. ast_copy_string(cel_dateformat, s, sizeof(cel_dateformat));
  325. }
  326. if ((val = ast_variable_retrieve(config, "general", "events"))) {
  327. parse_events(val);
  328. }
  329. if ((val = ast_variable_retrieve(config, "general", "apps"))) {
  330. parse_apps(val);
  331. }
  332. return_cleanup:
  333. ast_verb(3, "CEL logging %sabled.\n", cel_enabled ? "en" : "dis");
  334. ast_mutex_unlock(&reload_lock);
  335. if (config) {
  336. ast_config_destroy(config);
  337. }
  338. return res;
  339. }
  340. const char *ast_cel_get_type_name(enum ast_cel_event_type type)
  341. {
  342. return S_OR(cel_event_types[type], "Unknown");
  343. }
  344. const char *ast_cel_get_ama_flag_name(enum ast_cel_ama_flag flag)
  345. {
  346. if (flag >= ARRAY_LEN(cel_ama_flags)) {
  347. ast_log(LOG_WARNING, "Invalid AMA flag: %u\n", flag);
  348. return "Unknown";
  349. }
  350. return S_OR(cel_ama_flags[flag], "Unknown");
  351. }
  352. /* called whenever a channel is destroyed or a linkedid is changed to
  353. * potentially emit a CEL_LINKEDID_END event */
  354. void ast_cel_check_retire_linkedid(struct ast_channel *chan)
  355. {
  356. const char *linkedid = ast_channel_linkedid(chan);
  357. struct cel_linkedid *lid;
  358. if (ast_strlen_zero(linkedid)) {
  359. return;
  360. }
  361. /* Get the lock in case any CEL events are still in flight when we shutdown. */
  362. ast_mutex_lock(&reload_lock);
  363. if (!cel_enabled || !ast_cel_track_event(AST_CEL_LINKEDID_END)
  364. || !linkedids) {
  365. /*
  366. * CEL is disabled or we are not tracking linkedids
  367. * or the CEL module is shutdown.
  368. */
  369. ast_mutex_unlock(&reload_lock);
  370. return;
  371. }
  372. lid = ao2_find(linkedids, (void *) linkedid, OBJ_KEY);
  373. if (!lid) {
  374. ast_mutex_unlock(&reload_lock);
  375. /*
  376. * The user may have done a reload to start tracking linkedids
  377. * when a call was already in progress. This is an unusual kind
  378. * of change to make after starting Asterisk.
  379. */
  380. ast_log(LOG_ERROR, "Something weird happened, couldn't find linkedid %s\n", linkedid);
  381. return;
  382. }
  383. if (!--lid->count) {
  384. /* No channels use this linkedid anymore. */
  385. ao2_unlink(linkedids, lid);
  386. ast_mutex_unlock(&reload_lock);
  387. ast_cel_report_event(chan, AST_CEL_LINKEDID_END, NULL, NULL, NULL);
  388. } else {
  389. ast_mutex_unlock(&reload_lock);
  390. }
  391. ao2_ref(lid, -1);
  392. }
  393. /* Note that no 'chan_fixup' function is provided for this datastore type,
  394. * because the channels that will use it will never be involved in masquerades.
  395. */
  396. static const struct ast_datastore_info fabricated_channel_datastore = {
  397. .type = "CEL fabricated channel",
  398. .destroy = ast_free_ptr,
  399. };
  400. struct ast_channel *ast_cel_fabricate_channel_from_event(const struct ast_event *event)
  401. {
  402. struct varshead *headp;
  403. struct ast_var_t *newvariable;
  404. const char *mixed_name;
  405. char timebuf[30];
  406. struct ast_channel *tchan;
  407. struct ast_cel_event_record record = {
  408. .version = AST_CEL_EVENT_RECORD_VERSION,
  409. };
  410. struct ast_datastore *datastore;
  411. char *app_data;
  412. /* do not call ast_channel_alloc because this is not really a real channel */
  413. if (!(tchan = ast_dummy_channel_alloc())) {
  414. return NULL;
  415. }
  416. headp = ast_channel_varshead(tchan);
  417. /* first, get the variables from the event */
  418. if (ast_cel_fill_record(event, &record)) {
  419. ast_channel_unref(tchan);
  420. return NULL;
  421. }
  422. /* next, fill the channel with their data */
  423. mixed_name = (record.event_type == AST_CEL_USER_DEFINED)
  424. ? record.user_defined_name : record.event_name;
  425. if ((newvariable = ast_var_assign("eventtype", mixed_name))) {
  426. AST_LIST_INSERT_HEAD(headp, newvariable, entries);
  427. }
  428. if (ast_strlen_zero(cel_dateformat)) {
  429. snprintf(timebuf, sizeof(timebuf), "%ld.%06ld", (long) record.event_time.tv_sec,
  430. (long) record.event_time.tv_usec);
  431. } else {
  432. struct ast_tm tm;
  433. ast_localtime(&record.event_time, &tm, NULL);
  434. ast_strftime(timebuf, sizeof(timebuf), cel_dateformat, &tm);
  435. }
  436. if ((newvariable = ast_var_assign("eventtime", timebuf))) {
  437. AST_LIST_INSERT_HEAD(headp, newvariable, entries);
  438. }
  439. if ((newvariable = ast_var_assign("eventenum", record.event_name))) {
  440. AST_LIST_INSERT_HEAD(headp, newvariable, entries);
  441. }
  442. if ((newvariable = ast_var_assign("userdeftype", record.user_defined_name))) {
  443. AST_LIST_INSERT_HEAD(headp, newvariable, entries);
  444. }
  445. if ((newvariable = ast_var_assign("eventextra", record.extra))) {
  446. AST_LIST_INSERT_HEAD(headp, newvariable, entries);
  447. }
  448. ast_channel_caller(tchan)->id.name.valid = 1;
  449. ast_channel_caller(tchan)->id.name.str = ast_strdup(record.caller_id_name);
  450. ast_channel_caller(tchan)->id.number.valid = 1;
  451. ast_channel_caller(tchan)->id.number.str = ast_strdup(record.caller_id_num);
  452. ast_channel_caller(tchan)->ani.number.valid = 1;
  453. ast_channel_caller(tchan)->ani.number.str = ast_strdup(record.caller_id_ani);
  454. ast_channel_redirecting(tchan)->from.number.valid = 1;
  455. ast_channel_redirecting(tchan)->from.number.str = ast_strdup(record.caller_id_rdnis);
  456. ast_channel_dialed(tchan)->number.str = ast_strdup(record.caller_id_dnid);
  457. ast_channel_exten_set(tchan, record.extension);
  458. ast_channel_context_set(tchan, record.context);
  459. ast_channel_name_set(tchan, record.channel_name);
  460. ast_channel_uniqueid_set(tchan, record.unique_id);
  461. ast_channel_linkedid_set(tchan, record.linked_id);
  462. ast_channel_accountcode_set(tchan, record.account_code);
  463. ast_channel_peeraccount_set(tchan, record.peer_account);
  464. ast_channel_userfield_set(tchan, record.user_field);
  465. if ((newvariable = ast_var_assign("BRIDGEPEER", record.peer))) {
  466. AST_LIST_INSERT_HEAD(headp, newvariable, entries);
  467. }
  468. ast_channel_amaflags_set(tchan, record.amaflag);
  469. /* We need to store an 'application name' and 'application
  470. * data' on the channel for logging purposes, but the channel
  471. * structure only provides a place to store pointers, and it
  472. * expects these pointers to be pointing to data that does not
  473. * need to be freed. This means that the channel's destructor
  474. * does not attempt to free any storage that these pointers
  475. * point to. However, we can't provide data in that form directly for
  476. * these structure members. In order to ensure that these data
  477. * elements have a lifetime that matches the channel's
  478. * lifetime, we'll put them in a datastore attached to the
  479. * channel, and set's the channel's pointers to point into the
  480. * datastore. The datastore will then be automatically destroyed
  481. * when the channel is destroyed.
  482. */
  483. if (!(datastore = ast_datastore_alloc(&fabricated_channel_datastore, NULL))) {
  484. ast_channel_unref(tchan);
  485. return NULL;
  486. }
  487. if (!(app_data = ast_malloc(strlen(record.application_name) + strlen(record.application_data) + 2))) {
  488. ast_datastore_free(datastore);
  489. ast_channel_unref(tchan);
  490. return NULL;
  491. }
  492. ast_channel_appl_set(tchan, strcpy(app_data, record.application_name));
  493. ast_channel_data_set(tchan, strcpy(app_data + strlen(record.application_name) + 1,
  494. record.application_data));
  495. datastore->data = app_data;
  496. ast_channel_datastore_add(tchan, datastore);
  497. return tchan;
  498. }
  499. int ast_cel_linkedid_ref(const char *linkedid)
  500. {
  501. struct cel_linkedid *lid;
  502. if (ast_strlen_zero(linkedid)) {
  503. ast_log(LOG_ERROR, "The linkedid should never be empty\n");
  504. return -1;
  505. }
  506. /* Get the lock in case any CEL events are still in flight when we shutdown. */
  507. ast_mutex_lock(&reload_lock);
  508. if (!cel_enabled || !ast_cel_track_event(AST_CEL_LINKEDID_END)) {
  509. /* CEL is disabled or we are not tracking linkedids. */
  510. ast_mutex_unlock(&reload_lock);
  511. return 0;
  512. }
  513. if (!linkedids) {
  514. /* The CEL module is shutdown. Abort. */
  515. ast_mutex_unlock(&reload_lock);
  516. return -1;
  517. }
  518. lid = ao2_find(linkedids, (void *) linkedid, OBJ_KEY);
  519. if (!lid) {
  520. /*
  521. * Changes to the lid->count member are protected by the
  522. * reload_lock so the lid object does not need its own lock.
  523. */
  524. lid = ao2_alloc_options(sizeof(*lid) + strlen(linkedid) + 1, NULL,
  525. AO2_ALLOC_OPT_LOCK_NOLOCK);
  526. if (!lid) {
  527. ast_mutex_unlock(&reload_lock);
  528. return -1;
  529. }
  530. strcpy(lid->id, linkedid);/* Safe */
  531. ao2_link(linkedids, lid);
  532. }
  533. ++lid->count;
  534. ast_mutex_unlock(&reload_lock);
  535. ao2_ref(lid, -1);
  536. return 0;
  537. }
  538. int ast_cel_report_event(struct ast_channel *chan, enum ast_cel_event_type event_type,
  539. const char *userdefevname, const char *extra, struct ast_channel *peer2)
  540. {
  541. struct timeval eventtime;
  542. struct ast_event *ev;
  543. const char *peername = "";
  544. struct ast_channel *peer;
  545. char *linkedid = ast_strdupa(ast_channel_linkedid(chan));
  546. /* Make sure a reload is not occurring while we're checking to see if this
  547. * is an event that we care about. We could lose an important event in this
  548. * process otherwise. */
  549. ast_mutex_lock(&reload_lock);
  550. if (!appset) {
  551. /* The CEL module is shutdown. Abort. */
  552. ast_mutex_unlock(&reload_lock);
  553. return -1;
  554. }
  555. /* Record the linkedid of new channels if we are tracking LINKEDID_END even if we aren't
  556. * reporting on CHANNEL_START so we can track when to send LINKEDID_END */
  557. if (cel_enabled && ast_cel_track_event(AST_CEL_LINKEDID_END) && event_type == AST_CEL_CHANNEL_START && linkedid) {
  558. if (ast_cel_linkedid_ref(linkedid)) {
  559. ast_mutex_unlock(&reload_lock);
  560. return -1;
  561. }
  562. }
  563. if (!cel_enabled || !ast_cel_track_event(event_type)) {
  564. ast_mutex_unlock(&reload_lock);
  565. return 0;
  566. }
  567. if (event_type == AST_CEL_APP_START || event_type == AST_CEL_APP_END) {
  568. char *app;
  569. if (!(app = ao2_find(appset, (char *) ast_channel_appl(chan), OBJ_POINTER))) {
  570. ast_mutex_unlock(&reload_lock);
  571. return 0;
  572. }
  573. ao2_ref(app, -1);
  574. }
  575. ast_mutex_unlock(&reload_lock);
  576. ast_channel_lock(chan);
  577. peer = ast_bridged_channel(chan);
  578. if (peer) {
  579. ast_channel_ref(peer);
  580. }
  581. ast_channel_unlock(chan);
  582. if (peer) {
  583. ast_channel_lock(peer);
  584. peername = ast_strdupa(ast_channel_name(peer));
  585. ast_channel_unlock(peer);
  586. } else if (peer2) {
  587. ast_channel_lock(peer2);
  588. peername = ast_strdupa(ast_channel_name(peer2));
  589. ast_channel_unlock(peer2);
  590. }
  591. if (!userdefevname) {
  592. userdefevname = "";
  593. }
  594. if (!extra) {
  595. extra = "";
  596. }
  597. eventtime = ast_tvnow();
  598. ast_channel_lock(chan);
  599. ev = ast_event_new(AST_EVENT_CEL,
  600. AST_EVENT_IE_CEL_EVENT_TYPE, AST_EVENT_IE_PLTYPE_UINT, event_type,
  601. AST_EVENT_IE_CEL_EVENT_TIME, AST_EVENT_IE_PLTYPE_UINT, eventtime.tv_sec,
  602. AST_EVENT_IE_CEL_EVENT_TIME_USEC, AST_EVENT_IE_PLTYPE_UINT, eventtime.tv_usec,
  603. AST_EVENT_IE_CEL_USEREVENT_NAME, AST_EVENT_IE_PLTYPE_STR, userdefevname,
  604. AST_EVENT_IE_CEL_CIDNAME, AST_EVENT_IE_PLTYPE_STR,
  605. S_COR(ast_channel_caller(chan)->id.name.valid, ast_channel_caller(chan)->id.name.str, ""),
  606. AST_EVENT_IE_CEL_CIDNUM, AST_EVENT_IE_PLTYPE_STR,
  607. S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, ""),
  608. AST_EVENT_IE_CEL_CIDANI, AST_EVENT_IE_PLTYPE_STR,
  609. S_COR(ast_channel_caller(chan)->ani.number.valid, ast_channel_caller(chan)->ani.number.str, ""),
  610. AST_EVENT_IE_CEL_CIDRDNIS, AST_EVENT_IE_PLTYPE_STR,
  611. S_COR(ast_channel_redirecting(chan)->from.number.valid, ast_channel_redirecting(chan)->from.number.str, ""),
  612. AST_EVENT_IE_CEL_CIDDNID, AST_EVENT_IE_PLTYPE_STR,
  613. S_OR(ast_channel_dialed(chan)->number.str, ""),
  614. AST_EVENT_IE_CEL_EXTEN, AST_EVENT_IE_PLTYPE_STR, ast_channel_exten(chan),
  615. AST_EVENT_IE_CEL_CONTEXT, AST_EVENT_IE_PLTYPE_STR, ast_channel_context(chan),
  616. AST_EVENT_IE_CEL_CHANNAME, AST_EVENT_IE_PLTYPE_STR, ast_channel_name(chan),
  617. AST_EVENT_IE_CEL_APPNAME, AST_EVENT_IE_PLTYPE_STR, S_OR(ast_channel_appl(chan), ""),
  618. AST_EVENT_IE_CEL_APPDATA, AST_EVENT_IE_PLTYPE_STR, S_OR(ast_channel_data(chan), ""),
  619. AST_EVENT_IE_CEL_AMAFLAGS, AST_EVENT_IE_PLTYPE_UINT, ast_channel_amaflags(chan),
  620. AST_EVENT_IE_CEL_ACCTCODE, AST_EVENT_IE_PLTYPE_STR, ast_channel_accountcode(chan),
  621. AST_EVENT_IE_CEL_PEERACCT, AST_EVENT_IE_PLTYPE_STR, ast_channel_peeraccount(chan),
  622. AST_EVENT_IE_CEL_UNIQUEID, AST_EVENT_IE_PLTYPE_STR, ast_channel_uniqueid(chan),
  623. AST_EVENT_IE_CEL_LINKEDID, AST_EVENT_IE_PLTYPE_STR, ast_channel_linkedid(chan),
  624. AST_EVENT_IE_CEL_USERFIELD, AST_EVENT_IE_PLTYPE_STR, ast_channel_userfield(chan),
  625. AST_EVENT_IE_CEL_EXTRA, AST_EVENT_IE_PLTYPE_STR, extra,
  626. AST_EVENT_IE_CEL_PEER, AST_EVENT_IE_PLTYPE_STR, peername,
  627. AST_EVENT_IE_END);
  628. ast_channel_unlock(chan);
  629. if (peer) {
  630. peer = ast_channel_unref(peer);
  631. }
  632. if (ev && ast_event_queue(ev)) {
  633. ast_event_destroy(ev);
  634. return -1;
  635. }
  636. return 0;
  637. }
  638. int ast_cel_fill_record(const struct ast_event *e, struct ast_cel_event_record *r)
  639. {
  640. if (r->version != AST_CEL_EVENT_RECORD_VERSION) {
  641. ast_log(LOG_ERROR, "Module ABI mismatch for ast_cel_event_record. "
  642. "Please ensure all modules were compiled for "
  643. "this version of Asterisk.\n");
  644. return -1;
  645. }
  646. r->event_type = ast_event_get_ie_uint(e, AST_EVENT_IE_CEL_EVENT_TYPE);
  647. r->event_time.tv_sec = ast_event_get_ie_uint(e, AST_EVENT_IE_CEL_EVENT_TIME);
  648. r->event_time.tv_usec = ast_event_get_ie_uint(e, AST_EVENT_IE_CEL_EVENT_TIME_USEC);
  649. r->event_name = ast_cel_get_type_name(r->event_type);
  650. if (r->event_type == AST_CEL_USER_DEFINED) {
  651. r->user_defined_name = ast_event_get_ie_str(e, AST_EVENT_IE_CEL_USEREVENT_NAME);
  652. } else {
  653. r->user_defined_name = "";
  654. }
  655. r->caller_id_name = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_CIDNAME), "");
  656. r->caller_id_num = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_CIDNUM), "");
  657. r->caller_id_ani = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_CIDANI), "");
  658. r->caller_id_rdnis = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_CIDRDNIS), "");
  659. r->caller_id_dnid = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_CIDDNID), "");
  660. r->extension = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_EXTEN), "");
  661. r->context = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_CONTEXT), "");
  662. r->channel_name = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_CHANNAME), "");
  663. r->application_name = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_APPNAME), "");
  664. r->application_data = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_APPDATA), "");
  665. r->account_code = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_ACCTCODE), "");
  666. r->peer_account = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_ACCTCODE), "");
  667. r->unique_id = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_UNIQUEID), "");
  668. r->linked_id = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_LINKEDID), "");
  669. r->amaflag = ast_event_get_ie_uint(e, AST_EVENT_IE_CEL_AMAFLAGS);
  670. r->user_field = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_USERFIELD), "");
  671. r->peer = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_PEER), "");
  672. r->extra = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_EXTRA), "");
  673. return 0;
  674. }
  675. static int app_hash(const void *obj, const int flags)
  676. {
  677. return ast_str_case_hash((const char *) obj);
  678. }
  679. static int app_cmp(void *obj, void *arg, int flags)
  680. {
  681. const char *app1 = obj;
  682. const char *app2 = arg;
  683. return !strcasecmp(app1, app2) ? CMP_MATCH : 0;
  684. }
  685. static int lid_hash(const void *obj, const int flags)
  686. {
  687. const struct cel_linkedid *lid = obj;
  688. const char *key = obj;
  689. switch (flags & (OBJ_POINTER | OBJ_KEY)) {
  690. case OBJ_POINTER:
  691. default:
  692. key = lid->id;
  693. break;
  694. case OBJ_KEY:
  695. break;
  696. }
  697. return ast_str_case_hash(key);
  698. }
  699. static int lid_cmp(void *obj, void *arg, int flags)
  700. {
  701. struct cel_linkedid *lid1 = obj;
  702. struct cel_linkedid *lid2 = arg;
  703. const char *key = arg;
  704. switch (flags & (OBJ_POINTER | OBJ_KEY)) {
  705. case OBJ_POINTER:
  706. default:
  707. key = lid2->id;
  708. break;
  709. case OBJ_KEY:
  710. break;
  711. }
  712. return !strcasecmp(lid1->id, key) ? CMP_MATCH : 0;
  713. }
  714. static void ast_cel_engine_term(void)
  715. {
  716. /* Get the lock in case any CEL events are still in flight when we shutdown. */
  717. ast_mutex_lock(&reload_lock);
  718. ao2_cleanup(appset);
  719. appset = NULL;
  720. ao2_cleanup(linkedids);
  721. linkedids = NULL;
  722. ast_mutex_unlock(&reload_lock);
  723. ast_cli_unregister(&cli_status);
  724. }
  725. int ast_cel_engine_init(void)
  726. {
  727. /*
  728. * Accesses to the appset and linkedids containers have to be
  729. * protected by the reload_lock so they don't need a lock of
  730. * their own.
  731. */
  732. appset = ao2_container_alloc_options(AO2_ALLOC_OPT_LOCK_NOLOCK, NUM_APP_BUCKETS,
  733. app_hash, app_cmp);
  734. if (!appset) {
  735. return -1;
  736. }
  737. linkedids = ao2_container_alloc_options(AO2_ALLOC_OPT_LOCK_NOLOCK, NUM_APP_BUCKETS,
  738. lid_hash, lid_cmp);
  739. if (!linkedids) {
  740. ast_cel_engine_term();
  741. return -1;
  742. }
  743. if (do_reload(0) || ast_cli_register(&cli_status)) {
  744. ast_cel_engine_term();
  745. return -1;
  746. }
  747. ast_register_cleanup(ast_cel_engine_term);
  748. return 0;
  749. }
  750. int ast_cel_engine_reload(void)
  751. {
  752. return do_reload(1);
  753. }