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