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