Asterisk - The Open Source Telephony Project  GIT-master-a24979a
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"
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;
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 
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 {
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 
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 = "";
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;
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 {
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  <managerEvent language="en_US" name="DTMFBegin">
895  <managerEventInstance class="EVENT_FLAG_DTMF">
896  <synopsis>Raised when a DTMF digit has started on a channel.</synopsis>
897  <syntax>
898  <channel_snapshot/>
899  <parameter name="Digit">
900  <para>DTMF digit received or transmitted (0-9, A-E, # or *</para>
901  </parameter>
902  <parameter name="Direction">
903  <enumlist>
904  <enum name="Received"/>
905  <enum name="Sent"/>
906  </enumlist>
907  </parameter>
908  </syntax>
909  <see-also>
910  <ref type="managerEvent">DTMFEnd</ref>
911  </see-also>
912  </managerEventInstance>
913  </managerEvent>
914  ***/
915  manager_event(EVENT_FLAG_DTMF, "DTMFBegin",
916  "%s"
917  "Digit: %s\r\n"
918  "Direction: %s\r\n",
919  ast_str_buffer(channel_event_string),
920  digit, direction);
921 }
922 
923 static void channel_dtmf_end_cb(void *data, struct stasis_subscription *sub,
924  struct stasis_message *message)
925 {
927  RAII_VAR(struct ast_str *, channel_event_string, NULL, ast_free);
928  const char *digit =
930  const char *direction =
931  ast_json_string_get(ast_json_object_get(obj->blob, "direction"));
932  long duration_ms =
933  ast_json_integer_get(ast_json_object_get(obj->blob, "duration_ms"));
934 
935  channel_event_string = ast_manager_build_channel_state_string(obj->snapshot);
936 
937  if (!channel_event_string) {
938  return;
939  }
940 
941  /*** DOCUMENTATION
942  <managerEvent language="en_US" name="DTMFEnd">
943  <managerEventInstance class="EVENT_FLAG_DTMF">
944  <synopsis>Raised when a DTMF digit has ended on a channel.</synopsis>
945  <syntax>
946  <channel_snapshot/>
947  <parameter name="Digit">
948  <para>DTMF digit received or transmitted (0-9, A-E, # or *</para>
949  </parameter>
950  <parameter name="DurationMs">
951  <para>Duration (in milliseconds) DTMF was sent/received</para>
952  </parameter>
953  <parameter name="Direction">
954  <enumlist>
955  <enum name="Received"/>
956  <enum name="Sent"/>
957  </enumlist>
958  </parameter>
959  </syntax>
960  <see-also>
961  <ref type="managerEvent">DTMFBegin</ref>
962  </see-also>
963  </managerEventInstance>
964  </managerEvent>
965  ***/
966  manager_event(EVENT_FLAG_DTMF, "DTMFEnd",
967  "%s"
968  "Digit: %s\r\n"
969  "DurationMs: %ld\r\n"
970  "Direction: %s\r\n",
971  ast_str_buffer(channel_event_string),
972  digit, duration_ms, direction);
973 }
974 
975 static void channel_flash_cb(void *data, struct stasis_subscription *sub,
976  struct stasis_message *message)
977 {
979  struct ast_str *channel_event_string;
980 
981  channel_event_string = ast_manager_build_channel_state_string(obj->snapshot);
982  if (!channel_event_string) {
983  return;
984  }
985 
986  /*** DOCUMENTATION
987  <managerEvent language="en_US" name="Flash">
988  <managerEventInstance class="EVENT_FLAG_CALL">
989  <synopsis>Raised when a hook flash occurs on a channel.</synopsis>
990  <syntax>
991  <channel_snapshot/>
992  </syntax>
993  </managerEventInstance>
994  </managerEvent>
995  ***/
997  "%s",
998  ast_str_buffer(channel_event_string));
999 
1000  ast_free(channel_event_string);
1001 }
1002 
1003 static void channel_wink_cb(void *data, struct stasis_subscription *sub,
1004  struct stasis_message *message)
1005 {
1007  struct ast_str *channel_event_string;
1008 
1009  channel_event_string = ast_manager_build_channel_state_string(obj->snapshot);
1010  if (!channel_event_string) {
1011  return;
1012  }
1013 
1014  /*** DOCUMENTATION
1015  <managerEvent language="en_US" name="Wink">
1016  <managerEventInstance class="EVENT_FLAG_CALL">
1017  <synopsis>Raised when a wink occurs on a channel.</synopsis>
1018  <syntax>
1019  <channel_snapshot/>
1020  </syntax>
1021  </managerEventInstance>
1022  </managerEvent>
1023  ***/
1025  "%s",
1026  ast_str_buffer(channel_event_string));
1027 
1028  ast_free(channel_event_string);
1029 }
1030 
1031 static void channel_hangup_handler_cb(void *data, struct stasis_subscription *sub,
1032  struct stasis_message *message)
1033 {
1034  RAII_VAR(struct ast_str *, channel_event_string, NULL, ast_free);
1035  struct ast_channel_blob *payload = stasis_message_data(message);
1036  const char *action = ast_json_string_get(ast_json_object_get(payload->blob, "type"));
1037  const char *handler = ast_json_string_get(ast_json_object_get(payload->blob, "handler"));
1038  const char *event;
1039 
1040  channel_event_string = ast_manager_build_channel_state_string(payload->snapshot);
1041 
1042  if (!channel_event_string) {
1043  return;
1044  }
1045 
1046  if (!strcmp(action, "run")) {
1047  event = "HangupHandlerRun";
1048  } else if (!strcmp(action, "pop")) {
1049  event = "HangupHandlerPop";
1050  } else if (!strcmp(action, "push")) {
1051  event = "HangupHandlerPush";
1052  } else {
1053  return;
1054  }
1056  "%s"
1057  "Handler: %s\r\n",
1058  ast_str_buffer(channel_event_string),
1059  handler);
1060 }
1061 
1062 static void channel_fax_cb(void *data, struct stasis_subscription *sub,
1063  struct stasis_message *message)
1064 {
1065  RAII_VAR(struct ast_str *, channel_event_string, NULL, ast_free);
1066  RAII_VAR(struct ast_str *, event_buffer, ast_str_create(256), ast_free);
1067  struct ast_channel_blob *payload = stasis_message_data(message);
1068  const char *type = ast_json_string_get(ast_json_object_get(payload->blob, "type"));
1069  struct ast_json *operation = ast_json_object_get(payload->blob, "operation");
1070  struct ast_json *status = ast_json_object_get(payload->blob, "status");
1071  struct ast_json *local_station_id = ast_json_object_get(payload->blob, "local_station_id");
1072  struct ast_json *remote_station_id = ast_json_object_get(payload->blob, "remote_station_id");
1073  struct ast_json *fax_pages = ast_json_object_get(payload->blob, "fax_pages");
1074  struct ast_json *fax_resolution = ast_json_object_get(payload->blob, "fax_resolution");
1075  struct ast_json *fax_bitrate = ast_json_object_get(payload->blob, "fax_bitrate");
1076  struct ast_json *filenames = ast_json_object_get(payload->blob, "filenames");
1077  const char *event;
1078  size_t array_len;
1079  size_t i;
1080 
1081  if (!event_buffer) {
1082  return;
1083  }
1084 
1085  channel_event_string = ast_manager_build_channel_state_string(payload->snapshot);
1086  if (!channel_event_string) {
1087  return;
1088  }
1089 
1090  if (!strcmp(type, "status")) {
1091  event = "FAXStatus";
1092  } else if (!strcmp(type, "receive")) {
1093  event = "ReceiveFAX";
1094  } else if (!strcmp(type, "send")) {
1095  event = "SendFAX";
1096  } else {
1097  return;
1098  }
1099 
1100  if (operation) {
1101  ast_str_append(&event_buffer, 0, "Operation: %s\r\n", ast_json_string_get(operation));
1102  }
1103  if (status) {
1104  ast_str_append(&event_buffer, 0, "Status: %s\r\n", ast_json_string_get(status));
1105  }
1106  if (local_station_id) {
1107  ast_str_append(&event_buffer, 0, "LocalStationID: %s\r\n", ast_json_string_get(local_station_id));
1108  }
1109  if (remote_station_id) {
1110  ast_str_append(&event_buffer, 0, "RemoteStationID: %s\r\n", ast_json_string_get(remote_station_id));
1111  }
1112  if (fax_pages) {
1113  ast_str_append(&event_buffer, 0, "PagesTransferred: %s\r\n", ast_json_string_get(fax_pages));
1114  }
1115  if (fax_resolution) {
1116  ast_str_append(&event_buffer, 0, "Resolution: %s\r\n", ast_json_string_get(fax_resolution));
1117  }
1118  if (fax_bitrate) {
1119  ast_str_append(&event_buffer, 0, "TransferRate: %s\r\n", ast_json_string_get(fax_bitrate));
1120  }
1121  if (filenames) {
1122  array_len = ast_json_array_size(filenames);
1123  for (i = 0; i < array_len; i++) {
1124  ast_str_append(&event_buffer, 0, "FileName: %s\r\n", ast_json_string_get(ast_json_array_get(filenames, i)));
1125  }
1126  }
1127 
1129  "%s"
1130  "%s",
1131  ast_str_buffer(channel_event_string),
1132  ast_str_buffer(event_buffer));
1133 }
1134 
1135 static void channel_moh_start_cb(void *data, struct stasis_subscription *sub,
1136  struct stasis_message *message)
1137 {
1138  struct ast_channel_blob *payload = stasis_message_data(message);
1139  struct ast_json *blob = payload->blob;
1140  RAII_VAR(struct ast_str *, channel_event_string, NULL, ast_free);
1141 
1142  channel_event_string = ast_manager_build_channel_state_string(payload->snapshot);
1143  if (!channel_event_string) {
1144  return;
1145  }
1146 
1147  manager_event(EVENT_FLAG_CALL, "MusicOnHoldStart",
1148  "%s"
1149  "Class: %s\r\n",
1150  ast_str_buffer(channel_event_string),
1151  ast_json_string_get(ast_json_object_get(blob, "class")));
1152 
1153 }
1154 
1155 static void channel_moh_stop_cb(void *data, struct stasis_subscription *sub,
1156  struct stasis_message *message)
1157 {
1158  struct ast_channel_blob *payload = stasis_message_data(message);
1159 
1160  publish_basic_channel_event("MusicOnHoldStop", EVENT_FLAG_CALL, payload->snapshot);
1161 }
1162 
1163 static void channel_monitor_start_cb(void *data, struct stasis_subscription *sub,
1164  struct stasis_message *message)
1165 {
1166  struct ast_channel_blob *payload = stasis_message_data(message);
1167 
1168  publish_basic_channel_event("MonitorStart", EVENT_FLAG_CALL, payload->snapshot);
1169 }
1170 
1171 static void channel_monitor_stop_cb(void *data, struct stasis_subscription *sub,
1172  struct stasis_message *message)
1173 {
1174  struct ast_channel_blob *payload = stasis_message_data(message);
1175 
1176  publish_basic_channel_event("MonitorStop", EVENT_FLAG_CALL, payload->snapshot);
1177 }
1178 
1179 static void channel_mixmonitor_start_cb(void *data, struct stasis_subscription *sub,
1180  struct stasis_message *message)
1181 {
1182  struct ast_channel_blob *payload = stasis_message_data(message);
1183 
1184  publish_basic_channel_event("MixMonitorStart", EVENT_FLAG_CALL, payload->snapshot);
1185 }
1186 
1187 static void channel_mixmonitor_stop_cb(void *data, struct stasis_subscription *sub,
1188  struct stasis_message *message)
1189 {
1190  struct ast_channel_blob *payload = stasis_message_data(message);
1191 
1192  publish_basic_channel_event("MixMonitorStop", EVENT_FLAG_CALL, payload->snapshot);
1193 }
1194 
1195 static void channel_mixmonitor_mute_cb(void *data, struct stasis_subscription *sub,
1196  struct stasis_message *message)
1197 {
1198  RAII_VAR(struct ast_str *, channel_event_string, NULL, ast_free);
1199  RAII_VAR(struct ast_str *, event_buffer, ast_str_create(64), ast_free);
1200  struct ast_channel_blob *payload = stasis_message_data(message);
1201  struct ast_json *direction = ast_json_object_get(payload->blob, "direction");
1202  const int state = ast_json_is_true(ast_json_object_get(payload->blob, "state"));
1203 
1204  if (!event_buffer) {
1205  return;
1206  }
1207 
1208  channel_event_string = ast_manager_build_channel_state_string(payload->snapshot);
1209  if (!channel_event_string) {
1210  return;
1211  }
1212 
1213  if (direction) {
1214  ast_str_append(&event_buffer, 0, "Direction: %s\r\n", ast_json_string_get(direction));
1215  }
1216  ast_str_append(&event_buffer, 0, "State: %s\r\n", state ? "1" : "0");
1217 
1218  manager_event(EVENT_FLAG_CALL, "MixMonitorMute",
1219  "%s"
1220  "%s",
1221  ast_str_buffer(channel_event_string),
1222  ast_str_buffer(event_buffer));
1223 
1224 }
1225 
1226 static int dial_status_end(const char *dialstatus)
1227 {
1228  return (strcmp(dialstatus, "RINGING") &&
1229  strcmp(dialstatus, "PROCEEDING") &&
1230  strcmp(dialstatus, "PROGRESS"));
1231 }
1232 
1233 /*!
1234  * \brief Callback processing messages for channel dialing
1235  */
1236 static void channel_dial_cb(void *data, struct stasis_subscription *sub,
1237  struct stasis_message *message)
1238 {
1240  const char *dialstatus;
1241  const char *dialstring;
1242  const char *forward;
1243  struct ast_channel_snapshot *caller;
1244  struct ast_channel_snapshot *peer;
1245  RAII_VAR(struct ast_str *, caller_event_string, NULL, ast_free);
1246  RAII_VAR(struct ast_str *, peer_event_string, NULL, ast_free);
1247 
1248  caller = ast_multi_channel_blob_get_channel(obj, "caller");
1250 
1251  /* Peer is required - otherwise, who are we dialing? */
1252  ast_assert(peer != NULL);
1253  peer_event_string = ast_manager_build_channel_state_string_prefix(peer, "Dest");
1254  if (!peer_event_string) {
1255  return;
1256  }
1257 
1258  if (caller && !(caller_event_string = ast_manager_build_channel_state_string(caller))) {
1259  return;
1260  }
1261 
1265  if (ast_strlen_zero(dialstatus)) {
1266  manager_event(EVENT_FLAG_CALL, "DialBegin",
1267  "%s"
1268  "%s"
1269  "DialString: %s\r\n",
1270  caller_event_string ? ast_str_buffer(caller_event_string) : "",
1271  ast_str_buffer(peer_event_string),
1272  S_OR(dialstring, "unknown"));
1273  } else {
1274  int forwarded = !ast_strlen_zero(forward);
1275 
1276  manager_event(EVENT_FLAG_CALL, dial_status_end(dialstatus) ? "DialEnd" : "DialState",
1277  "%s"
1278  "%s"
1279  "%s%s%s"
1280  "DialStatus: %s\r\n",
1281  caller_event_string ? ast_str_buffer(caller_event_string) : "",
1282  ast_str_buffer(peer_event_string),
1283  forwarded ? "Forward: " : "", S_OR(forward, ""), forwarded ? "\r\n" : "",
1284  S_OR(dialstatus, "unknown"));
1285  }
1286 
1287 }
1288 
1289 static void channel_hold_cb(void *data, struct stasis_subscription *sub,
1290  struct stasis_message *message)
1291 {
1293  struct ast_str *musicclass_string = ast_str_create(32);
1294  struct ast_str *channel_event_string;
1295 
1296  if (!musicclass_string) {
1297  return;
1298  }
1299 
1300  channel_event_string = ast_manager_build_channel_state_string(obj->snapshot);
1301  if (!channel_event_string) {
1302  ast_free(musicclass_string);
1303  return;
1304  }
1305 
1306  if (obj->blob) {
1307  const char *musicclass;
1308 
1309  musicclass = ast_json_string_get(ast_json_object_get(obj->blob, "musicclass"));
1310 
1311  if (!ast_strlen_zero(musicclass)) {
1312  ast_str_set(&musicclass_string, 0, "MusicClass: %s\r\n", musicclass);
1313  }
1314  }
1315 
1317  "%s"
1318  "%s",
1319  ast_str_buffer(channel_event_string),
1320  ast_str_buffer(musicclass_string));
1321 
1322  ast_free(musicclass_string);
1323  ast_free(channel_event_string);
1324 }
1325 
1326 static void channel_unhold_cb(void *data, struct stasis_subscription *sub,
1327  struct stasis_message *message)
1328 {
1330  struct ast_str *channel_event_string;
1331 
1332  channel_event_string = ast_manager_build_channel_state_string(obj->snapshot);
1333  if (!channel_event_string) {
1334  return;
1335  }
1336 
1337  manager_event(EVENT_FLAG_CALL, "Unhold",
1338  "%s",
1339  ast_str_buffer(channel_event_string));
1340 
1341  ast_free(channel_event_string);
1342 }
1343 
1344 static void manager_channels_shutdown(void)
1345 {
1348 }
1349 
1351 {
1352  int ret = 0;
1353  struct stasis_topic *manager_topic;
1354  struct stasis_topic *channel_topic;
1355  struct stasis_message_router *message_router;
1356 
1358  if (!manager_topic) {
1359  return -1;
1360  }
1361  message_router = ast_manager_get_message_router();
1362  if (!message_router) {
1363  return -1;
1364  }
1365  channel_topic = ast_channel_topic_all();
1366  if (!channel_topic) {
1367  return -1;
1368  }
1369 
1371  if (!topic_forwarder) {
1372  return -1;
1373  }
1374 
1376 
1377  /* The snapshot type has a special handler as it can result in multiple
1378  * manager events being queued due to aspects of the snapshot itself
1379  * changing.
1380  */
1381  ret |= stasis_message_router_add(message_router,
1383 
1384  ret |= stasis_message_router_add(message_router,
1386 
1387  ret |= stasis_message_router_add(message_router,
1389 
1390  ret |= stasis_message_router_add(message_router,
1392 
1393  ret |= stasis_message_router_add(message_router,
1395 
1396  ret |= stasis_message_router_add(message_router,
1398  NULL);
1399 
1400  ret |= stasis_message_router_add(message_router,
1402 
1403  ret |= stasis_message_router_add(message_router,
1405 
1406  ret |= stasis_message_router_add(message_router,
1408 
1409  ret |= stasis_message_router_add(message_router,
1411 
1412  ret |= stasis_message_router_add(message_router,
1414  NULL);
1415 
1416  ret |= stasis_message_router_add(message_router,
1418 
1419  ret |= stasis_message_router_add(message_router,
1421  NULL);
1422 
1423  ret |= stasis_message_router_add(message_router,
1425 
1426  ret |= stasis_message_router_add(message_router,
1428 
1429  ret |= stasis_message_router_add(message_router,
1431  NULL);
1432 
1433  ret |= stasis_message_router_add(message_router,
1435 
1436  ret |= stasis_message_router_add(message_router,
1438 
1439  ret |= stasis_message_router_add(message_router,
1441 
1442  ret |= stasis_message_router_add(message_router,
1444 
1445  /* If somehow we failed to add any routes, just shut down the whole
1446  * thing and fail it.
1447  */
1448  if (ret) {
1450  return -1;
1451  }
1452 
1453  return 0;
1454 }
char digit
jack_status_t status
Definition: app_jack.c:146
#define var
Definition: ast_expr2f.c:614
Asterisk main include file. File version handling, generic pbx functions.
int ast_register_cleanup(void(*func)(void))
Register a function to be executed before Asterisk gracefully exits.
Definition: clicompat.c:19
#define ast_free(a)
Definition: astmm.h:180
#define ast_log
Definition: astobj2.c:42
#define ao2_cleanup(obj)
Definition: astobj2.h:1934
CallerID (and other GR30) management and generation Includes code and algorithms from the Zapata libr...
const char * ast_describe_caller_presentation(int data)
Convert caller ID pres value to explanatory string.
Definition: callerid.c:1164
static char musicclass[MAX_MUSICCLASS]
Definition: chan_mgcp.c:165
static const char type[]
Definition: chan_ooh323.c:109
General Asterisk PBX channel definitions.
const char * ast_cause2str(int cause) attribute_pure
Gives the string form of a given cause code.
Definition: channel.c:612
const char * ast_state2str(enum ast_channel_state state)
Gives the string form of a given channel state.
Definition: channel.c:636
@ AST_FLAG_DEAD
Definition: channel.h:1045
@ AST_CHAN_TP_INTERNAL
Channels with this particular technology are an implementation detail of Asterisk and should generall...
Definition: channel.h:971
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
direction
struct stasis_topic * ast_manager_get_topic(void)
Get the Stasis Message Bus API topic for AMI.
Definition: manager.c:1727
struct stasis_message_router * ast_manager_get_message_router(void)
Get the stasis_message_router for AMI.
Definition: manager.c:1732
static struct stasis_topic * manager_topic
A stasis_topic that all topics AMI cares about will be forwarded to.
Definition: manager.c:1497
struct stasis_message_type * ast_channel_monitor_stop_type(void)
Message type for stopping monitor on a channel.
struct stasis_message_type * ast_channel_mixmonitor_start_type(void)
Message type for starting mixmonitor on a channel.
struct stasis_message_type * ast_channel_moh_stop_type(void)
Message type for stopping music on hold on a channel.
struct stasis_topic * ast_channel_topic_all(void)
A topic which publishes the events for all channels.
struct stasis_message_type * ast_channel_mixmonitor_mute_type(void)
Message type for muting or unmuting mixmonitor on a channel.
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.
struct stasis_message_type * ast_channel_flash_type(void)
Message type for when a hook flash occurs on a channel.
struct stasis_message_type * ast_channel_wink_type(void)
Message type for when a wink occurs on a channel.
struct stasis_message_type * ast_channel_hold_type(void)
Message type for when a channel is placed on hold.
struct stasis_message_type * ast_channel_monitor_start_type(void)
Message type for starting monitor on a channel.
struct stasis_message_type * ast_channel_chanspy_stop_type(void)
Message type for when a channel stops spying on another channel.
struct stasis_message_type * ast_channel_fax_type(void)
Message type for a fax operation.
struct stasis_message_type * ast_channel_chanspy_start_type(void)
Message type for when a channel starts spying on another channel.
struct stasis_message_type * ast_channel_snapshot_type(void)
Message type for ast_channel_snapshot_update.
struct stasis_message_type * ast_channel_dtmf_begin_type(void)
Message type for when DTMF begins on a channel.
struct stasis_message_type * ast_channel_dtmf_end_type(void)
Message type for when DTMF ends on a channel.
struct stasis_message_type * ast_channel_hangup_request_type(void)
Message type for when a hangup is requested on a channel.
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.
struct stasis_message_type * ast_channel_unhold_type(void)
Message type for when a channel is removed from hold.
struct stasis_message_type * ast_channel_mixmonitor_stop_type(void)
Message type for stopping mixmonitor on a channel.
struct stasis_message_type * ast_channel_moh_start_type(void)
Message type for starting music on hold on a channel.
struct stasis_message_type * ast_channel_dial_type(void)
Message type for when a channel dials another channel.
struct stasis_message_type * ast_channel_hangup_handler_type(void)
Message type for hangup handler related actions.
static char prefix[MAX_PREFIX]
Definition: http.c:144
#define AST_LOG_WARNING
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
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 char * ast_json_string_get(const struct ast_json *string)
Get the value of a JSON string.
Definition: json.c:273
intmax_t ast_json_integer_get(const struct ast_json *integer)
Get the value from a JSON integer.
Definition: json.c:322
int ast_json_is_true(const struct ast_json *value)
Check if value is JSON true.
Definition: json.c:253
size_t ast_json_array_size(const struct ast_json *array)
Get the size of a JSON array.
Definition: json.c:356
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:491
The AMI - Asterisk Manager Interface - is a TCP protocol created to manage Asterisk with third-party ...
#define manager_event(category, event, contents,...)
External routines may send asterisk manager events this way.
Definition: manager.h:253
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:9760
#define NO_EXTRA_FIELDS
Definition: manager.h:521
#define EVENT_FLAG_DTMF
Definition: manager.h:83
#define EVENT_FLAG_CALL
Definition: manager.h:76
#define EVENT_FLAG_DIALPLAN
Definition: manager.h:86
static void channel_flash_cb(void *data, struct stasis_subscription *sub, struct stasis_message *message)
static void channel_hangup_handler_cb(void *data, struct stasis_subscription *sub, struct stasis_message *message)
static void channel_chanspy_stop_cb(void *data, struct stasis_subscription *sub, struct stasis_message *message)
static struct ast_manager_event_blob * channel_newexten(struct ast_channel_snapshot *old_snapshot, struct ast_channel_snapshot *new_snapshot)
static void channel_snapshot_update(void *data, struct stasis_subscription *sub, struct stasis_message *message)
static struct ast_manager_event_blob * channel_new_callerid(struct ast_channel_snapshot *old_snapshot, struct ast_channel_snapshot *new_snapshot)
static void channel_mixmonitor_start_cb(void *data, struct stasis_subscription *sub, struct stasis_message *message)
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 struct ast_manager_event_blob * channel_new_accountcode(struct ast_channel_snapshot *old_snapshot, struct ast_channel_snapshot *new_snapshot)
static void channel_dtmf_end_cb(void *data, struct stasis_subscription *sub, struct stasis_message *message)
static void channel_mixmonitor_stop_cb(void *data, struct stasis_subscription *sub, struct stasis_message *message)
static void channel_dial_cb(void *data, struct stasis_subscription *sub, struct stasis_message *message)
Callback processing messages for channel dialing.
static int dial_status_end(const char *dialstatus)
struct ast_str * ast_manager_build_channel_state_string(const struct ast_channel_snapshot *snapshot)
Generate the AMI message body from a channel snapshot.
static void channel_monitor_start_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)
static void channel_moh_start_cb(void *data, struct stasis_subscription *sub, struct stasis_message *message)
static void channel_wink_cb(void *data, struct stasis_subscription *sub, struct stasis_message *message)
static void publish_basic_channel_event(const char *event, int class, struct ast_channel_snapshot *snapshot)
static void channel_fax_cb(void *data, struct stasis_subscription *sub, struct stasis_message *message)
static void channel_chanspy_start_cb(void *data, struct stasis_subscription *sub, struct stasis_message *message)
static void channel_hangup_request_cb(void *data, struct stasis_subscription *sub, struct stasis_message *message)
static void channel_dtmf_begin_cb(void *data, struct stasis_subscription *sub, struct stasis_message *message)
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.
int manager_channels_init(void)
Initialize support for AMI channel events.
static void channel_monitor_stop_cb(void *data, struct stasis_subscription *sub, struct stasis_message *message)
channel_snapshot_monitor channel_monitors[]
static void channel_moh_stop_cb(void *data, struct stasis_subscription *sub, struct stasis_message *message)
static struct ast_manager_event_blob * channel_new_connected_line(struct ast_channel_snapshot *old_snapshot, struct ast_channel_snapshot *new_snapshot)
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.
static void channel_mixmonitor_mute_cb(void *data, struct stasis_subscription *sub, struct stasis_message *message)
static void manager_channels_shutdown(void)
static struct stasis_forward * topic_forwarder
The Stasis Message Bus API subscription returned by the forwarding of the channel topic to the manage...
static void channel_unhold_cb(void *data, struct stasis_subscription *sub, struct stasis_message *message)
Core PBX routines and definitions.
struct stasis_forward * sub
Definition: res_corosync.c:240
#define NULL
Definition: resample.c:96
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:1580
struct stasis_forward * stasis_forward_cancel(struct stasis_forward *forward)
Definition: stasis.c:1550
void * stasis_message_data(const struct stasis_message *msg)
Get the data contained in a 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.
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.
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.
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:1117
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:739
#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
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
char * ast_escape_c_alloc(const char *s)
Escape standard 'C' sequences in the given string.
Definition: main/utils.c:2038
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
Definition: strings.h:640
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:1091
Blob of data associated with a channel.
struct ast_channel_snapshot * snapshot
struct ast_json * blob
const ast_string_field language
const ast_string_field accountcode
const ast_string_field uniqueid
const ast_string_field name
const ast_string_field number
const ast_string_field name
const ast_string_field data
const ast_string_field context
const ast_string_field exten
const ast_string_field appl
Structure representing a change of snapshot of channel state.
Structure representing a snapshot of channel state.
struct ast_channel_snapshot_connected * connected
struct varshead * manager_vars
struct ast_channel_snapshot_dialplan * dialplan
struct ast_channel_snapshot_peer * peer
struct ast_channel_snapshot_base * base
enum ast_channel_state state
struct ast_channel_snapshot_caller * caller
struct ast_flags flags
struct ast_channel_snapshot_hangup * hangup
Abstract JSON element (object, array, string, int, ...).
Struct containing info for an AMI event to send out.
Definition: manager.h:490
A multi channel blob data structure for multi_channel_blob stasis messages.
Support for dynamic strings.
Definition: strings.h:604
struct ast_var_t::@239 entries
Definition: astman.c:222
Forwarding information.
Definition: stasis.c:1533
Definition: ast_expr2.c:325
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
FILE * out
Definition: utils/frame.c:33
#define ast_test_flag(p, flag)
Definition: utils.h:63
#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:936
#define ast_assert(a)
Definition: utils.h:734
#define ARRAY_LEN(a)
Definition: utils.h:661