Merge in the bridge_construction branch to make the system use the Bridging API.
[asterisk/asterisk.git] / main / manager_channels.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2013, Digium, Inc.
5  *
6  * David M. Lee, II <dlee@digium.com>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18
19 /*! \file
20  *
21  * \brief The Asterisk Management Interface - AMI (channel event handling)
22  *
23  * \author David M. Lee, II <dlee@digium.com>
24  *
25  * AMI generated many per-channel and global-channel events by converting Stasis
26  * messages to AMI events. It makes sense to simply put them into a single file.
27  */
28
29 #include "asterisk.h"
30
31 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
32
33 #include "asterisk/callerid.h"
34 #include "asterisk/channel.h"
35 #include "asterisk/manager.h"
36 #include "asterisk/stasis_message_router.h"
37 #include "asterisk/pbx.h"
38 #include "asterisk/stasis_channels.h"
39
40 static struct stasis_message_router *channel_state_router;
41
42 /*** DOCUMENTATION
43         <managerEvent language="en_US" name="Newchannel">
44                 <managerEventInstance class="EVENT_FLAG_CALL">
45                         <synopsis>Raised when a new channel is created.</synopsis>
46                         <syntax>
47                                 <parameter name="Channel">
48                                 </parameter>
49                                 <parameter name="ChannelState">
50                                         <para>A numeric code for the channel's current state, related to ChannelStateDesc</para>
51                                 </parameter>
52                                 <parameter name="ChannelStateDesc">
53                                         <enumlist>
54                                                 <enum name="Down"/>
55                                                 <enum name="Rsrvd"/>
56                                                 <enum name="OffHook"/>
57                                                 <enum name="Dialing"/>
58                                                 <enum name="Ring"/>
59                                                 <enum name="Ringing"/>
60                                                 <enum name="Up"/>
61                                                 <enum name="Busy"/>
62                                                 <enum name="Dialing Offhook"/>
63                                                 <enum name="Pre-ring"/>
64                                                 <enum name="Unknown"/>
65                                         </enumlist>
66                                 </parameter>
67                                 <parameter name="CallerIDNum">
68                                 </parameter>
69                                 <parameter name="CallerIDName">
70                                 </parameter>
71                                 <parameter name="ConnectedLineNum">
72                                 </parameter>
73                                 <parameter name="ConnectedLineName">
74                                 </parameter>
75                                 <parameter name="AccountCode">
76                                 </parameter>
77                                 <parameter name="Context">
78                                 </parameter>
79                                 <parameter name="Exten">
80                                 </parameter>
81                                 <parameter name="Priority">
82                                 </parameter>
83                                 <parameter name="Uniqueid">
84                                 </parameter>
85                         </syntax>
86                 </managerEventInstance>
87         </managerEvent>
88         <managerEvent language="en_US" name="Newstate">
89                 <managerEventInstance class="EVENT_FLAG_CALL">
90                         <synopsis>Raised when a channel's state changes.</synopsis>
91                         <syntax>
92                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='Newchannel']/managerEventInstance/syntax/parameter)" />
93                         </syntax>
94                 </managerEventInstance>
95         </managerEvent>
96         <managerEvent language="en_US" name="Hangup">
97                 <managerEventInstance class="EVENT_FLAG_CALL">
98                         <synopsis>Raised when a channel is hung up.</synopsis>
99                         <syntax>
100                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='Newchannel']/managerEventInstance/syntax/parameter)" />
101                                 <parameter name="Cause">
102                                         <para>A numeric cause code for why the channel was hung up.</para>
103                                 </parameter>
104                                 <parameter name="Cause-txt">
105                                         <para>A description of why the channel was hung up.</para>
106                                 </parameter>
107                         </syntax>
108                 </managerEventInstance>
109         </managerEvent>
110         <managerEvent language="en_US" name="HangupRequest">
111                 <managerEventInstance class="EVENT_FLAG_CALL">
112                         <synopsis>Raised when a hangup is requested.</synopsis>
113                         <syntax>
114                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='Newchannel']/managerEventInstance/syntax/parameter)" />
115                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='Hangup']/managerEventInstance/syntax/parameter[@name='Cause'])" />
116                         </syntax>
117                 </managerEventInstance>
118         </managerEvent>
119         <managerEvent language="en_US" name="SoftHangupRequest">
120                 <managerEventInstance class="EVENT_FLAG_CALL">
121                         <synopsis>Raised when a soft hangup is requested with a specific cause code.</synopsis>
122                         <syntax>
123                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='Newchannel']/managerEventInstance/syntax/parameter)" />
124                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='Hangup']/managerEventInstance/syntax/parameter[@name='Cause'])" />
125                         </syntax>
126                 </managerEventInstance>
127         </managerEvent>
128         <managerEvent language="en_US" name="NewExten">
129                 <managerEventInstance class="EVENT_FLAG_DIALPLAN">
130                         <synopsis>Raised when a channel enters a new context, extension, priority.</synopsis>
131                         <syntax>
132                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='Newchannel']/managerEventInstance/syntax/parameter)" />
133                                 <parameter name="Extension">
134                                         <para>Deprecated in 12, but kept for
135                                         backward compatability. Please use
136                                         'Exten' instead.</para>
137                                 </parameter>
138                                 <parameter name="Application">
139                                         <para>The application about to be executed.</para>
140                                 </parameter>
141                                 <parameter name="AppData">
142                                         <para>The data to be passed to the application.</para>
143                                 </parameter>
144                         </syntax>
145                 </managerEventInstance>
146         </managerEvent>
147         <managerEvent language="en_US" name="NewCallerid">
148                 <managerEventInstance class="EVENT_FLAG_CALL">
149                         <synopsis>Raised when a channel receives new Caller ID information.</synopsis>
150                         <syntax>
151                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='Newchannel']/managerEventInstance/syntax/parameter)" />
152                                 <parameter name="CID-CallingPres">
153                                         <para>A description of the Caller ID presentation.</para>
154                                 </parameter>
155                         </syntax>
156                 </managerEventInstance>
157         </managerEvent>
158         <managerEvent language="en_US" name="DialBegin">
159                 <managerEventInstance class="EVENT_FLAG_CALL">
160                         <synopsis>Raised when a dial action has started.</synopsis>
161                         <syntax>
162                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='Newchannel']/managerEventInstance/syntax/parameter)" />
163                                 <parameter name="ChannelDest">
164                                 </parameter>
165                                 <parameter name="ChannelStateDest">
166                                         <para>A numeric code for the channel's current state, related to ChannelStateDescDest</para>
167                                 </parameter>
168                                 <parameter name="ChannelStateDescDest">
169                                         <enumlist>
170                                                 <enum name="Down"/>
171                                                 <enum name="Rsrvd"/>
172                                                 <enum name="OffHook"/>
173                                                 <enum name="Dialing"/>
174                                                 <enum name="Ring"/>
175                                                 <enum name="Ringing"/>
176                                                 <enum name="Up"/>
177                                                 <enum name="Busy"/>
178                                                 <enum name="Dialing Offhook"/>
179                                                 <enum name="Pre-ring"/>
180                                                 <enum name="Unknown"/>
181                                         </enumlist>
182                                 </parameter>
183                                 <parameter name="CallerIDNumDest">
184                                 </parameter>
185                                 <parameter name="CallerIDNameDest">
186                                 </parameter>
187                                 <parameter name="ConnectedLineNumDest">
188                                 </parameter>
189                                 <parameter name="ConnectedLineNameDest">
190                                 </parameter>
191                                 <parameter name="AccountCodeDest">
192                                 </parameter>
193                                 <parameter name="ContextDest">
194                                 </parameter>
195                                 <parameter name="ExtenDest">
196                                 </parameter>
197                                 <parameter name="PriorityDest">
198                                 </parameter>
199                                 <parameter name="UniqueidDest">
200                                 </parameter>
201                                 <parameter name="DialString">
202                                         <para>The non-technology specific device being dialed.</para>
203                                 </parameter>
204                         </syntax>
205                         <see-also>
206                                 <ref type="application">Dial</ref>
207                         </see-also>
208                 </managerEventInstance>
209         </managerEvent>
210         <managerEvent language="en_US" name="DialEnd">
211                 <managerEventInstance class="EVENT_FLAG_CALL">
212                         <synopsis>Raised when a dial action has completed.</synopsis>
213                         <syntax>
214                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='Newchannel']/managerEventInstance/syntax/parameter)" />
215                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='DialBegin']/managerEventInstance/syntax/parameter[contains(@name, 'Dest')])" />
216                                 <parameter name="DialStatus">
217                                         <para>The result of the dial operation.</para>
218                                         <enumlist>
219                                                 <enum name="ANSWER" />
220                                                 <enum name="BUSY" />
221                                                 <enum name="CANCEL" />
222                                                 <enum name="CHANUNAVAIL" />
223                                                 <enum name="CONGESTION" />
224                                                 <enum name="NOANSWER" />
225                                         </enumlist>
226                                 </parameter>
227                         </syntax>
228                         <see-also>
229                                 <ref type="application">Dial</ref>
230                         </see-also>
231                 </managerEventInstance>
232         </managerEvent>
233  ***/
234
235 struct ast_str *ast_manager_build_channel_state_string_suffix(
236                 const struct ast_channel_snapshot *snapshot,
237                 const char *suffix)
238 {
239         struct ast_str *out = ast_str_create(1024);
240         int res = 0;
241         if (!out) {
242                 return NULL;
243         }
244         res = ast_str_set(&out, 0,
245                 "Channel%s: %s\r\n"
246                 "ChannelState%s: %d\r\n"
247                 "ChannelStateDesc%s: %s\r\n"
248                 "CallerIDNum%s: %s\r\n"
249                 "CallerIDName%s: %s\r\n"
250                 "ConnectedLineNum%s: %s\r\n"
251                 "ConnectedLineName%s: %s\r\n"
252                 "AccountCode%s: %s\r\n"
253                 "Context%s: %s\r\n"
254                 "Exten%s: %s\r\n"
255                 "Priority%s: %d\r\n"
256                 "Uniqueid%s: %s\r\n",
257                 suffix, snapshot->name,
258                 suffix, snapshot->state,
259                 suffix, ast_state2str(snapshot->state),
260                 suffix, S_OR(snapshot->caller_number, "<unknown>"),
261                 suffix, S_OR(snapshot->caller_name, "<unknown>"),
262                 suffix, S_OR(snapshot->connected_number, "<unknown>"),
263                 suffix, S_OR(snapshot->connected_name, "<unknown>"),
264                 suffix, snapshot->accountcode,
265                 suffix, snapshot->context,
266                 suffix, snapshot->exten,
267                 suffix, snapshot->priority,
268                 suffix, snapshot->uniqueid);
269
270         if (!res) {
271                 return NULL;
272         }
273
274         if (snapshot->manager_vars) {
275                 struct ast_var_t *var;
276                 AST_LIST_TRAVERSE(snapshot->manager_vars, var, entries) {
277                         ast_str_append(&out, 0, "ChanVariable%s: %s=%s\r\n",
278                                        suffix,
279                                        var->name, var->value);
280                 }
281         }
282
283         return out;
284 }
285
286 struct ast_str *ast_manager_build_channel_state_string(
287                 const struct ast_channel_snapshot *snapshot)
288 {
289         return ast_manager_build_channel_state_string_suffix(snapshot, "");
290 }
291
292 /*! \brief Typedef for callbacks that get called on channel snapshot updates */
293 typedef struct ast_manager_event_blob *(*channel_snapshot_monitor)(
294         struct ast_channel_snapshot *old_snapshot,
295         struct ast_channel_snapshot *new_snapshot);
296
297 /*! \brief Handle channel state changes */
298 static struct ast_manager_event_blob *channel_state_change(
299         struct ast_channel_snapshot *old_snapshot,
300         struct ast_channel_snapshot *new_snapshot)
301 {
302         int is_hungup, was_hungup;
303
304         if (!new_snapshot) {
305                 /* Ignore cache clearing events; we'll see the hangup first */
306                 return NULL;
307         }
308
309         /* The Newchannel, Newstate and Hangup events are closely related, in
310          * in that they are mutually exclusive, basically different flavors
311          * of a new channel state event.
312          */
313
314         if (!old_snapshot) {
315                 return ast_manager_event_blob_create(
316                         EVENT_FLAG_CALL, "Newchannel", NO_EXTRA_FIELDS);
317         }
318
319         was_hungup = ast_test_flag(&old_snapshot->flags, AST_FLAG_ZOMBIE) ? 1 : 0;
320         is_hungup = ast_test_flag(&new_snapshot->flags, AST_FLAG_ZOMBIE) ? 1 : 0;
321
322         if (!was_hungup && is_hungup) {
323                 return ast_manager_event_blob_create(
324                         EVENT_FLAG_CALL, "Hangup",
325                         "Cause: %d\r\n"
326                         "Cause-txt: %s\r\n",
327                         new_snapshot->hangupcause,
328                         ast_cause2str(new_snapshot->hangupcause));
329         }
330
331         if (old_snapshot->state != new_snapshot->state) {
332                 return ast_manager_event_blob_create(
333                         EVENT_FLAG_CALL, "Newstate", NO_EXTRA_FIELDS);
334         }
335
336         /* No event */
337         return NULL;
338 }
339
340 static struct ast_manager_event_blob *channel_newexten(
341         struct ast_channel_snapshot *old_snapshot,
342         struct ast_channel_snapshot *new_snapshot)
343 {
344         /* No Newexten event on cache clear */
345         if (!new_snapshot) {
346                 return NULL;
347         }
348
349         /* Empty application is not valid for a Newexten event */
350         if (ast_strlen_zero(new_snapshot->appl)) {
351                 return NULL;
352         }
353
354         if (old_snapshot && ast_channel_snapshot_cep_equal(old_snapshot, new_snapshot)) {
355                 return NULL;
356         }
357
358         /* DEPRECATED: Extension field deprecated in 12; remove in 14 */
359         return ast_manager_event_blob_create(
360                 EVENT_FLAG_CALL, "Newexten",
361                 "Extension: %s\r\n"
362                 "Application: %s\r\n"
363                 "AppData: %s\r\n",
364                 new_snapshot->exten,
365                 new_snapshot->appl,
366                 new_snapshot->data);
367 }
368
369 static struct ast_manager_event_blob *channel_new_callerid(
370         struct ast_channel_snapshot *old_snapshot,
371         struct ast_channel_snapshot *new_snapshot)
372 {
373         /* No NewCallerid event on cache clear or first event */
374         if (!old_snapshot || !new_snapshot) {
375                 return NULL;
376         }
377
378         if (ast_channel_snapshot_caller_id_equal(old_snapshot, new_snapshot)) {
379                 return NULL;
380         }
381
382         return ast_manager_event_blob_create(
383                 EVENT_FLAG_CALL, "NewCallerid",
384                 "CID-CallingPres: %d (%s)\r\n",
385                 new_snapshot->caller_pres,
386                 ast_describe_caller_presentation(new_snapshot->caller_pres));
387 }
388
389 channel_snapshot_monitor channel_monitors[] = {
390         channel_state_change,
391         channel_newexten,
392         channel_new_callerid
393 };
394
395 static void channel_snapshot_update(void *data, struct stasis_subscription *sub,
396                                     struct stasis_topic *topic,
397                                     struct stasis_message *message)
398 {
399         RAII_VAR(struct ast_str *, channel_event_string, NULL, ast_free);
400         struct stasis_cache_update *update;
401         struct ast_channel_snapshot *old_snapshot;
402         struct ast_channel_snapshot *new_snapshot;
403         size_t i;
404
405         update = stasis_message_data(message);
406
407         if (ast_channel_snapshot_type() != update->type) {
408                 return;
409         }
410
411         old_snapshot = stasis_message_data(update->old_snapshot);
412         new_snapshot = stasis_message_data(update->new_snapshot);
413
414         for (i = 0; i < ARRAY_LEN(channel_monitors); ++i) {
415                 RAII_VAR(struct ast_manager_event_blob *, ev, NULL, ao2_cleanup);
416                 ev = channel_monitors[i](old_snapshot, new_snapshot);
417
418                 if (!ev) {
419                         continue;
420                 }
421
422                 /* If we haven't already, build the channel event string */
423                 if (!channel_event_string) {
424                         channel_event_string =
425                                 ast_manager_build_channel_state_string(new_snapshot);
426                         if (!channel_event_string) {
427                                 return;
428                         }
429                 }
430
431                 manager_event(ev->event_flags, ev->manager_event, "%s%s",
432                         ast_str_buffer(channel_event_string),
433                         ev->extra_fields);
434         }
435 }
436
437 static void channel_varset_cb(void *data, struct stasis_subscription *sub,
438         struct stasis_topic *topic, struct stasis_message *message)
439 {
440         struct ast_channel_blob *obj = stasis_message_data(message);
441         RAII_VAR(struct ast_str *, channel_event_string, NULL, ast_free);
442         const char *variable = ast_json_string_get(ast_json_object_get(obj->blob, "variable"));
443         const char *value = ast_json_string_get(ast_json_object_get(obj->blob, "value"));
444
445         if (obj->snapshot) {
446                 channel_event_string = ast_manager_build_channel_state_string(obj->snapshot);
447         } else {
448                 channel_event_string = ast_str_create(35);
449                 ast_str_set(&channel_event_string, 0,
450                             "Channel: none\r\n"
451                             "Uniqueid: none\r\n");
452         }
453
454         if (!channel_event_string) {
455                 return;
456         }
457
458         /*** DOCUMENTATION
459                 <managerEventInstance>
460                         <synopsis>Raised when a variable is set to a particular value.</synopsis>
461                         <syntax>
462                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='Newchannel']/managerEventInstance/syntax/parameter)" />
463                                 <parameter name="Variable">
464                                         <para>The variable being set.</para>
465                                 </parameter>
466                                 <parameter name="Value">
467                                         <para>The new value of the variable.</para>
468                                 </parameter>
469                         </syntax>
470                 </managerEventInstance>
471         ***/
472         manager_event(EVENT_FLAG_DIALPLAN, "VarSet",
473                       "%s"
474                       "Variable: %s\r\n"
475                       "Value: %s\r\n",
476                       ast_str_buffer(channel_event_string),
477                       variable, value);
478 }
479
480 /*!
481  * \brief Callback used to determine whether a key should be skipped when converting a JSON object to a manager blob
482  * \param key Key from JSON blob to be evaluated
483  * \retval non-zero if the key should be excluded
484  * \retval zero if the key should not be excluded
485  */
486 typedef int (*key_exclusion_cb)(const char *key);
487
488 static struct ast_str *manager_str_from_json_object(struct ast_json *blob, key_exclusion_cb exclusion_cb)
489 {
490         struct ast_str *output_str = ast_str_create(32);
491         struct ast_json_iter *blob_iter = ast_json_object_iter(blob);
492         if (!output_str || !blob_iter) {
493                 return NULL;
494         }
495
496         do {
497                 const char *key = ast_json_object_iter_key(blob_iter);
498                 const char *value = ast_json_string_get(ast_json_object_iter_value(blob_iter));
499                 if (exclusion_cb && exclusion_cb(key)) {
500                         continue;
501                 }
502
503                 ast_str_append(&output_str, 0, "%s: %s\r\n", key, value);
504                 if (!output_str) {
505                         return NULL;
506                 }
507         } while ((blob_iter = ast_json_object_iter_next(blob, blob_iter)));
508
509         return output_str;
510 }
511
512 static int userevent_exclusion_cb(const char *key)
513 {
514         if (!strcmp("type", key)) {
515                 return 1;
516         }
517         if (!strcmp("eventname", key)) {
518                 return 1;
519         }
520         return 0;
521 }
522
523 static void channel_user_event_cb(void *data, struct stasis_subscription *sub,
524         struct stasis_topic *topic, struct stasis_message *message)
525 {
526         struct ast_channel_blob *obj = stasis_message_data(message);
527         RAII_VAR(struct ast_str *, channel_event_string, NULL, ast_free);
528         RAII_VAR(struct ast_str *, body, NULL, ast_free);
529         const char *eventname;
530
531         eventname = ast_json_string_get(ast_json_object_get(obj->blob, "eventname"));
532         body = manager_str_from_json_object(obj->blob, userevent_exclusion_cb);
533         channel_event_string = ast_manager_build_channel_state_string(obj->snapshot);
534
535         if (!channel_event_string || !body) {
536                 return;
537         }
538
539         /*** DOCUMENTATION
540                 <managerEventInstance>
541                         <synopsis>A user defined event raised from the dialplan.</synopsis>
542                         <syntax>
543                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='Newchannel']/managerEventInstance/syntax/parameter)" />
544                                 <parameter name="UserEvent">
545                                         <para>The event name, as specified in the dialplan.</para>
546                                 </parameter>
547                         </syntax>
548                         <see-also>
549                                 <ref type="application">UserEvent</ref>
550                         </see-also>
551                 </managerEventInstance>
552         ***/
553         manager_event(EVENT_FLAG_USER, "UserEvent",
554                       "%s"
555                       "UserEvent: %s\r\n"
556                       "%s",
557                       ast_str_buffer(channel_event_string), eventname, ast_str_buffer(body));
558 }
559
560 static void channel_hangup_request_cb(void *data,
561         struct stasis_subscription *sub, struct stasis_topic *topic,
562         struct stasis_message *message)
563 {
564         struct ast_channel_blob *obj = stasis_message_data(message);
565         RAII_VAR(struct ast_str *, extra, NULL, ast_free);
566         RAII_VAR(struct ast_str *, channel_event_string, NULL, ast_free);
567         struct ast_json *cause;
568         int is_soft;
569         char *manager_event = "HangupRequest";
570
571         extra = ast_str_create(20);
572         if (!extra) {
573                 return;
574         }
575
576         channel_event_string = ast_manager_build_channel_state_string(obj->snapshot);
577
578         if (!channel_event_string) {
579                 return;
580         }
581
582         cause = ast_json_object_get(obj->blob, "cause");
583         if (cause) {
584                 ast_str_append(&extra, 0,
585                                "Cause: %jd\r\n",
586                                ast_json_integer_get(cause));
587         }
588
589         is_soft = ast_json_is_true(ast_json_object_get(obj->blob, "soft"));
590         if (is_soft) {
591                 manager_event = "SoftHangupRequest";
592         }
593
594         manager_event(EVENT_FLAG_CALL, manager_event,
595                       "%s%s",
596                       ast_str_buffer(channel_event_string),
597                       ast_str_buffer(extra));
598 }
599
600 static void channel_dtmf_begin_cb(void *data, struct stasis_subscription *sub,
601         struct stasis_topic *topic, struct stasis_message *message)
602 {
603         struct ast_channel_blob *obj = stasis_message_data(message);
604         RAII_VAR(struct ast_str *, channel_event_string, NULL, ast_free);
605         const char *digit =
606                 ast_json_string_get(ast_json_object_get(obj->blob, "digit"));
607         const char *direction =
608                 ast_json_string_get(ast_json_object_get(obj->blob, "direction"));
609
610         channel_event_string = ast_manager_build_channel_state_string(obj->snapshot);
611
612         if (!channel_event_string) {
613                 return;
614         }
615
616         /*** DOCUMENTATION
617                 <managerEventInstance>
618                         <synopsis>Raised when a DTMF digit has started on a channel.</synopsis>
619                                 <syntax>
620                                         <xi:include xpointer="xpointer(/docs/managerEvent[@name='Newchannel']/managerEventInstance/syntax/parameter)" />
621                                         <parameter name="Digit">
622                                                 <para>DTMF digit received or transmitted (0-9, A-E, # or *</para>
623                                         </parameter>
624                                         <parameter name="Direction">
625                                                 <enumlist>
626                                                         <enum name="Received"/>
627                                                         <enum name="Sent"/>
628                                                 </enumlist>
629                                         </parameter>
630                                 </syntax>
631                 </managerEventInstance>
632         ***/
633         manager_event(EVENT_FLAG_DTMF, "DTMFBegin",
634                 "%s"
635                 "Digit: %s\r\n"
636                 "Direction: %s\r\n",
637                 ast_str_buffer(channel_event_string),
638                 digit, direction);
639 }
640
641 static void channel_dtmf_end_cb(void *data, struct stasis_subscription *sub,
642         struct stasis_topic *topic, struct stasis_message *message)
643 {
644         struct ast_channel_blob *obj = stasis_message_data(message);
645         RAII_VAR(struct ast_str *, channel_event_string, NULL, ast_free);
646         const char *digit =
647                 ast_json_string_get(ast_json_object_get(obj->blob, "digit"));
648         const char *direction =
649                 ast_json_string_get(ast_json_object_get(obj->blob, "direction"));
650         long duration_ms =
651                 ast_json_integer_get(ast_json_object_get(obj->blob, "duration_ms"));
652
653         channel_event_string = ast_manager_build_channel_state_string(obj->snapshot);
654
655         if (!channel_event_string) {
656                 return;
657         }
658
659         /*** DOCUMENTATION
660                 <managerEventInstance>
661                         <synopsis>Raised when a DTMF digit has ended on a channel.</synopsis>
662                                 <syntax>
663                                         <xi:include xpointer="xpointer(/docs/managerEvent[@name='Newchannel']/managerEventInstance/syntax/parameter)" />
664                                         <parameter name="Digit">
665                                                 <para>DTMF digit received or transmitted (0-9, A-E, # or *</para>
666                                         </parameter>
667                                         <parameter name="DurationMs">
668                                                 <para>Duration (in milliseconds) DTMF was sent/received</para>
669                                         </parameter>
670                                         <parameter name="Direction">
671                                                 <enumlist>
672                                                         <enum name="Received"/>
673                                                         <enum name="Sent"/>
674                                                 </enumlist>
675                                         </parameter>
676                                 </syntax>
677                 </managerEventInstance>
678         ***/
679         manager_event(EVENT_FLAG_DTMF, "DTMFEnd",
680                 "%s"
681                 "Digit: %s\r\n"
682                 "DurationMs: %ld\r\n"
683                 "Direction: %s\r\n",
684                 ast_str_buffer(channel_event_string),
685                 digit, duration_ms, direction);
686 }
687
688 /*!
689  * \brief Callback processing messages for channel dialing
690  */
691 static void channel_dial_cb(void *data, struct stasis_subscription *sub,
692         struct stasis_topic *topic, struct stasis_message *message)
693 {
694         struct ast_multi_channel_blob *obj = stasis_message_data(message);
695         const char *dialstatus;
696         const char *dialstring;
697         struct ast_channel_snapshot *caller;
698         struct ast_channel_snapshot *peer;
699         RAII_VAR(struct ast_str *, caller_event_string, NULL, ast_free);
700         RAII_VAR(struct ast_str *, peer_event_string, NULL, ast_free);
701
702         caller = ast_multi_channel_blob_get_channel(obj, "caller");
703         peer = ast_multi_channel_blob_get_channel(obj, "peer");
704
705         /* Peer is required - otherwise, who are we dialing? */
706         ast_assert(peer != NULL);
707         peer_event_string = ast_manager_build_channel_state_string_suffix(peer, "Dest");
708         if (!peer_event_string) {
709                 return;
710         }
711
712         if (caller && !(caller_event_string = ast_manager_build_channel_state_string(caller))) {
713                 return;
714         }
715
716         dialstatus = ast_json_string_get(ast_json_object_get(ast_multi_channel_blob_get_json(obj), "dialstatus"));
717         dialstring = ast_json_string_get(ast_json_object_get(ast_multi_channel_blob_get_json(obj), "dialstring"));
718         if (ast_strlen_zero(dialstatus)) {
719                 manager_event(EVENT_FLAG_CALL, "DialBegin",
720                                 "%s"
721                                 "%s"
722                                 "DialString: %s\r\n",
723                                 caller_event_string ? ast_str_buffer(caller_event_string) : "",
724                                 ast_str_buffer(peer_event_string),
725                                 S_OR(dialstring, "unknown"));
726         } else {
727                 manager_event(EVENT_FLAG_CALL, "DialEnd",
728                                 "%s"
729                                 "%s"
730                                 "DialStatus: %s\r\n",
731                                 caller_event_string ? ast_str_buffer(caller_event_string) : "",
732                                 ast_str_buffer(peer_event_string),
733                                 S_OR(dialstatus, "unknown"));
734         }
735
736 }
737
738 static void manager_channels_shutdown(void)
739 {
740         stasis_message_router_unsubscribe_and_join(channel_state_router);
741         channel_state_router = NULL;
742 }
743
744 int manager_channels_init(void)
745 {
746         int ret = 0;
747
748         if (channel_state_router) {
749                 /* Already initialized */
750                 return 0;
751         }
752
753         ast_register_atexit(manager_channels_shutdown);
754
755         channel_state_router = stasis_message_router_create(
756                 stasis_caching_get_topic(ast_channel_topic_all_cached()));
757
758         if (!channel_state_router) {
759                 return -1;
760         }
761
762         ret |= stasis_message_router_add(channel_state_router,
763                                          stasis_cache_update_type(),
764                                          channel_snapshot_update,
765                                          NULL);
766
767         ret |= stasis_message_router_add(channel_state_router,
768                                          ast_channel_varset_type(),
769                                          channel_varset_cb,
770                                          NULL);
771
772         ret |= stasis_message_router_add(channel_state_router,
773                                          ast_channel_user_event_type(),
774                                          channel_user_event_cb,
775                                          NULL);
776
777         ret |= stasis_message_router_add(channel_state_router,
778                                          ast_channel_dtmf_begin_type(),
779                                          channel_dtmf_begin_cb,
780                                          NULL);
781
782         ret |= stasis_message_router_add(channel_state_router,
783                                          ast_channel_dtmf_end_type(),
784                                          channel_dtmf_end_cb,
785                                          NULL);
786
787         ret |= stasis_message_router_add(channel_state_router,
788                                          ast_channel_hangup_request_type(),
789                                          channel_hangup_request_cb,
790                                          NULL);
791
792         ret |= stasis_message_router_add(channel_state_router,
793                                          ast_channel_dial_type(),
794                                          channel_dial_cb,
795                                          NULL);
796
797         /* If somehow we failed to add any routes, just shut down the whole
798          * thing and fail it.
799          */
800         if (ret) {
801                 manager_channels_shutdown();
802                 return -1;
803         }
804
805         return 0;
806 }
807