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