Asterisk - The Open Source Telephony Project  18.5.0
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 <[email protected]>
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 <[email protected]>
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"
35 #include "asterisk/pbx.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  <managerEvent language="en_US" name="MonitorStart">
455  <managerEventInstance class="EVENT_FLAG_CALL">
456  <synopsis>Raised when monitoring has started on a channel.</synopsis>
457  <syntax>
458  <channel_snapshot/>
459  </syntax>
460  <see-also>
461  <ref type="managerEvent">MonitorStop</ref>
462  <ref type="application">Monitor</ref>
463  <ref type="manager">Monitor</ref>
464  </see-also>
465  </managerEventInstance>
466  </managerEvent>
467  <managerEvent language="en_US" name="MonitorStop">
468  <managerEventInstance class="EVENT_FLAG_CALL">
469  <synopsis>Raised when monitoring has stopped on a channel.</synopsis>
470  <syntax>
471  <channel_snapshot/>
472  </syntax>
473  <see-also>
474  <ref type="managerEvent">MonitorStart</ref>
475  <ref type="application">StopMonitor</ref>
476  <ref type="manager">StopMonitor</ref>
477  </see-also>
478  </managerEventInstance>
479  </managerEvent>
480 ***/
481 
482 /*! \brief The \ref stasis subscription returned by the forwarding of the channel topic
483  * to the manager topic
484  */
486 
488  const struct ast_channel_snapshot *snapshot,
489  const char *prefix)
490 {
491  struct ast_str *out;
492  char *caller_name;
493  char *connected_name;
494  int res;
495 
496  if (snapshot->base->tech_properties & AST_CHAN_TP_INTERNAL) {
497  return NULL;
498  }
499 
500  out = ast_str_create(1024);
501  if (!out) {
502  return NULL;
503  }
504 
505  caller_name = ast_escape_c_alloc(snapshot->caller->name);
506  connected_name = ast_escape_c_alloc(snapshot->connected->name);
507 
508  res = ast_str_set(&out, 0,
509  "%sChannel: %s\r\n"
510  "%sChannelState: %u\r\n"
511  "%sChannelStateDesc: %s\r\n"
512  "%sCallerIDNum: %s\r\n"
513  "%sCallerIDName: %s\r\n"
514  "%sConnectedLineNum: %s\r\n"
515  "%sConnectedLineName: %s\r\n"
516  "%sLanguage: %s\r\n"
517  "%sAccountCode: %s\r\n"
518  "%sContext: %s\r\n"
519  "%sExten: %s\r\n"
520  "%sPriority: %d\r\n"
521  "%sUniqueid: %s\r\n"
522  "%sLinkedid: %s\r\n",
523  prefix, snapshot->base->name,
524  prefix, snapshot->state,
525  prefix, ast_state2str(snapshot->state),
526  prefix, S_OR(snapshot->caller->number, "<unknown>"),
527  prefix, S_OR(caller_name, "<unknown>"),
528  prefix, S_OR(snapshot->connected->number, "<unknown>"),
529  prefix, S_OR(connected_name, "<unknown>"),
530  prefix, snapshot->base->language,
531  prefix, snapshot->base->accountcode,
532  prefix, snapshot->dialplan->context,
533  prefix, snapshot->dialplan->exten,
534  prefix, snapshot->dialplan->priority,
535  prefix, snapshot->base->uniqueid,
536  prefix, snapshot->peer->linkedid);
537 
538  ast_free(caller_name);
539  ast_free(connected_name);
540 
541  if (!res) {
542  ast_free(out);
543  return NULL;
544  }
545 
546  if (snapshot->manager_vars) {
547  struct ast_var_t *var;
548  char *val;
549  AST_LIST_TRAVERSE(snapshot->manager_vars, var, entries) {
550  val = ast_escape_c_alloc(var->value);
551  ast_str_append(&out, 0, "%sChanVariable: %s=%s\r\n",
552  prefix,
553  var->name, S_OR(val, ""));
554  ast_free(val);
555  }
556  }
557 
558  return out;
559 }
560 
562  const struct ast_channel_snapshot *snapshot)
563 {
565 }
566 
567 /*! \brief Typedef for callbacks that get called on channel snapshot updates */
568 typedef struct ast_manager_event_blob *(*channel_snapshot_monitor)(
569  struct ast_channel_snapshot *old_snapshot,
570  struct ast_channel_snapshot *new_snapshot);
571 
572 /*! \brief Handle channel state changes */
574  struct ast_channel_snapshot *old_snapshot,
575  struct ast_channel_snapshot *new_snapshot)
576 {
577  int is_hungup, was_hungup;
578 
579  /* The Newchannel, Newstate and Hangup events are closely related, in
580  * in that they are mutually exclusive, basically different flavors
581  * of a new channel state event.
582  */
583 
584  if (!old_snapshot) {
586  EVENT_FLAG_CALL, "Newchannel", NO_EXTRA_FIELDS);
587  }
588 
589  was_hungup = ast_test_flag(&old_snapshot->flags, AST_FLAG_DEAD) ? 1 : 0;
590  is_hungup = ast_test_flag(&new_snapshot->flags, AST_FLAG_DEAD) ? 1 : 0;
591 
592  if (!was_hungup && is_hungup) {
594  EVENT_FLAG_CALL, "Hangup",
595  "Cause: %d\r\n"
596  "Cause-txt: %s\r\n",
597  new_snapshot->hangup->cause,
598  ast_cause2str(new_snapshot->hangup->cause));
599  }
600 
601  if (old_snapshot->state != new_snapshot->state) {
603  EVENT_FLAG_CALL, "Newstate", NO_EXTRA_FIELDS);
604  }
605 
606  /* No event */
607  return NULL;
608 }
609 
611  struct ast_channel_snapshot *old_snapshot,
612  struct ast_channel_snapshot *new_snapshot)
613 {
614  /* Empty application is not valid for a Newexten event */
615  if (ast_strlen_zero(new_snapshot->dialplan->appl)) {
616  return NULL;
617  }
618 
619  /* Ignore any updates if we're hungup */
620  if (ast_test_flag(&new_snapshot->flags, AST_FLAG_DEAD)) {
621  return NULL;
622  }
623 
624  /* Ignore updates if the CEP is unchanged */
625  if (old_snapshot && ast_channel_snapshot_cep_equal(old_snapshot, new_snapshot)) {
626  return NULL;
627  }
628 
629  /* DEPRECATED: Extension field deprecated in 12; remove in 14 */
631  EVENT_FLAG_DIALPLAN, "Newexten",
632  "Extension: %s\r\n"
633  "Application: %s\r\n"
634  "AppData: %s\r\n",
635  new_snapshot->dialplan->exten,
636  new_snapshot->dialplan->appl,
637  new_snapshot->dialplan->data);
638 }
639 
641  struct ast_channel_snapshot *old_snapshot,
642  struct ast_channel_snapshot *new_snapshot)
643 {
644  struct ast_manager_event_blob *res;
645  char *callerid;
646 
647  /* No NewCallerid event on first channel snapshot */
648  if (!old_snapshot) {
649  return NULL;
650  }
651 
652  if (ast_channel_snapshot_caller_id_equal(old_snapshot, new_snapshot)) {
653  return NULL;
654  }
655 
656  if (!(callerid = ast_escape_c_alloc(
657  ast_describe_caller_presentation(new_snapshot->caller->pres)))) {
658  return NULL;
659  }
660 
662  EVENT_FLAG_CALL, "NewCallerid",
663  "CID-CallingPres: %d (%s)\r\n",
664  new_snapshot->caller->pres,
665  callerid);
666 
667  ast_free(callerid);
668  return res;
669 }
670 
672  struct ast_channel_snapshot *old_snapshot,
673  struct ast_channel_snapshot *new_snapshot)
674 {
675  /* No NewConnectedLine event on first channel snapshot */
676  if (!old_snapshot) {
677  return NULL;
678  }
679 
680  if (ast_channel_snapshot_connected_line_equal(old_snapshot, new_snapshot)) {
681  return NULL;
682  }
683 
685  EVENT_FLAG_CALL, "NewConnectedLine", "%s", "");
686 }
687 
689  struct ast_channel_snapshot *old_snapshot,
690  struct ast_channel_snapshot *new_snapshot)
691 {
692  if (!old_snapshot) {
693  return NULL;
694  }
695 
696  if (!strcmp(old_snapshot->base->accountcode, new_snapshot->base->accountcode)) {
697  return NULL;
698  }
699 
701  EVENT_FLAG_CALL, "NewAccountCode",
702  "OldAccountCode: %s\r\n", old_snapshot->base->accountcode);
703 }
704 
711 };
712 
713 static void channel_snapshot_update(void *data, struct stasis_subscription *sub,
714  struct stasis_message *message)
715 {
716  RAII_VAR(struct ast_str *, channel_event_string, NULL, ast_free);
718  size_t i;
719 
720  update = stasis_message_data(message);
721 
722  for (i = 0; i < ARRAY_LEN(channel_monitors); ++i) {
724  ev = channel_monitors[i](update->old_snapshot, update->new_snapshot);
725 
726  if (!ev) {
727  continue;
728  }
729 
730  /* If we haven't already, build the channel event string */
731  if (!channel_event_string) {
732  channel_event_string =
734  if (!channel_event_string) {
735  return;
736  }
737  }
738 
739  manager_event(ev->event_flags, ev->manager_event, "%s%s",
740  ast_str_buffer(channel_event_string),
741  ev->extra_fields);
742  }
743 }
744 
745 static void publish_basic_channel_event(const char *event, int class, struct ast_channel_snapshot *snapshot)
746 {
747  RAII_VAR(struct ast_str *, channel_event_string, NULL, ast_free);
748 
749  channel_event_string = ast_manager_build_channel_state_string(snapshot);
750  if (!channel_event_string) {
751  return;
752  }
753 
754  manager_event(class, event,
755  "%s",
756  ast_str_buffer(channel_event_string));
757 }
758 
759 static void channel_hangup_request_cb(void *data,
760  struct stasis_subscription *sub,
761  struct stasis_message *message)
762 {
763  struct ast_channel_blob *obj = stasis_message_data(message);
764  struct ast_str *extra;
765  struct ast_str *channel_event_string;
766  struct ast_json *cause;
767  int is_soft;
768  char *manager_event = "HangupRequest";
769 
770  if (!obj->snapshot) {
771  /* No snapshot? Likely an earlier allocation failure creating it. */
772  return;
773  }
774 
775  extra = ast_str_create(20);
776  if (!extra) {
777  return;
778  }
779 
780  channel_event_string = ast_manager_build_channel_state_string(obj->snapshot);
781  if (!channel_event_string) {
782  ast_free(extra);
783  return;
784  }
785 
786  cause = ast_json_object_get(obj->blob, "cause");
787  if (cause) {
788  ast_str_append(&extra, 0,
789  "Cause: %jd\r\n",
790  ast_json_integer_get(cause));
791  }
792 
793  is_soft = ast_json_is_true(ast_json_object_get(obj->blob, "soft"));
794  if (is_soft) {
795  manager_event = "SoftHangupRequest";
796  }
797 
798  manager_event(EVENT_FLAG_CALL, manager_event,
799  "%s%s",
800  ast_str_buffer(channel_event_string),
801  ast_str_buffer(extra));
802 
803  ast_free(channel_event_string);
804  ast_free(extra);
805 }
806 
807 static void channel_chanspy_stop_cb(void *data, struct stasis_subscription *sub,
808  struct stasis_message *message)
809 {
810  RAII_VAR(struct ast_str *, spyer_channel_string, NULL, ast_free);
811  RAII_VAR(struct ast_str *, spyee_channel_string, NULL, ast_free);
812  struct ast_channel_snapshot *spyer;
813  struct ast_channel_snapshot *spyee;
814  const char *spyee_info = "";
815  struct ast_multi_channel_blob *payload = stasis_message_data(message);
816 
817  spyer = ast_multi_channel_blob_get_channel(payload, "spyer_channel");
818  if (!spyer) {
819  ast_log(AST_LOG_WARNING, "Received ChanSpy Stop event with no spyer channel!\n");
820  return;
821  }
822 
823  spyer_channel_string = ast_manager_build_channel_state_string_prefix(spyer, "Spyer");
824  if (!spyer_channel_string) {
825  return;
826  }
827 
828  spyee = ast_multi_channel_blob_get_channel(payload, "spyee_channel");
829  if (spyee) {
830  spyee_channel_string = ast_manager_build_channel_state_string_prefix(spyee, "Spyee");
831  if (spyee_channel_string) {
832  spyee_info = ast_str_buffer(spyee_channel_string);
833  }
834  }
835 
836  manager_event(EVENT_FLAG_CALL, "ChanSpyStop",
837  "%s%s",
838  ast_str_buffer(spyer_channel_string),
839  spyee_info);
840 }
841 
842 static void channel_chanspy_start_cb(void *data, struct stasis_subscription *sub,
843  struct stasis_message *message)
844 {
845  RAII_VAR(struct ast_str *, spyer_channel_string, NULL, ast_free);
846  RAII_VAR(struct ast_str *, spyee_channel_string, NULL, ast_free);
847  struct ast_channel_snapshot *spyer;
848  struct ast_channel_snapshot *spyee;
849  struct ast_multi_channel_blob *payload = stasis_message_data(message);
850 
851  spyer = ast_multi_channel_blob_get_channel(payload, "spyer_channel");
852  if (!spyer) {
853  ast_log(AST_LOG_WARNING, "Received ChanSpy Start event with no spyer channel!\n");
854  return;
855  }
856  spyee = ast_multi_channel_blob_get_channel(payload, "spyee_channel");
857  if (!spyee) {
858  ast_log(AST_LOG_WARNING, "Received ChanSpy Start event with no spyee channel!\n");
859  return;
860  }
861 
862  spyer_channel_string = ast_manager_build_channel_state_string_prefix(spyer, "Spyer");
863  if (!spyer_channel_string) {
864  return;
865  }
866  spyee_channel_string = ast_manager_build_channel_state_string_prefix(spyee, "Spyee");
867  if (!spyee_channel_string) {
868  return;
869  }
870 
871  manager_event(EVENT_FLAG_CALL, "ChanSpyStart",
872  "%s%s",
873  ast_str_buffer(spyer_channel_string),
874  ast_str_buffer(spyee_channel_string));
875 }
876 
877 static void channel_dtmf_begin_cb(void *data, struct stasis_subscription *sub,
878  struct stasis_message *message)
879 {
880  struct ast_channel_blob *obj = stasis_message_data(message);
881  RAII_VAR(struct ast_str *, channel_event_string, NULL, ast_free);
882  const char *digit =
884  const char *direction =
885  ast_json_string_get(ast_json_object_get(obj->blob, "direction"));
886 
887  channel_event_string = ast_manager_build_channel_state_string(obj->snapshot);
888 
889  if (!channel_event_string) {
890  return;
891  }
892 
893  /*** DOCUMENTATION
894  <managerEventInstance>
895  <synopsis>Raised when a DTMF digit has started on a channel.</synopsis>
896  <syntax>
897  <channel_snapshot/>
898  <parameter name="Digit">
899  <para>DTMF digit received or transmitted (0-9, A-E, # or *</para>
900  </parameter>
901  <parameter name="Direction">
902  <enumlist>
903  <enum name="Received"/>
904  <enum name="Sent"/>
905  </enumlist>
906  </parameter>
907  </syntax>
908  <see-also>
909  <ref type="managerEvent">DTMFEnd</ref>
910  </see-also>
911  </managerEventInstance>
912  ***/
913  manager_event(EVENT_FLAG_DTMF, "DTMFBegin",
914  "%s"
915  "Digit: %s\r\n"
916  "Direction: %s\r\n",
917  ast_str_buffer(channel_event_string),
918  digit, direction);
919 }
920 
921 static void channel_dtmf_end_cb(void *data, struct stasis_subscription *sub,
922  struct stasis_message *message)
923 {
924  struct ast_channel_blob *obj = stasis_message_data(message);
925  RAII_VAR(struct ast_str *, channel_event_string, NULL, ast_free);
926  const char *digit =
928  const char *direction =
929  ast_json_string_get(ast_json_object_get(obj->blob, "direction"));
930  long duration_ms =
931  ast_json_integer_get(ast_json_object_get(obj->blob, "duration_ms"));
932 
933  channel_event_string = ast_manager_build_channel_state_string(obj->snapshot);
934 
935  if (!channel_event_string) {
936  return;
937  }
938 
939  /*** DOCUMENTATION
940  <managerEventInstance>
941  <synopsis>Raised when a DTMF digit has ended on a channel.</synopsis>
942  <syntax>
943  <channel_snapshot/>
944  <parameter name="Digit">
945  <para>DTMF digit received or transmitted (0-9, A-E, # or *</para>
946  </parameter>
947  <parameter name="DurationMs">
948  <para>Duration (in milliseconds) DTMF was sent/received</para>
949  </parameter>
950  <parameter name="Direction">
951  <enumlist>
952  <enum name="Received"/>
953  <enum name="Sent"/>
954  </enumlist>
955  </parameter>
956  </syntax>
957  <see-also>
958  <ref type="managerEvent">DTMFBegin</ref>
959  </see-also>
960  </managerEventInstance>
961  ***/
962  manager_event(EVENT_FLAG_DTMF, "DTMFEnd",
963  "%s"
964  "Digit: %s\r\n"
965  "DurationMs: %ld\r\n"
966  "Direction: %s\r\n",
967  ast_str_buffer(channel_event_string),
968  digit, duration_ms, direction);
969 }
970 
971 static void channel_flash_cb(void *data, struct stasis_subscription *sub,
972  struct stasis_message *message)
973 {
974  struct ast_channel_blob *obj = stasis_message_data(message);
975  struct ast_str *channel_event_string;
976 
977  channel_event_string = ast_manager_build_channel_state_string(obj->snapshot);
978  if (!channel_event_string) {
979  return;
980  }
981 
983  "%s",
984  ast_str_buffer(channel_event_string));
985 
986  ast_free(channel_event_string);
987 }
988 
989 static void channel_hangup_handler_cb(void *data, struct stasis_subscription *sub,
990  struct stasis_message *message)
991 {
992  RAII_VAR(struct ast_str *, channel_event_string, NULL, ast_free);
993  struct ast_channel_blob *payload = stasis_message_data(message);
994  const char *action = ast_json_string_get(ast_json_object_get(payload->blob, "type"));
995  const char *handler = ast_json_string_get(ast_json_object_get(payload->blob, "handler"));
996  const char *event;
997 
998  channel_event_string = ast_manager_build_channel_state_string(payload->snapshot);
999 
1000  if (!channel_event_string) {
1001  return;
1002  }
1003 
1004  if (!strcmp(action, "run")) {
1005  event = "HangupHandlerRun";
1006  } else if (!strcmp(action, "pop")) {
1007  event = "HangupHandlerPop";
1008  } else if (!strcmp(action, "push")) {
1009  event = "HangupHandlerPush";
1010  } else {
1011  return;
1012  }
1014  "%s"
1015  "Handler: %s\r\n",
1016  ast_str_buffer(channel_event_string),
1017  handler);
1018 }
1019 
1020 static void channel_fax_cb(void *data, struct stasis_subscription *sub,
1021  struct stasis_message *message)
1022 {
1023  RAII_VAR(struct ast_str *, channel_event_string, NULL, ast_free);
1024  RAII_VAR(struct ast_str *, event_buffer, ast_str_create(256), ast_free);
1025  struct ast_channel_blob *payload = stasis_message_data(message);
1026  const char *type = ast_json_string_get(ast_json_object_get(payload->blob, "type"));
1027  struct ast_json *operation = ast_json_object_get(payload->blob, "operation");
1028  struct ast_json *status = ast_json_object_get(payload->blob, "status");
1029  struct ast_json *local_station_id = ast_json_object_get(payload->blob, "local_station_id");
1030  struct ast_json *remote_station_id = ast_json_object_get(payload->blob, "remote_station_id");
1031  struct ast_json *fax_pages = ast_json_object_get(payload->blob, "fax_pages");
1032  struct ast_json *fax_resolution = ast_json_object_get(payload->blob, "fax_resolution");
1033  struct ast_json *fax_bitrate = ast_json_object_get(payload->blob, "fax_bitrate");
1034  struct ast_json *filenames = ast_json_object_get(payload->blob, "filenames");
1035  const char *event;
1036  size_t array_len;
1037  size_t i;
1038 
1039  if (!event_buffer) {
1040  return;
1041  }
1042 
1043  channel_event_string = ast_manager_build_channel_state_string(payload->snapshot);
1044  if (!channel_event_string) {
1045  return;
1046  }
1047 
1048  if (!strcmp(type, "status")) {
1049  event = "FAXStatus";
1050  } else if (!strcmp(type, "receive")) {
1051  event = "ReceiveFAX";
1052  } else if (!strcmp(type, "send")) {
1053  event = "SendFAX";
1054  } else {
1055  return;
1056  }
1057 
1058  if (operation) {
1059  ast_str_append(&event_buffer, 0, "Operation: %s\r\n", ast_json_string_get(operation));
1060  }
1061  if (status) {
1062  ast_str_append(&event_buffer, 0, "Status: %s\r\n", ast_json_string_get(status));
1063  }
1064  if (local_station_id) {
1065  ast_str_append(&event_buffer, 0, "LocalStationID: %s\r\n", ast_json_string_get(local_station_id));
1066  }
1067  if (remote_station_id) {
1068  ast_str_append(&event_buffer, 0, "RemoteStationID: %s\r\n", ast_json_string_get(remote_station_id));
1069  }
1070  if (fax_pages) {
1071  ast_str_append(&event_buffer, 0, "PagesTransferred: %s\r\n", ast_json_string_get(fax_pages));
1072  }
1073  if (fax_resolution) {
1074  ast_str_append(&event_buffer, 0, "Resolution: %s\r\n", ast_json_string_get(fax_resolution));
1075  }
1076  if (fax_bitrate) {
1077  ast_str_append(&event_buffer, 0, "TransferRate: %s\r\n", ast_json_string_get(fax_bitrate));
1078  }
1079  if (filenames) {
1080  array_len = ast_json_array_size(filenames);
1081  for (i = 0; i < array_len; i++) {
1082  ast_str_append(&event_buffer, 0, "FileName: %s\r\n", ast_json_string_get(ast_json_array_get(filenames, i)));
1083  }
1084  }
1085 
1087  "%s"
1088  "%s",
1089  ast_str_buffer(channel_event_string),
1090  ast_str_buffer(event_buffer));
1091 }
1092 
1093 static void channel_moh_start_cb(void *data, struct stasis_subscription *sub,
1094  struct stasis_message *message)
1095 {
1096  struct ast_channel_blob *payload = stasis_message_data(message);
1097  struct ast_json *blob = payload->blob;
1098  RAII_VAR(struct ast_str *, channel_event_string, NULL, ast_free);
1099 
1100  channel_event_string = ast_manager_build_channel_state_string(payload->snapshot);
1101  if (!channel_event_string) {
1102  return;
1103  }
1104 
1105  manager_event(EVENT_FLAG_CALL, "MusicOnHoldStart",
1106  "%s"
1107  "Class: %s\r\n",
1108  ast_str_buffer(channel_event_string),
1109  ast_json_string_get(ast_json_object_get(blob, "class")));
1110 
1111 }
1112 
1113 static void channel_moh_stop_cb(void *data, struct stasis_subscription *sub,
1114  struct stasis_message *message)
1115 {
1116  struct ast_channel_blob *payload = stasis_message_data(message);
1117 
1118  publish_basic_channel_event("MusicOnHoldStop", EVENT_FLAG_CALL, payload->snapshot);
1119 }
1120 
1121 static void channel_monitor_start_cb(void *data, struct stasis_subscription *sub,
1122  struct stasis_message *message)
1123 {
1124  struct ast_channel_blob *payload = stasis_message_data(message);
1125 
1126  publish_basic_channel_event("MonitorStart", EVENT_FLAG_CALL, payload->snapshot);
1127 }
1128 
1129 static void channel_monitor_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("MonitorStop", 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 
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 
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,
1341 
1342  ret |= stasis_message_router_add(message_router,
1344 
1345  ret |= stasis_message_router_add(message_router,
1347 
1348  ret |= stasis_message_router_add(message_router,
1350 
1351  ret |= stasis_message_router_add(message_router,
1353  NULL);
1354 
1355  ret |= stasis_message_router_add(message_router,
1357 
1358  ret |= stasis_message_router_add(message_router,
1360 
1361  ret |= stasis_message_router_add(message_router,
1363 
1364  ret |= stasis_message_router_add(message_router,
1366 
1367  ret |= stasis_message_router_add(message_router,
1369  NULL);
1370 
1371  ret |= stasis_message_router_add(message_router,
1373 
1374  ret |= stasis_message_router_add(message_router,
1376  NULL);
1377 
1378  ret |= stasis_message_router_add(message_router,
1380 
1381  ret |= stasis_message_router_add(message_router,
1383 
1384  ret |= stasis_message_router_add(message_router,
1386  NULL);
1387 
1388  ret |= stasis_message_router_add(message_router,
1390 
1391  ret |= stasis_message_router_add(message_router,
1393 
1394  ret |= stasis_message_router_add(message_router,
1396 
1397  ret |= stasis_message_router_add(message_router,
1399 
1400  /* If somehow we failed to add any routes, just shut down the whole
1401  * thing and fail it.
1402  */
1403  if (ret) {
1405  return -1;
1406  }
1407 
1408  return 0;
1409 }
struct stasis_message_type * ast_channel_hold_type(void)
Message type for when a channel is placed on hold.
static char musicclass[MAX_MUSICCLASS]
Definition: chan_mgcp.c:162
static const char type[]
Definition: chan_ooh323.c:109
const ast_string_field data
Struct containing info for an AMI event to send out.
Definition: manager.h:491
char digit
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.
Asterisk main include file. File version handling, generic pbx functions.
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
struct stasis_message_type * ast_channel_unhold_type(void)
Message type for when a channel is removed from hold.
static void manager_channels_shutdown(void)
CallerID (and other GR30) management and generation Includes code and algorithms from the Zapata libr...
Definition: ast_expr2.c:325
const ast_string_field name
const char * ast_describe_caller_presentation(int data)
Convert caller ID pres value to explanatory string.
Definition: callerid.c:1164
#define ast_test_flag(p, flag)
Definition: utils.h:63
static void update(int code_size, int y, int wi, int fi, int dq, int sr, int dqsez, struct g726_state *state_ptr)
Definition: codec_g726.c:367
struct ast_json * blob
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.
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:714
static void channel_hangup_request_cb(void *data, struct stasis_subscription *sub, struct stasis_message *message)
int ast_json_is_true(const struct ast_json *value)
Check if value is JSON true.
Definition: json.c:253
#define AST_LOG_WARNING
Definition: logger.h:279
#define var
Definition: ast_expr2f.c:614
Structure representing a snapshot of channel state.
#define EVENT_FLAG_CALL
Definition: manager.h:72
#define EVENT_FLAG_DTMF
Definition: manager.h:79
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:1091
static struct ast_manager_event_blob * channel_new_connected_line(struct ast_channel_snapshot *old_snapshot, struct ast_channel_snapshot *new_snapshot)
static void channel_chanspy_start_cb(void *data, struct stasis_subscription *sub, struct stasis_message *message)
#define ast_assert(a)
Definition: utils.h:695
static void channel_mixmonitor_stop_cb(void *data, struct stasis_subscription *sub, struct stasis_message *message)
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.
const char * ast_state2str(enum ast_channel_state)
Gives the string form of a given channel state.
Definition: channel.c:642
struct stasis_message_type * ast_channel_chanspy_start_type(void)
Message type for when a channel starts spying on another channel.
#define NULL
Definition: resample.c:96
static struct stasis_topic * manager_topic
A stasis_topic that all topics AMI cares about will be forwarded to.
Definition: manager.c:1490
struct stasis_message_type * ast_channel_monitor_start_type(void)
Message type for starting monitor on a channel.
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.
Structure representing a change of snapshot of channel state.
#define EVENT_FLAG_DIALPLAN
Definition: manager.h:82
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:9727
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.
static void channel_dtmf_begin_cb(void *data, struct stasis_subscription *sub, struct stasis_message *message)
#define ast_strlen_zero(foo)
Definition: strings.h:52
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:1065
const ast_string_field context
struct stasis_topic * ast_channel_topic_all(void)
A topic which publishes the events for all channels.
#define ast_log
Definition: astobj2.c:42
static void channel_flash_cb(void *data, struct stasis_subscription *sub, struct stasis_message *message)
General Asterisk PBX channel definitions.
static struct ast_manager_event_blob * channel_newexten(struct ast_channel_snapshot *old_snapshot, struct ast_channel_snapshot *new_snapshot)
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 RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:911
struct stasis_message_type * ast_channel_monitor_stop_type(void)
Message type for stopping monitor on a channel.
#define NO_EXTRA_FIELDS
Definition: manager.h:522
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:273
struct ast_str * ast_manager_build_channel_state_string(const struct ast_channel_snapshot *snapshot)
Generate the AMI message body from a channel snapshot.
Channels with this particular technology are an implementation detail of Asterisk and should generall...
Definition: channel.h:972
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.
static void channel_chanspy_stop_cb(void *data, struct stasis_subscription *sub, struct stasis_message *message)
static void channel_monitor_start_cb(void *data, struct stasis_subscription *sub, struct stasis_message *message)
struct ast_channel_snapshot_caller * caller
static void channel_monitor_stop_cb(void *data, struct stasis_subscription *sub, struct stasis_message *message)
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.
char name[0]
Definition: chanvars.h:31
static struct ast_manager_event_blob * channel_new_accountcode(struct ast_channel_snapshot *old_snapshot, struct ast_channel_snapshot *new_snapshot)
struct varshead * manager_vars
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:584
static void publish_basic_channel_event(const char *event, int class, struct ast_channel_snapshot *snapshot)
struct stasis_message_type * ast_channel_mixmonitor_stop_type(void)
Message type for stopping mixmonitor on 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.
void * stasis_message_data(const struct stasis_message *msg)
Get the data contained in a message.
static void channel_dtmf_end_cb(void *data, struct stasis_subscription *sub, struct stasis_message *message)
static void channel_hold_cb(void *data, struct stasis_subscription *sub, struct stasis_message *message)
char * value
Definition: chanvars.h:30
static void channel_unhold_cb(void *data, struct stasis_subscription *sub, struct stasis_message *message)
struct stasis_message_router * ast_manager_get_message_router(void)
Get the stasis_message_router for AMI.
Definition: manager.c:1725
static int dial_status_end(const char *dialstatus)
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
const char * ast_cause2str(int state) attribute_pure
Gives the string form of a given cause code.
Definition: channel.c:612
struct stasis_message_type * ast_channel_hangup_handler_type(void)
Message type for hangup handler related actions.
#define ast_free(a)
Definition: astmm.h:182
static void channel_mixmonitor_start_cb(void *data, struct stasis_subscription *sub, struct stasis_message *message)
static void channel_moh_start_cb(void *data, struct stasis_subscription *sub, struct stasis_message *message)
struct ast_var_t::@249 entries
char * ast_escape_c_alloc(const char *s)
Escape standard &#39;C&#39; sequences in the given string.
Definition: main/utils.c:1892
struct stasis_forward * stasis_forward_cancel(struct stasis_forward *forward)
Definition: stasis.c:1548
static void channel_mixmonitor_mute_cb(void *data, struct stasis_subscription *sub, struct stasis_message *message)
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:1720
const ast_string_field language
static void channel_fax_cb(void *data, struct stasis_subscription *sub, struct stasis_message *message)
FILE * out
Definition: utils/frame.c:33
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
struct ast_json * ast_json_object_get(struct ast_json *object, const char *key)
Get a field from a JSON object.
Definition: json.c:397
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:79
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.
static void handler(const char *name, int response_code, struct ast_variable *get_params, struct ast_variable *path_vars, struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
Definition: test_ari.c:59
size_t ast_json_array_size(const struct ast_json *array)
Get the size of a JSON array.
Definition: json.c:356
struct stasis_forward * sub
Definition: res_corosync.c:240
Abstract JSON element (object, array, string, int, ...).
static void channel_hangup_handler_cb(void *data, struct stasis_subscription *sub, struct stasis_message *message)
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.
static void channel_moh_stop_cb(void *data, struct stasis_subscription *sub, struct stasis_message *message)
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.
direction
#define manager_event(category, event, contents,...)
External routines may send asterisk manager events this way.
Definition: manager.h:248
intmax_t ast_json_integer_get(const struct ast_json *integer)
Get the value from a JSON integer.
Definition: json.c:322
struct stasis_message_type * ast_channel_fax_type(void)
Message type for a fax operation.
struct ast_json * ast_json_array_get(const struct ast_json *array, size_t index)
Get an element from an array.
Definition: json.c:360
channel_snapshot_monitor channel_monitors[]
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.
jack_status_t status
Definition: app_jack.c:146
int manager_channels_init(void)
Initialize support for AMI channel events.
const ast_string_field name
static struct ast_manager_event_blob * channel_new_callerid(struct ast_channel_snapshot *old_snapshot, struct ast_channel_snapshot *new_snapshot)
#define ast_str_create(init_len)
Create a malloc&#39;ed dynamic length string.
Definition: strings.h:620
static void channel_snapshot_update(void *data, struct stasis_subscription *sub, struct stasis_message *message)
static char prefix[MAX_PREFIX]
Definition: http.c:141
struct stasis_message_type * ast_channel_mixmonitor_mute_type(void)
Message type for muting or unmuting mixmonitor on a channel.