Asterisk - The Open Source Telephony Project  21.4.1
manager_channels.c
Go to the documentation of this file.
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 #include "asterisk/callerid.h"
32 #include "asterisk/channel.h"
33 #include "asterisk/manager.h"
34 #include "asterisk/stasis_message_router.h"
35 #include "asterisk/pbx.h"
36 #include "asterisk/stasis_channels.h"
37 
38 /*** DOCUMENTATION
39  <managerEvent language="en_US" name="Newchannel">
40  <managerEventInstance class="EVENT_FLAG_CALL">
41  <synopsis>Raised when a new channel is created.</synopsis>
42  <syntax>
43  <channel_snapshot/>
44  </syntax>
45  <see-also>
46  <ref type="managerEvent">Newstate</ref>
47  <ref type="managerEvent">Hangup</ref>
48  </see-also>
49  </managerEventInstance>
50  </managerEvent>
51  <managerEvent language="en_US" name="Newstate">
52  <managerEventInstance class="EVENT_FLAG_CALL">
53  <synopsis>Raised when a channel's state changes.</synopsis>
54  <syntax>
55  <channel_snapshot/>
56  </syntax>
57  <see-also>
58  <ref type="managerEvent">Newchannel</ref>
59  <ref type="managerEvent">Hangup</ref>
60  </see-also>
61  </managerEventInstance>
62  </managerEvent>
63  <managerEvent language="en_US" name="Hangup">
64  <managerEventInstance class="EVENT_FLAG_CALL">
65  <synopsis>Raised when a channel is hung up.</synopsis>
66  <syntax>
67  <channel_snapshot/>
68  <parameter name="Cause">
69  <para>A numeric cause code for why the channel was hung up.</para>
70  </parameter>
71  <parameter name="Cause-txt">
72  <para>A description of why the channel was hung up.</para>
73  </parameter>
74  </syntax>
75  <see-also>
76  <ref type="managerEvent">Newchannel</ref>
77  <ref type="managerEvent">SoftHangupRequest</ref>
78  <ref type="managerEvent">HangupRequest</ref>
79  <ref type="managerEvent">Newstate</ref>
80  </see-also>
81  </managerEventInstance>
82  </managerEvent>
83  <managerEvent language="en_US" name="HangupRequest">
84  <managerEventInstance class="EVENT_FLAG_CALL">
85  <synopsis>Raised when a hangup is requested.</synopsis>
86  <syntax>
87  <channel_snapshot/>
88  <xi:include xpointer="xpointer(/docs/managerEvent[@name='Hangup']/managerEventInstance/syntax/parameter[@name='Cause'])" />
89  </syntax>
90  <see-also>
91  <ref type="managerEvent">SoftHangupRequest</ref>
92  <ref type="managerEvent">Hangup</ref>
93  </see-also>
94  </managerEventInstance>
95  </managerEvent>
96  <managerEvent language="en_US" name="SoftHangupRequest">
97  <managerEventInstance class="EVENT_FLAG_CALL">
98  <synopsis>Raised when a soft hangup is requested with a specific cause code.</synopsis>
99  <syntax>
100  <channel_snapshot/>
101  <xi:include xpointer="xpointer(/docs/managerEvent[@name='Hangup']/managerEventInstance/syntax/parameter[@name='Cause'])" />
102  </syntax>
103  <see-also>
104  <ref type="managerEvent">HangupRequest</ref>
105  <ref type="managerEvent">Hangup</ref>
106  </see-also>
107  </managerEventInstance>
108  </managerEvent>
109  <managerEvent language="en_US" name="NewExten">
110  <managerEventInstance class="EVENT_FLAG_DIALPLAN">
111  <synopsis>Raised when a channel enters a new context, extension, priority.</synopsis>
112  <syntax>
113  <channel_snapshot/>
114  <parameter name="Extension">
115  <para>Deprecated in 12, but kept for
116  backward compatability. Please use
117  'Exten' instead.</para>
118  </parameter>
119  <parameter name="Application">
120  <para>The application about to be executed.</para>
121  </parameter>
122  <parameter name="AppData">
123  <para>The data to be passed to the application.</para>
124  </parameter>
125  </syntax>
126  </managerEventInstance>
127  </managerEvent>
128  <managerEvent language="en_US" name="NewCallerid">
129  <managerEventInstance class="EVENT_FLAG_CALL">
130  <synopsis>Raised when a channel receives new Caller ID information.</synopsis>
131  <syntax>
132  <channel_snapshot/>
133  <parameter name="CID-CallingPres">
134  <para>A description of the Caller ID presentation.</para>
135  </parameter>
136  </syntax>
137  <see-also>
138  <ref type="function">CALLERID</ref>
139  </see-also>
140  </managerEventInstance>
141  </managerEvent>
142  <managerEvent language="en_US" name="NewConnectedLine">
143  <managerEventInstance class="EVENT_FLAG_CALL">
144  <synopsis>Raised when a channel's connected line information is changed.</synopsis>
145  <syntax>
146  <channel_snapshot/>
147  </syntax>
148  <see-also>
149  <ref type="function">CONNECTEDLINE</ref>
150  </see-also>
151  </managerEventInstance>
152  </managerEvent>
153  <managerEvent language="en_US" name="NewAccountCode">
154  <managerEventInstance class="EVENT_FLAG_CALL">
155  <synopsis>Raised when a Channel's AccountCode is changed.</synopsis>
156  <syntax>
157  <channel_snapshot/>
158  <parameter name="OldAccountCode">
159  <para>The channel's previous account code</para>
160  </parameter>
161  </syntax>
162  <see-also>
163  <ref type="function">CHANNEL</ref>
164  </see-also>
165  </managerEventInstance>
166  </managerEvent>
167  <managerEvent language="en_US" name="DialBegin">
168  <managerEventInstance class="EVENT_FLAG_CALL">
169  <synopsis>Raised when a dial action has started.</synopsis>
170  <syntax>
171  <channel_snapshot/>
172  <channel_snapshot prefix="Dest"/>
173  <parameter name="DialString">
174  <para>The non-technology specific device being dialed.</para>
175  </parameter>
176  </syntax>
177  <see-also>
178  <ref type="application">Dial</ref>
179  <ref type="application">Originate</ref>
180  <ref type="manager">Originate</ref>
181  <ref type="managerEvent">DialEnd</ref>
182  </see-also>
183  </managerEventInstance>
184  </managerEvent>
185  <managerEvent language="en_US" name="DialState">
186  <managerEventInstance class="EVENT_FLAG_CALL">
187  <synopsis>Raised when dial status has changed.</synopsis>
188  <syntax>
189  <channel_snapshot/>
190  <channel_snapshot prefix="Dest"/>
191  <parameter name="DialStatus">
192  <para> The new state of the outbound dial attempt.</para>
193  <enumlist>
194  <enum name="RINGING">
195  <para>The outbound channel is ringing.</para>
196  </enum>
197  <enum name="PROCEEDING">
198  <para>The call to the outbound channel is proceeding.</para>
199  </enum>
200  <enum name="PROGRESS">
201  <para>Progress has been received on the outbound channel.</para>
202  </enum>
203  </enumlist>
204  </parameter>
205  <parameter name="Forward" required="false">
206  <para>If the call was forwarded, where the call was
207  forwarded to.</para>
208  </parameter>
209  </syntax>
210  </managerEventInstance>
211  </managerEvent>
212  <managerEvent language="en_US" name="DialEnd">
213  <managerEventInstance class="EVENT_FLAG_CALL">
214  <synopsis>Raised when a dial action has completed.</synopsis>
215  <syntax>
216  <channel_snapshot/>
217  <channel_snapshot prefix="Dest"/>
218  <parameter name="DialStatus">
219  <para>The result of the dial operation.</para>
220  <enumlist>
221  <enum name="ABORT">
222  <para>The call was aborted.</para>
223  </enum>
224  <enum name="ANSWER">
225  <para>The caller answered.</para>
226  </enum>
227  <enum name="BUSY">
228  <para>The caller was busy.</para>
229  </enum>
230  <enum name="CANCEL">
231  <para>The caller cancelled the call.</para>
232  </enum>
233  <enum name="CHANUNAVAIL">
234  <para>The requested channel is unavailable.</para>
235  </enum>
236  <enum name="CONGESTION">
237  <para>The called party is congested.</para>
238  </enum>
239  <enum name="CONTINUE">
240  <para>The dial completed, but the caller elected
241  to continue in the dialplan.</para>
242  </enum>
243  <enum name="GOTO">
244  <para>The dial completed, but the caller jumped to
245  a dialplan location.</para>
246  <para>If known, the location the caller is jumping
247  to will be appended to the result following a
248  ":".</para>
249  </enum>
250  <enum name="NOANSWER">
251  <para>The called party failed to answer.</para>
252  </enum>
253  </enumlist>
254  </parameter>
255  <parameter name="Forward" required="false">
256  <para>If the call was forwarded, where the call was
257  forwarded to.</para>
258  </parameter>
259  </syntax>
260  <see-also>
261  <ref type="application">Dial</ref>
262  <ref type="application">Originate</ref>
263  <ref type="manager">Originate</ref>
264  <ref type="managerEvent">DialBegin</ref>
265  </see-also>
266  </managerEventInstance>
267  </managerEvent>
268  <managerEvent language="en_US" name="Hold">
269  <managerEventInstance class="EVENT_FLAG_CALL">
270  <synopsis>Raised when a channel goes on hold.</synopsis>
271  <syntax>
272  <channel_snapshot/>
273  <parameter name="MusicClass">
274  <para>The suggested MusicClass, if provided.</para>
275  </parameter>
276  </syntax>
277  <see-also>
278  <ref type="managerEvent">Unhold</ref>
279  </see-also>
280  </managerEventInstance>
281  </managerEvent>
282  <managerEvent language="en_US" name="Unhold">
283  <managerEventInstance class="EVENT_FLAG_CALL">
284  <synopsis>Raised when a channel goes off hold.</synopsis>
285  <syntax>
286  <channel_snapshot/>
287  </syntax>
288  <see-also>
289  <ref type="managerEvent">Hold</ref>
290  </see-also>
291  </managerEventInstance>
292  </managerEvent>
293  <managerEvent language="en_US" name="ChanSpyStart">
294  <managerEventInstance class="EVENT_FLAG_CALL">
295  <synopsis>Raised when one channel begins spying on another channel.</synopsis>
296  <syntax>
297  <channel_snapshot prefix="Spyer"/>
298  <channel_snapshot prefix="Spyee"/>
299  </syntax>
300  <see-also>
301  <ref type="managerEvent">ChanSpyStop</ref>
302  <ref type="application">ChanSpy</ref>
303  </see-also>
304  </managerEventInstance>
305  </managerEvent>
306  <managerEvent language="en_US" name="ChanSpyStop">
307  <managerEventInstance class="EVENT_FLAG_CALL">
308  <synopsis>Raised when a channel has stopped spying.</synopsis>
309  <syntax>
310  <channel_snapshot prefix="Spyer"/>
311  <channel_snapshot prefix="Spyee"/>
312  </syntax>
313  <see-also>
314  <ref type="managerEvent">ChanSpyStart</ref>
315  <ref type="application">ChanSpy</ref>
316  </see-also>
317  </managerEventInstance>
318  </managerEvent>
319  <managerEvent language="en_US" name="HangupHandlerRun">
320  <managerEventInstance class="EVENT_FLAG_DIALPLAN">
321  <synopsis>Raised when a hangup handler is about to be called.</synopsis>
322  <syntax>
323  <channel_snapshot/>
324  <parameter name="Handler">
325  <para>Hangup handler parameter string passed to the Gosub application.</para>
326  </parameter>
327  </syntax>
328  <see-also>
329  <ref type="function">CHANNEL</ref>
330  </see-also>
331  </managerEventInstance>
332  </managerEvent>
333  <managerEvent language="en_US" name="HangupHandlerPop">
334  <managerEventInstance class="EVENT_FLAG_DIALPLAN">
335  <synopsis>
336  Raised when a hangup handler is removed from the handler stack
337  by the CHANNEL() function.
338  </synopsis>
339  <syntax>
340  <channel_snapshot/>
341  <xi:include xpointer="xpointer(/docs/managerEvent[@name='HangupHandlerRun']/managerEventInstance/syntax/parameter)" />
342  </syntax>
343  <see-also>
344  <ref type="managerEvent">HangupHandlerPush</ref>
345  <ref type="function">CHANNEL</ref>
346  </see-also>
347  </managerEventInstance>
348  </managerEvent>
349  <managerEvent language="en_US" name="HangupHandlerPush">
350  <managerEventInstance class="EVENT_FLAG_DIALPLAN">
351  <synopsis>
352  Raised when a hangup handler is added to the handler stack by
353  the CHANNEL() function.
354  </synopsis>
355  <syntax>
356  <channel_snapshot/>
357  <xi:include xpointer="xpointer(/docs/managerEvent[@name='HangupHandlerRun']/managerEventInstance/syntax/parameter)" />
358  </syntax>
359  <see-also>
360  <ref type="managerEvent">HangupHandlerPop</ref>
361  <ref type="function">CHANNEL</ref>
362  </see-also>
363  </managerEventInstance>
364  </managerEvent>
365  <managerEvent language="en_US" name="FAXStatus">
366  <managerEventInstance class="EVENT_FLAG_CALL">
367  <synopsis>
368  Raised periodically during a fax transmission.
369  </synopsis>
370  <syntax>
371  <channel_snapshot/>
372  <parameter name="Operation">
373  <enumlist>
374  <enum name="gateway"/>
375  <enum name="receive"/>
376  <enum name="send"/>
377  </enumlist>
378  </parameter>
379  <parameter name="Status">
380  <para>A text message describing the current status of the fax</para>
381  </parameter>
382  <xi:include xpointer="xpointer(/docs/managerEvent[@name='ReceiveFAX']/managerEventInstance/syntax/parameter[@name='LocalStationID'])" />
383  <xi:include xpointer="xpointer(/docs/managerEvent[@name='ReceiveFAX']/managerEventInstance/syntax/parameter[@name='FileName'])" />
384  </syntax>
385  </managerEventInstance>
386  </managerEvent>
387  <managerEvent language="en_US" name="ReceiveFAX">
388  <managerEventInstance class="EVENT_FLAG_CALL">
389  <synopsis>
390  Raised when a receive fax operation has completed.
391  </synopsis>
392  <syntax>
393  <channel_snapshot/>
394  <parameter name="LocalStationID">
395  <para>The value of the <variable>LOCALSTATIONID</variable> channel variable</para>
396  </parameter>
397  <parameter name="RemoteStationID">
398  <para>The value of the <variable>REMOTESTATIONID</variable> channel variable</para>
399  </parameter>
400  <parameter name="PagesTransferred">
401  <para>The number of pages that have been transferred</para>
402  </parameter>
403  <parameter name="Resolution">
404  <para>The negotiated resolution</para>
405  </parameter>
406  <parameter name="TransferRate">
407  <para>The negotiated transfer rate</para>
408  </parameter>
409  <parameter name="FileName" multiple="yes">
410  <para>The files being affected by the fax operation</para>
411  </parameter>
412  </syntax>
413  </managerEventInstance>
414  </managerEvent>
415  <managerEvent language="en_US" name="SendFAX">
416  <managerEventInstance class="EVENT_FLAG_CALL">
417  <synopsis>
418  Raised when a send fax operation has completed.
419  </synopsis>
420  <syntax>
421  <channel_snapshot/>
422  <xi:include xpointer="xpointer(/docs/managerEvent[@name='ReceiveFAX']/managerEventInstance/syntax/parameter)" />
423  </syntax>
424  </managerEventInstance>
425  </managerEvent>
426  <managerEvent language="en_US" name="MusicOnHoldStart">
427  <managerEventInstance class="EVENT_FLAG_CALL">
428  <synopsis>Raised when music on hold has started on a channel.</synopsis>
429  <syntax>
430  <channel_snapshot/>
431  <parameter name="Class">
432  <para>The class of music being played on the channel</para>
433  </parameter>
434  </syntax>
435  <see-also>
436  <ref type="managerEvent">MusicOnHoldStop</ref>
437  <ref type="application">StartMusicOnHold</ref>
438  <ref type="application">MusicOnHold</ref>
439  </see-also>
440  </managerEventInstance>
441  </managerEvent>
442  <managerEvent language="en_US" name="MusicOnHoldStop">
443  <managerEventInstance class="EVENT_FLAG_CALL">
444  <synopsis>Raised when music on hold has stopped on a channel.</synopsis>
445  <syntax>
446  <channel_snapshot/>
447  </syntax>
448  <see-also>
449  <ref type="managerEvent">MusicOnHoldStart</ref>
450  <ref type="application">StopMusicOnHold</ref>
451  </see-also>
452  </managerEventInstance>
453  </managerEvent>
454 ***/
455 
456 /*! \brief The \ref stasis subscription returned by the forwarding of the channel topic
457  * to the manager topic
458  */
460 
462  const struct ast_channel_snapshot *snapshot,
463  const char *prefix)
464 {
465  struct ast_str *out;
466  char *caller_name;
467  char *connected_name;
468  int res;
469 
470  if (!snapshot || (snapshot->base->tech_properties & AST_CHAN_TP_INTERNAL)) {
471  return NULL;
472  }
473 
474  out = ast_str_create(1024);
475  if (!out) {
476  return NULL;
477  }
478 
479  caller_name = ast_escape_c_alloc(snapshot->caller->name);
480  connected_name = ast_escape_c_alloc(snapshot->connected->name);
481 
482  res = ast_str_set(&out, 0,
483  "%sChannel: %s\r\n"
484  "%sChannelState: %u\r\n"
485  "%sChannelStateDesc: %s\r\n"
486  "%sCallerIDNum: %s\r\n"
487  "%sCallerIDName: %s\r\n"
488  "%sConnectedLineNum: %s\r\n"
489  "%sConnectedLineName: %s\r\n"
490  "%sLanguage: %s\r\n"
491  "%sAccountCode: %s\r\n"
492  "%sContext: %s\r\n"
493  "%sExten: %s\r\n"
494  "%sPriority: %d\r\n"
495  "%sUniqueid: %s\r\n"
496  "%sLinkedid: %s\r\n",
497  prefix, snapshot->base->name,
498  prefix, snapshot->state,
499  prefix, ast_state2str(snapshot->state),
500  prefix, S_OR(snapshot->caller->number, "<unknown>"),
501  prefix, S_OR(caller_name, "<unknown>"),
502  prefix, S_OR(snapshot->connected->number, "<unknown>"),
503  prefix, S_OR(connected_name, "<unknown>"),
504  prefix, snapshot->base->language,
505  prefix, snapshot->base->accountcode,
506  prefix, snapshot->dialplan->context,
507  prefix, snapshot->dialplan->exten,
508  prefix, snapshot->dialplan->priority,
509  prefix, snapshot->base->uniqueid,
510  prefix, snapshot->peer->linkedid);
511 
512  ast_free(caller_name);
513  ast_free(connected_name);
514 
515  if (!res) {
516  ast_free(out);
517  return NULL;
518  }
519 
520  if (snapshot->manager_vars) {
521  struct ast_var_t *var;
522  char *val;
523  AST_LIST_TRAVERSE(snapshot->manager_vars, var, entries) {
524  val = ast_escape_c_alloc(var->value);
525  ast_str_append(&out, 0, "%sChanVariable: %s=%s\r\n",
526  prefix,
527  var->name, S_OR(val, ""));
528  ast_free(val);
529  }
530  }
531 
532  return out;
533 }
534 
536  const struct ast_channel_snapshot *snapshot)
537 {
539 }
540 
541 /*! \brief Typedef for callbacks that get called on channel snapshot updates */
542 typedef struct ast_manager_event_blob *(*channel_snapshot_monitor)(
543  struct ast_channel_snapshot *old_snapshot,
544  struct ast_channel_snapshot *new_snapshot);
545 
546 /*! \brief Handle channel state changes */
548  struct ast_channel_snapshot *old_snapshot,
549  struct ast_channel_snapshot *new_snapshot)
550 {
551  int is_hungup, was_hungup;
552 
553  /* The Newchannel, Newstate and Hangup events are closely related, in
554  * in that they are mutually exclusive, basically different flavors
555  * of a new channel state event.
556  */
557 
558  if (!old_snapshot) {
560  EVENT_FLAG_CALL, "Newchannel", NO_EXTRA_FIELDS);
561  }
562 
563  was_hungup = ast_test_flag(&old_snapshot->flags, AST_FLAG_DEAD) ? 1 : 0;
564  is_hungup = ast_test_flag(&new_snapshot->flags, AST_FLAG_DEAD) ? 1 : 0;
565 
566  if (!was_hungup && is_hungup) {
568  EVENT_FLAG_CALL, "Hangup",
569  "Cause: %d\r\n"
570  "Cause-txt: %s\r\n",
571  new_snapshot->hangup->cause,
572  ast_cause2str(new_snapshot->hangup->cause));
573  }
574 
575  if (old_snapshot->state != new_snapshot->state) {
577  EVENT_FLAG_CALL, "Newstate", NO_EXTRA_FIELDS);
578  }
579 
580  /* No event */
581  return NULL;
582 }
583 
584 static struct ast_manager_event_blob *channel_newexten(
585  struct ast_channel_snapshot *old_snapshot,
586  struct ast_channel_snapshot *new_snapshot)
587 {
588  /* Empty application is not valid for a Newexten event */
589  if (ast_strlen_zero(new_snapshot->dialplan->appl)) {
590  return NULL;
591  }
592 
593  /* Ignore any updates if we're hungup */
594  if (ast_test_flag(&new_snapshot->flags, AST_FLAG_DEAD)) {
595  return NULL;
596  }
597 
598  /* Ignore updates if the CEP is unchanged */
599  if (old_snapshot && ast_channel_snapshot_cep_equal(old_snapshot, new_snapshot)) {
600  return NULL;
601  }
602 
603  /* DEPRECATED: Extension field deprecated in 12; remove in 14 */
605  EVENT_FLAG_DIALPLAN, "Newexten",
606  "Extension: %s\r\n"
607  "Application: %s\r\n"
608  "AppData: %s\r\n",
609  new_snapshot->dialplan->exten,
610  new_snapshot->dialplan->appl,
611  new_snapshot->dialplan->data);
612 }
613 
614 static struct ast_manager_event_blob *channel_new_callerid(
615  struct ast_channel_snapshot *old_snapshot,
616  struct ast_channel_snapshot *new_snapshot)
617 {
618  struct ast_manager_event_blob *res;
619  char *callerid;
620 
621  /* No NewCallerid event on first channel snapshot */
622  if (!old_snapshot) {
623  return NULL;
624  }
625 
626  if (ast_channel_snapshot_caller_id_equal(old_snapshot, new_snapshot)) {
627  return NULL;
628  }
629 
630  if (!(callerid = ast_escape_c_alloc(
631  ast_describe_caller_presentation(new_snapshot->caller->pres)))) {
632  return NULL;
633  }
634 
636  EVENT_FLAG_CALL, "NewCallerid",
637  "CID-CallingPres: %d (%s)\r\n",
638  new_snapshot->caller->pres,
639  callerid);
640 
641  ast_free(callerid);
642  return res;
643 }
644 
645 static struct ast_manager_event_blob *channel_new_connected_line(
646  struct ast_channel_snapshot *old_snapshot,
647  struct ast_channel_snapshot *new_snapshot)
648 {
649  /* No NewConnectedLine event on first channel snapshot */
650  if (!old_snapshot) {
651  return NULL;
652  }
653 
654  if (ast_channel_snapshot_connected_line_equal(old_snapshot, new_snapshot)) {
655  return NULL;
656  }
657 
659  EVENT_FLAG_CALL, "NewConnectedLine", "%s", "");
660 }
661 
662 static struct ast_manager_event_blob *channel_new_accountcode(
663  struct ast_channel_snapshot *old_snapshot,
664  struct ast_channel_snapshot *new_snapshot)
665 {
666  if (!old_snapshot) {
667  return NULL;
668  }
669 
670  if (!strcmp(old_snapshot->base->accountcode, new_snapshot->base->accountcode)) {
671  return NULL;
672  }
673 
675  EVENT_FLAG_CALL, "NewAccountCode",
676  "OldAccountCode: %s\r\n", old_snapshot->base->accountcode);
677 }
678 
679 channel_snapshot_monitor channel_monitors[] = {
681  channel_newexten,
682  channel_new_callerid,
683  channel_new_accountcode,
684  channel_new_connected_line,
685 };
686 
687 static void channel_snapshot_update(void *data, struct stasis_subscription *sub,
688  struct stasis_message *message)
689 {
690  RAII_VAR(struct ast_str *, channel_event_string, NULL, ast_free);
691  struct ast_channel_snapshot_update *update;
692  size_t i;
693 
694  update = stasis_message_data(message);
695 
696  for (i = 0; i < ARRAY_LEN(channel_monitors); ++i) {
697  RAII_VAR(struct ast_manager_event_blob *, ev, NULL, ao2_cleanup);
698  ev = channel_monitors[i](update->old_snapshot, update->new_snapshot);
699 
700  if (!ev) {
701  continue;
702  }
703 
704  /* If we haven't already, build the channel event string */
705  if (!channel_event_string) {
706  channel_event_string =
708  if (!channel_event_string) {
709  return;
710  }
711  }
712 
713  manager_event(ev->event_flags, ev->manager_event, "%s%s",
714  ast_str_buffer(channel_event_string),
715  ev->extra_fields);
716  }
717 }
718 
719 static void publish_basic_channel_event(const char *event, int class, struct ast_channel_snapshot *snapshot)
720 {
721  RAII_VAR(struct ast_str *, channel_event_string, NULL, ast_free);
722 
723  channel_event_string = ast_manager_build_channel_state_string(snapshot);
724  if (!channel_event_string) {
725  return;
726  }
727 
728  manager_event(class, event,
729  "%s",
730  ast_str_buffer(channel_event_string));
731 }
732 
733 static void channel_hangup_request_cb(void *data,
734  struct stasis_subscription *sub,
735  struct stasis_message *message)
736 {
737  struct ast_channel_blob *obj = stasis_message_data(message);
738  struct ast_str *extra;
739  struct ast_str *channel_event_string;
740  struct ast_json *cause;
741  int is_soft;
742  char *manager_event = "HangupRequest";
743 
744  if (!obj->snapshot) {
745  /* No snapshot? Likely an earlier allocation failure creating it. */
746  return;
747  }
748 
749  extra = ast_str_create(20);
750  if (!extra) {
751  return;
752  }
753 
754  channel_event_string = ast_manager_build_channel_state_string(obj->snapshot);
755  if (!channel_event_string) {
756  ast_free(extra);
757  return;
758  }
759 
760  cause = ast_json_object_get(obj->blob, "cause");
761  if (cause) {
762  ast_str_append(&extra, 0,
763  "Cause: %jd\r\n",
764  ast_json_integer_get(cause));
765  }
766 
767  is_soft = ast_json_is_true(ast_json_object_get(obj->blob, "soft"));
768  if (is_soft) {
769  manager_event = "SoftHangupRequest";
770  }
771 
772  manager_event(EVENT_FLAG_CALL, manager_event,
773  "%s%s",
774  ast_str_buffer(channel_event_string),
775  ast_str_buffer(extra));
776 
777  ast_free(channel_event_string);
778  ast_free(extra);
779 }
780 
781 static void channel_chanspy_stop_cb(void *data, struct stasis_subscription *sub,
782  struct stasis_message *message)
783 {
784  RAII_VAR(struct ast_str *, spyer_channel_string, NULL, ast_free);
785  RAII_VAR(struct ast_str *, spyee_channel_string, NULL, ast_free);
786  struct ast_channel_snapshot *spyer;
787  struct ast_channel_snapshot *spyee;
788  const char *spyee_info = "";
789  struct ast_multi_channel_blob *payload = stasis_message_data(message);
790 
791  spyer = ast_multi_channel_blob_get_channel(payload, "spyer_channel");
792  if (!spyer) {
793  ast_log(AST_LOG_WARNING, "Received ChanSpy Stop event with no spyer channel!\n");
794  return;
795  }
796 
797  spyer_channel_string = ast_manager_build_channel_state_string_prefix(spyer, "Spyer");
798  if (!spyer_channel_string) {
799  return;
800  }
801 
802  spyee = ast_multi_channel_blob_get_channel(payload, "spyee_channel");
803  if (spyee) {
804  spyee_channel_string = ast_manager_build_channel_state_string_prefix(spyee, "Spyee");
805  if (spyee_channel_string) {
806  spyee_info = ast_str_buffer(spyee_channel_string);
807  }
808  }
809 
810  manager_event(EVENT_FLAG_CALL, "ChanSpyStop",
811  "%s%s",
812  ast_str_buffer(spyer_channel_string),
813  spyee_info);
814 }
815 
816 static void channel_chanspy_start_cb(void *data, struct stasis_subscription *sub,
817  struct stasis_message *message)
818 {
819  RAII_VAR(struct ast_str *, spyer_channel_string, NULL, ast_free);
820  RAII_VAR(struct ast_str *, spyee_channel_string, NULL, ast_free);
821  struct ast_channel_snapshot *spyer;
822  struct ast_channel_snapshot *spyee;
823  struct ast_multi_channel_blob *payload = stasis_message_data(message);
824 
825  spyer = ast_multi_channel_blob_get_channel(payload, "spyer_channel");
826  if (!spyer) {
827  ast_log(AST_LOG_WARNING, "Received ChanSpy Start event with no spyer channel!\n");
828  return;
829  }
830  spyee = ast_multi_channel_blob_get_channel(payload, "spyee_channel");
831  if (!spyee) {
832  ast_log(AST_LOG_WARNING, "Received ChanSpy Start event with no spyee channel!\n");
833  return;
834  }
835 
836  spyer_channel_string = ast_manager_build_channel_state_string_prefix(spyer, "Spyer");
837  if (!spyer_channel_string) {
838  return;
839  }
840  spyee_channel_string = ast_manager_build_channel_state_string_prefix(spyee, "Spyee");
841  if (!spyee_channel_string) {
842  return;
843  }
844 
845  manager_event(EVENT_FLAG_CALL, "ChanSpyStart",
846  "%s%s",
847  ast_str_buffer(spyer_channel_string),
848  ast_str_buffer(spyee_channel_string));
849 }
850 
851 static void channel_dtmf_begin_cb(void *data, struct stasis_subscription *sub,
852  struct stasis_message *message)
853 {
854  struct ast_channel_blob *obj = stasis_message_data(message);
855  RAII_VAR(struct ast_str *, channel_event_string, NULL, ast_free);
856  const char *digit =
858  const char *direction =
859  ast_json_string_get(ast_json_object_get(obj->blob, "direction"));
860 
861  channel_event_string = ast_manager_build_channel_state_string(obj->snapshot);
862 
863  if (!channel_event_string) {
864  return;
865  }
866 
867  /*** DOCUMENTATION
868  <managerEvent language="en_US" name="DTMFBegin">
869  <managerEventInstance class="EVENT_FLAG_DTMF">
870  <synopsis>Raised when a DTMF digit has started on a channel.</synopsis>
871  <syntax>
872  <channel_snapshot/>
873  <parameter name="Digit">
874  <para>DTMF digit received or transmitted (0-9, A-E, # or *</para>
875  </parameter>
876  <parameter name="Direction">
877  <enumlist>
878  <enum name="Received"/>
879  <enum name="Sent"/>
880  </enumlist>
881  </parameter>
882  </syntax>
883  <see-also>
884  <ref type="managerEvent">DTMFEnd</ref>
885  </see-also>
886  </managerEventInstance>
887  </managerEvent>
888  ***/
889  manager_event(EVENT_FLAG_DTMF, "DTMFBegin",
890  "%s"
891  "Digit: %s\r\n"
892  "Direction: %s\r\n",
893  ast_str_buffer(channel_event_string),
894  digit, direction);
895 }
896 
897 static void channel_dtmf_end_cb(void *data, struct stasis_subscription *sub,
898  struct stasis_message *message)
899 {
900  struct ast_channel_blob *obj = stasis_message_data(message);
901  RAII_VAR(struct ast_str *, channel_event_string, NULL, ast_free);
902  const char *digit =
904  const char *direction =
905  ast_json_string_get(ast_json_object_get(obj->blob, "direction"));
906  long duration_ms =
907  ast_json_integer_get(ast_json_object_get(obj->blob, "duration_ms"));
908 
909  channel_event_string = ast_manager_build_channel_state_string(obj->snapshot);
910 
911  if (!channel_event_string) {
912  return;
913  }
914 
915  /*** DOCUMENTATION
916  <managerEvent language="en_US" name="DTMFEnd">
917  <managerEventInstance class="EVENT_FLAG_DTMF">
918  <synopsis>Raised when a DTMF digit has ended on a channel.</synopsis>
919  <syntax>
920  <channel_snapshot/>
921  <parameter name="Digit">
922  <para>DTMF digit received or transmitted (0-9, A-E, # or *</para>
923  </parameter>
924  <parameter name="DurationMs">
925  <para>Duration (in milliseconds) DTMF was sent/received</para>
926  </parameter>
927  <parameter name="Direction">
928  <enumlist>
929  <enum name="Received"/>
930  <enum name="Sent"/>
931  </enumlist>
932  </parameter>
933  </syntax>
934  <see-also>
935  <ref type="managerEvent">DTMFBegin</ref>
936  </see-also>
937  </managerEventInstance>
938  </managerEvent>
939  ***/
940  manager_event(EVENT_FLAG_DTMF, "DTMFEnd",
941  "%s"
942  "Digit: %s\r\n"
943  "DurationMs: %ld\r\n"
944  "Direction: %s\r\n",
945  ast_str_buffer(channel_event_string),
946  digit, duration_ms, direction);
947 }
948 
949 static void channel_flash_cb(void *data, struct stasis_subscription *sub,
950  struct stasis_message *message)
951 {
952  struct ast_channel_blob *obj = stasis_message_data(message);
953  struct ast_str *channel_event_string;
954 
955  channel_event_string = ast_manager_build_channel_state_string(obj->snapshot);
956  if (!channel_event_string) {
957  return;
958  }
959 
960  /*** DOCUMENTATION
961  <managerEvent language="en_US" name="Flash">
962  <managerEventInstance class="EVENT_FLAG_CALL">
963  <synopsis>Raised when a hook flash occurs on a channel.</synopsis>
964  <syntax>
965  <channel_snapshot/>
966  </syntax>
967  </managerEventInstance>
968  </managerEvent>
969  ***/
970  manager_event(EVENT_FLAG_CALL, "Flash",
971  "%s",
972  ast_str_buffer(channel_event_string));
973 
974  ast_free(channel_event_string);
975 }
976 
977 static void channel_wink_cb(void *data, struct stasis_subscription *sub,
978  struct stasis_message *message)
979 {
980  struct ast_channel_blob *obj = stasis_message_data(message);
981  struct ast_str *channel_event_string;
982 
983  channel_event_string = ast_manager_build_channel_state_string(obj->snapshot);
984  if (!channel_event_string) {
985  return;
986  }
987 
988  /*** DOCUMENTATION
989  <managerEvent language="en_US" name="Wink">
990  <managerEventInstance class="EVENT_FLAG_CALL">
991  <synopsis>Raised when a wink occurs on a channel.</synopsis>
992  <syntax>
993  <channel_snapshot/>
994  </syntax>
995  </managerEventInstance>
996  </managerEvent>
997  ***/
998  manager_event(EVENT_FLAG_CALL, "Wink",
999  "%s",
1000  ast_str_buffer(channel_event_string));
1001 
1002  ast_free(channel_event_string);
1003 }
1004 
1005 static void channel_hangup_handler_cb(void *data, struct stasis_subscription *sub,
1006  struct stasis_message *message)
1007 {
1008  RAII_VAR(struct ast_str *, channel_event_string, NULL, ast_free);
1009  struct ast_channel_blob *payload = stasis_message_data(message);
1010  const char *action = ast_json_string_get(ast_json_object_get(payload->blob, "type"));
1011  const char *handler = ast_json_string_get(ast_json_object_get(payload->blob, "handler"));
1012  const char *event;
1013 
1014  channel_event_string = ast_manager_build_channel_state_string(payload->snapshot);
1015 
1016  if (!channel_event_string) {
1017  return;
1018  }
1019 
1020  if (!strcmp(action, "run")) {
1021  event = "HangupHandlerRun";
1022  } else if (!strcmp(action, "pop")) {
1023  event = "HangupHandlerPop";
1024  } else if (!strcmp(action, "push")) {
1025  event = "HangupHandlerPush";
1026  } else {
1027  return;
1028  }
1029  manager_event(EVENT_FLAG_DIALPLAN, event,
1030  "%s"
1031  "Handler: %s\r\n",
1032  ast_str_buffer(channel_event_string),
1033  handler);
1034 }
1035 
1036 static void channel_fax_cb(void *data, struct stasis_subscription *sub,
1037  struct stasis_message *message)
1038 {
1039  RAII_VAR(struct ast_str *, channel_event_string, NULL, ast_free);
1040  RAII_VAR(struct ast_str *, event_buffer, ast_str_create(256), ast_free);
1041  struct ast_channel_blob *payload = stasis_message_data(message);
1042  const char *type = ast_json_string_get(ast_json_object_get(payload->blob, "type"));
1043  struct ast_json *operation = ast_json_object_get(payload->blob, "operation");
1044  struct ast_json *status = ast_json_object_get(payload->blob, "status");
1045  struct ast_json *local_station_id = ast_json_object_get(payload->blob, "local_station_id");
1046  struct ast_json *remote_station_id = ast_json_object_get(payload->blob, "remote_station_id");
1047  struct ast_json *fax_pages = ast_json_object_get(payload->blob, "fax_pages");
1048  struct ast_json *fax_resolution = ast_json_object_get(payload->blob, "fax_resolution");
1049  struct ast_json *fax_bitrate = ast_json_object_get(payload->blob, "fax_bitrate");
1050  struct ast_json *filenames = ast_json_object_get(payload->blob, "filenames");
1051  const char *event;
1052  size_t array_len;
1053  size_t i;
1054 
1055  if (!event_buffer) {
1056  return;
1057  }
1058 
1059  channel_event_string = ast_manager_build_channel_state_string(payload->snapshot);
1060  if (!channel_event_string) {
1061  return;
1062  }
1063 
1064  if (!strcmp(type, "status")) {
1065  event = "FAXStatus";
1066  } else if (!strcmp(type, "receive")) {
1067  event = "ReceiveFAX";
1068  } else if (!strcmp(type, "send")) {
1069  event = "SendFAX";
1070  } else {
1071  return;
1072  }
1073 
1074  if (operation) {
1075  ast_str_append(&event_buffer, 0, "Operation: %s\r\n", ast_json_string_get(operation));
1076  }
1077  if (status) {
1078  ast_str_append(&event_buffer, 0, "Status: %s\r\n", ast_json_string_get(status));
1079  }
1080  if (local_station_id) {
1081  ast_str_append(&event_buffer, 0, "LocalStationID: %s\r\n", ast_json_string_get(local_station_id));
1082  }
1083  if (remote_station_id) {
1084  ast_str_append(&event_buffer, 0, "RemoteStationID: %s\r\n", ast_json_string_get(remote_station_id));
1085  }
1086  if (fax_pages) {
1087  ast_str_append(&event_buffer, 0, "PagesTransferred: %s\r\n", ast_json_string_get(fax_pages));
1088  }
1089  if (fax_resolution) {
1090  ast_str_append(&event_buffer, 0, "Resolution: %s\r\n", ast_json_string_get(fax_resolution));
1091  }
1092  if (fax_bitrate) {
1093  ast_str_append(&event_buffer, 0, "TransferRate: %s\r\n", ast_json_string_get(fax_bitrate));
1094  }
1095  if (filenames) {
1096  array_len = ast_json_array_size(filenames);
1097  for (i = 0; i < array_len; i++) {
1098  ast_str_append(&event_buffer, 0, "FileName: %s\r\n", ast_json_string_get(ast_json_array_get(filenames, i)));
1099  }
1100  }
1101 
1102  manager_event(EVENT_FLAG_CALL, event,
1103  "%s"
1104  "%s",
1105  ast_str_buffer(channel_event_string),
1106  ast_str_buffer(event_buffer));
1107 }
1108 
1109 static void channel_moh_start_cb(void *data, struct stasis_subscription *sub,
1110  struct stasis_message *message)
1111 {
1112  struct ast_channel_blob *payload = stasis_message_data(message);
1113  struct ast_json *blob = payload->blob;
1114  RAII_VAR(struct ast_str *, channel_event_string, NULL, ast_free);
1115 
1116  channel_event_string = ast_manager_build_channel_state_string(payload->snapshot);
1117  if (!channel_event_string) {
1118  return;
1119  }
1120 
1121  manager_event(EVENT_FLAG_CALL, "MusicOnHoldStart",
1122  "%s"
1123  "Class: %s\r\n",
1124  ast_str_buffer(channel_event_string),
1125  ast_json_string_get(ast_json_object_get(blob, "class")));
1126 
1127 }
1128 
1129 static void channel_moh_stop_cb(void *data, struct stasis_subscription *sub,
1130  struct stasis_message *message)
1131 {
1132  struct ast_channel_blob *payload = stasis_message_data(message);
1133 
1134  publish_basic_channel_event("MusicOnHoldStop", EVENT_FLAG_CALL, payload->snapshot);
1135 }
1136 
1137 static void channel_mixmonitor_start_cb(void *data, struct stasis_subscription *sub,
1138  struct stasis_message *message)
1139 {
1140  struct ast_channel_blob *payload = stasis_message_data(message);
1141 
1142  publish_basic_channel_event("MixMonitorStart", EVENT_FLAG_CALL, payload->snapshot);
1143 }
1144 
1145 static void channel_mixmonitor_stop_cb(void *data, struct stasis_subscription *sub,
1146  struct stasis_message *message)
1147 {
1148  struct ast_channel_blob *payload = stasis_message_data(message);
1149 
1150  publish_basic_channel_event("MixMonitorStop", EVENT_FLAG_CALL, payload->snapshot);
1151 }
1152 
1153 static void channel_mixmonitor_mute_cb(void *data, struct stasis_subscription *sub,
1154  struct stasis_message *message)
1155 {
1156  RAII_VAR(struct ast_str *, channel_event_string, NULL, ast_free);
1157  RAII_VAR(struct ast_str *, event_buffer, ast_str_create(64), ast_free);
1158  struct ast_channel_blob *payload = stasis_message_data(message);
1159  struct ast_json *direction = ast_json_object_get(payload->blob, "direction");
1160  const int state = ast_json_is_true(ast_json_object_get(payload->blob, "state"));
1161 
1162  if (!event_buffer) {
1163  return;
1164  }
1165 
1166  channel_event_string = ast_manager_build_channel_state_string(payload->snapshot);
1167  if (!channel_event_string) {
1168  return;
1169  }
1170 
1171  if (direction) {
1172  ast_str_append(&event_buffer, 0, "Direction: %s\r\n", ast_json_string_get(direction));
1173  }
1174  ast_str_append(&event_buffer, 0, "State: %s\r\n", state ? "1" : "0");
1175 
1176  manager_event(EVENT_FLAG_CALL, "MixMonitorMute",
1177  "%s"
1178  "%s",
1179  ast_str_buffer(channel_event_string),
1180  ast_str_buffer(event_buffer));
1181 
1182 }
1183 
1184 static int dial_status_end(const char *dialstatus)
1185 {
1186  return (strcmp(dialstatus, "RINGING") &&
1187  strcmp(dialstatus, "PROCEEDING") &&
1188  strcmp(dialstatus, "PROGRESS"));
1189 }
1190 
1191 /*!
1192  * \brief Callback processing messages for channel dialing
1193  */
1194 static void channel_dial_cb(void *data, struct stasis_subscription *sub,
1195  struct stasis_message *message)
1196 {
1197  struct ast_multi_channel_blob *obj = stasis_message_data(message);
1198  const char *dialstatus;
1199  const char *dialstring;
1200  const char *forward;
1201  struct ast_channel_snapshot *caller;
1202  struct ast_channel_snapshot *peer;
1203  RAII_VAR(struct ast_str *, caller_event_string, NULL, ast_free);
1204  RAII_VAR(struct ast_str *, peer_event_string, NULL, ast_free);
1205 
1206  caller = ast_multi_channel_blob_get_channel(obj, "caller");
1207  peer = ast_multi_channel_blob_get_channel(obj, "peer");
1208 
1209  /* Peer is required - otherwise, who are we dialing? */
1210  ast_assert(peer != NULL);
1211  peer_event_string = ast_manager_build_channel_state_string_prefix(peer, "Dest");
1212  if (!peer_event_string) {
1213  return;
1214  }
1215 
1216  if (caller && !(caller_event_string = ast_manager_build_channel_state_string(caller))) {
1217  return;
1218  }
1219 
1223  if (ast_strlen_zero(dialstatus)) {
1224  manager_event(EVENT_FLAG_CALL, "DialBegin",
1225  "%s"
1226  "%s"
1227  "DialString: %s\r\n",
1228  caller_event_string ? ast_str_buffer(caller_event_string) : "",
1229  ast_str_buffer(peer_event_string),
1230  S_OR(dialstring, "unknown"));
1231  } else {
1232  int forwarded = !ast_strlen_zero(forward);
1233 
1234  manager_event(EVENT_FLAG_CALL, dial_status_end(dialstatus) ? "DialEnd" : "DialState",
1235  "%s"
1236  "%s"
1237  "%s%s%s"
1238  "DialStatus: %s\r\n",
1239  caller_event_string ? ast_str_buffer(caller_event_string) : "",
1240  ast_str_buffer(peer_event_string),
1241  forwarded ? "Forward: " : "", S_OR(forward, ""), forwarded ? "\r\n" : "",
1242  S_OR(dialstatus, "unknown"));
1243  }
1244 
1245 }
1246 
1247 static void channel_hold_cb(void *data, struct stasis_subscription *sub,
1248  struct stasis_message *message)
1249 {
1250  struct ast_channel_blob *obj = stasis_message_data(message);
1251  struct ast_str *musicclass_string = ast_str_create(32);
1252  struct ast_str *channel_event_string;
1253 
1254  if (!musicclass_string) {
1255  return;
1256  }
1257 
1258  channel_event_string = ast_manager_build_channel_state_string(obj->snapshot);
1259  if (!channel_event_string) {
1260  ast_free(musicclass_string);
1261  return;
1262  }
1263 
1264  if (obj->blob) {
1265  const char *musicclass;
1266 
1267  musicclass = ast_json_string_get(ast_json_object_get(obj->blob, "musicclass"));
1268 
1269  if (!ast_strlen_zero(musicclass)) {
1270  ast_str_set(&musicclass_string, 0, "MusicClass: %s\r\n", musicclass);
1271  }
1272  }
1273 
1274  manager_event(EVENT_FLAG_CALL, "Hold",
1275  "%s"
1276  "%s",
1277  ast_str_buffer(channel_event_string),
1278  ast_str_buffer(musicclass_string));
1279 
1280  ast_free(musicclass_string);
1281  ast_free(channel_event_string);
1282 }
1283 
1284 static void channel_unhold_cb(void *data, struct stasis_subscription *sub,
1285  struct stasis_message *message)
1286 {
1287  struct ast_channel_blob *obj = stasis_message_data(message);
1288  struct ast_str *channel_event_string;
1289 
1290  channel_event_string = ast_manager_build_channel_state_string(obj->snapshot);
1291  if (!channel_event_string) {
1292  return;
1293  }
1294 
1295  manager_event(EVENT_FLAG_CALL, "Unhold",
1296  "%s",
1297  ast_str_buffer(channel_event_string));
1298 
1299  ast_free(channel_event_string);
1300 }
1301 
1302 static void manager_channels_shutdown(void)
1303 {
1304  stasis_forward_cancel(topic_forwarder);
1305  topic_forwarder = NULL;
1306 }
1307 
1309 {
1310  int ret = 0;
1311  struct stasis_topic *manager_topic;
1312  struct stasis_topic *channel_topic;
1313  struct stasis_message_router *message_router;
1314 
1315  manager_topic = ast_manager_get_topic();
1316  if (!manager_topic) {
1317  return -1;
1318  }
1319  message_router = ast_manager_get_message_router();
1320  if (!message_router) {
1321  return -1;
1322  }
1323  channel_topic = ast_channel_topic_all();
1324  if (!channel_topic) {
1325  return -1;
1326  }
1327 
1328  topic_forwarder = stasis_forward_all(channel_topic, manager_topic);
1329  if (!topic_forwarder) {
1330  return -1;
1331  }
1332 
1333  ast_register_cleanup(manager_channels_shutdown);
1334 
1335  /* The snapshot type has a special handler as it can result in multiple
1336  * manager events being queued due to aspects of the snapshot itself
1337  * changing.
1338  */
1339  ret |= stasis_message_router_add(message_router,
1340  ast_channel_snapshot_type(), channel_snapshot_update, NULL);
1341 
1342  ret |= stasis_message_router_add(message_router,
1343  ast_channel_dtmf_begin_type(), channel_dtmf_begin_cb, NULL);
1344 
1345  ret |= stasis_message_router_add(message_router,
1346  ast_channel_dtmf_end_type(), channel_dtmf_end_cb, NULL);
1347 
1348  ret |= stasis_message_router_add(message_router,
1349  ast_channel_flash_type(), channel_flash_cb, NULL);
1350 
1351  ret |= stasis_message_router_add(message_router,
1352  ast_channel_wink_type(), channel_wink_cb, NULL);
1353 
1354  ret |= stasis_message_router_add(message_router,
1355  ast_channel_hangup_request_type(), channel_hangup_request_cb,
1356  NULL);
1357 
1358  ret |= stasis_message_router_add(message_router,
1360 
1361  ret |= stasis_message_router_add(message_router,
1362  ast_channel_hold_type(), channel_hold_cb, NULL);
1363 
1364  ret |= stasis_message_router_add(message_router,
1365  ast_channel_unhold_type(), channel_unhold_cb, NULL);
1366 
1367  ret |= stasis_message_router_add(message_router,
1368  ast_channel_fax_type(), channel_fax_cb, NULL);
1369 
1370  ret |= stasis_message_router_add(message_router,
1371  ast_channel_chanspy_start_type(), channel_chanspy_start_cb,
1372  NULL);
1373 
1374  ret |= stasis_message_router_add(message_router,
1375  ast_channel_chanspy_stop_type(), channel_chanspy_stop_cb, NULL);
1376 
1377  ret |= stasis_message_router_add(message_router,
1378  ast_channel_hangup_handler_type(), channel_hangup_handler_cb,
1379  NULL);
1380 
1381  ret |= stasis_message_router_add(message_router,
1382  ast_channel_moh_start_type(), channel_moh_start_cb, NULL);
1383 
1384  ret |= stasis_message_router_add(message_router,
1385  ast_channel_moh_stop_type(), channel_moh_stop_cb, NULL);
1386 
1387  ret |= stasis_message_router_add(message_router,
1388  ast_channel_mixmonitor_start_type(), channel_mixmonitor_start_cb, NULL);
1389 
1390  ret |= stasis_message_router_add(message_router,
1391  ast_channel_mixmonitor_stop_type(), channel_mixmonitor_stop_cb, NULL);
1392 
1393  ret |= stasis_message_router_add(message_router,
1394  ast_channel_mixmonitor_mute_type(), channel_mixmonitor_mute_cb, NULL);
1395 
1396  /* If somehow we failed to add any routes, just shut down the whole
1397  * thing and fail it.
1398  */
1399  if (ret) {
1400  manager_channels_shutdown();
1401  return -1;
1402  }
1403 
1404  return 0;
1405 }
struct stasis_message_type * ast_channel_hold_type(void)
Message type for when a channel is placed on hold.
const ast_string_field data
Struct containing info for an AMI event to send out.
Definition: manager.h:502
struct ast_channel_snapshot_base * base
struct stasis_message_type * ast_channel_dtmf_end_type(void)
Message type for when DTMF ends on a channel.
Channels with this particular technology are an implementation detail of Asterisk and should generall...
Definition: channel.h:971
Asterisk main include file. File version handling, generic pbx functions.
struct stasis_message_type * ast_channel_unhold_type(void)
Message type for when a channel is removed from hold.
int ast_channel_snapshot_cep_equal(const struct ast_channel_snapshot *old_snapshot, const struct ast_channel_snapshot *new_snapshot)
Compares the context, exten and priority of two snapshots.
int stasis_message_router_add(struct stasis_message_router *router, struct stasis_message_type *message_type, stasis_subscription_cb callback, void *data)
Add a route to a message router.
CallerID (and other GR30) management and generation Includes code and algorithms from the Zapata libr...
const ast_string_field name
const char * ast_describe_caller_presentation(int data)
Convert caller ID pres value to explanatory string.
Definition: callerid.c:1364
struct ast_json * blob
struct ast_channel_snapshot * snapshot
struct stasis_message_type * ast_channel_moh_start_type(void)
Message type for starting music on hold on a channel.
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:761
int ast_json_is_true(const struct ast_json *value)
Check if value is JSON true.
Definition: json.c:263
Structure representing a snapshot of channel state.
struct stasis_message_type * ast_channel_wink_type(void)
Message type for when a wink occurs on a channel.
const ast_string_field accountcode
struct stasis_message_type * ast_channel_flash_type(void)
Message type for when a hook flash occurs on a channel.
Definition: astman.c:222
const ast_string_field uniqueid
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
Definition: strings.h:1139
const char * ast_cause2str(int cause) attribute_pure
Gives the string form of a given cause code.
Definition: channel.c:612
struct stasis_message_type * ast_channel_chanspy_start_type(void)
Message type for when a channel starts spying on another channel.
static struct stasis_topic * manager_topic
A stasis_topic that all topics AMI cares about will be forwarded to.
Definition: manager.c:1644
Structure representing a change of snapshot of channel state.
struct ast_channel_snapshot_dialplan * dialplan
struct ast_manager_event_blob * ast_manager_event_blob_create(int event_flags, const char *manager_event, const char *extra_fields_fmt,...)
Construct a ast_manager_event_blob.
Definition: manager.c:10563
struct ast_json * ast_multi_channel_blob_get_json(struct ast_multi_channel_blob *obj)
Retrieve the JSON blob from a ast_multi_channel_blob. Returned ast_json is still owned by obj...
Blob of data associated with a channel.
int ast_channel_snapshot_caller_id_equal(const struct ast_channel_snapshot *old_snapshot, const struct ast_channel_snapshot *new_snapshot)
Compares the callerid info of two snapshots.
static void channel_dial_cb(void *data, struct stasis_subscription *sub, struct stasis_message *message)
Callback processing messages for channel dialing.
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
Definition: strings.h:1113
const ast_string_field context
struct stasis_topic * ast_channel_topic_all(void)
A topic which publishes the events for all channels.
General Asterisk PBX channel definitions.
int ast_register_cleanup(void(*func)(void))
Register a function to be executed before Asterisk gracefully exits.
Definition: clicompat.c:19
const ast_string_field appl
#define NO_EXTRA_FIELDS
Definition: manager.h:533
const ast_string_field exten
struct ast_channel_snapshot_hangup * hangup
const char * ast_json_string_get(const struct ast_json *string)
Get the value of a JSON string.
Definition: json.c:283
struct ast_str * ast_manager_build_channel_state_string(const struct ast_channel_snapshot *snapshot)
Generate the AMI message body from a channel snapshot.
Core PBX routines and definitions.
static struct ast_manager_event_blob * channel_state_change(struct ast_channel_snapshot *old_snapshot, struct ast_channel_snapshot *new_snapshot)
Handle channel state changes.
struct ast_channel_snapshot_caller * caller
The AMI - Asterisk Manager Interface - is a TCP protocol created to manage Asterisk with third-party ...
struct ast_str * ast_manager_build_channel_state_string_prefix(const struct ast_channel_snapshot *snapshot, const char *prefix)
Generate the AMI message body from a channel snapshot.
struct stasis_message_type * ast_channel_mixmonitor_start_type(void)
Message type for starting mixmonitor on a channel.
struct varshead * manager_vars
Support for dynamic strings.
Definition: strings.h:623
struct stasis_message_type * ast_channel_mixmonitor_stop_type(void)
Message type for stopping mixmonitor on a channel.
void * stasis_message_data(const struct stasis_message *msg)
Get the data contained in a message.
struct stasis_message_router * ast_manager_get_message_router(void)
Get the stasis_message_router for AMI.
Definition: manager.c:1885
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:491
struct stasis_message_type * ast_channel_hangup_handler_type(void)
Message type for hangup handler related actions.
char * ast_escape_c_alloc(const char *s)
Escape standard 'C' sequences in the given string.
Definition: utils.c:2140
struct ast_channel_snapshot * new_snapshot
enum ast_channel_state state
struct stasis_message_type * ast_channel_snapshot_type(void)
Message type for ast_channel_snapshot_update.
struct ast_channel_snapshot * old_snapshot
struct stasis_message_type * ast_channel_dtmf_begin_type(void)
Message type for when DTMF begins on a channel.
struct stasis_topic * ast_manager_get_topic(void)
Get the Stasis Message Bus API topic for AMI.
Definition: manager.c:1880
const ast_string_field language
struct ast_json * ast_json_object_get(struct ast_json *object, const char *key)
Get a field from a JSON object.
Definition: json.c:407
const ast_string_field number
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:80
struct ast_flags flags
struct ast_channel_snapshot * ast_multi_channel_blob_get_channel(struct ast_multi_channel_blob *obj, const char *role)
Retrieve a channel snapshot associated with a specific role from a ast_multi_channel_blob.
A multi channel blob data structure for multi_channel_blob stasis messages.
size_t ast_json_array_size(const struct ast_json *array)
Get the size of a JSON array.
Definition: json.c:366
Abstract JSON element (object, array, string, int, ...).
static struct stasis_forward * topic_forwarder
The Stasis Message Bus API subscription returned by the forwarding of the channel topic to the manage...
Forwarding information.
Definition: stasis.c:1531
struct stasis_message_type * ast_channel_dial_type(void)
Message type for when a channel dials another channel.
int ast_channel_snapshot_connected_line_equal(const struct ast_channel_snapshot *old_snapshot, const struct ast_channel_snapshot *new_snapshot)
Compares the connected line info of two snapshots.
struct stasis_message_type * ast_channel_moh_stop_type(void)
Message type for stopping music on hold on a channel.
struct stasis_forward * stasis_forward_all(struct stasis_topic *from_topic, struct stasis_topic *to_topic)
Create a subscription which forwards all messages from one topic to another.
Definition: stasis.c:1578
struct ast_channel_snapshot_peer * peer
struct stasis_message_type * ast_channel_hangup_request_type(void)
Message type for when a hangup is requested on a channel.
#define manager_event(category, event, contents,...)
External routines may send asterisk manager events this way.
Definition: manager.h:253
intmax_t ast_json_integer_get(const struct ast_json *integer)
Get the value from a JSON integer.
Definition: json.c:332
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:941
struct stasis_message_type * ast_channel_fax_type(void)
Message type for a fax operation.
const char * ast_state2str(enum ast_channel_state state)
Gives the string form of a given channel state.
Definition: channel.c:636
struct ast_json * ast_json_array_get(const struct ast_json *array, size_t index)
Get an element from an array.
Definition: json.c:370
struct ast_manager_event_blob *(* channel_snapshot_monitor)(struct ast_channel_snapshot *old_snapshot, struct ast_channel_snapshot *new_snapshot)
Typedef for callbacks that get called on channel snapshot updates.
struct ast_channel_snapshot_connected * connected
struct stasis_message_type * ast_channel_chanspy_stop_type(void)
Message type for when a channel stops spying on another channel.
int manager_channels_init(void)
Initialize support for AMI channel events.
const ast_string_field name
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
Definition: strings.h:659
struct stasis_message_type * ast_channel_mixmonitor_mute_type(void)
Message type for muting or unmuting mixmonitor on a channel.