Asterisk - The Open Source Telephony Project GIT-master-754dea3
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros Modules Pages
confbridge_manager.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 * Jonathan Rose <jrose@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 Confbridge manager events for stasis messages
22 *
23 * \author Jonathan Rose <jrose@digium.com>
24 */
25
26#include "asterisk.h"
27
28#include "asterisk/channel.h"
29#include "asterisk/bridge.h"
30#include "asterisk/stasis.h"
33#include "asterisk/manager.h"
35#include "include/confbridge.h"
36#include "asterisk/message.h"
37#include "asterisk/stream.h"
38
39/*** DOCUMENTATION
40 <managerEvent language="en_US" name="ConfbridgeStart">
41 <managerEventInstance class="EVENT_FLAG_CALL">
42 <since>
43 <version>12.0.0</version>
44 </since>
45 <synopsis>Raised when a conference starts.</synopsis>
46 <syntax>
47 <parameter name="Conference">
48 <para>The name of the Confbridge conference.</para>
49 </parameter>
50 <bridge_snapshot/>
51 </syntax>
52 <see-also>
53 <ref type="managerEvent">ConfbridgeEnd</ref>
54 <ref type="application">ConfBridge</ref>
55 </see-also>
56 </managerEventInstance>
57 </managerEvent>
58 <managerEvent language="en_US" name="ConfbridgeEnd">
59 <managerEventInstance class="EVENT_FLAG_CALL">
60 <since>
61 <version>12.0.0</version>
62 </since>
63 <synopsis>Raised when a conference ends.</synopsis>
64 <syntax>
65 <parameter name="Conference">
66 <para>The name of the Confbridge conference.</para>
67 </parameter>
68 <bridge_snapshot/>
69 </syntax>
70 <see-also>
71 <ref type="managerEvent">ConfbridgeStart</ref>
72 <ref type="application">ConfBridge</ref>
73 </see-also>
74 </managerEventInstance>
75 </managerEvent>
76 <managerEvent language="en_US" name="ConfbridgeJoin">
77 <managerEventInstance class="EVENT_FLAG_CALL">
78 <since>
79 <version>12.0.0</version>
80 </since>
81 <synopsis>Raised when a channel joins a Confbridge conference.</synopsis>
82 <syntax>
83 <parameter name="Conference">
84 <para>The name of the Confbridge conference.</para>
85 </parameter>
86 <bridge_snapshot/>
87 <channel_snapshot/>
88 <parameter name="Admin">
89 <para>Identifies this user as an admin user.</para>
90 <enumlist>
91 <enum name="Yes"/>
92 <enum name="No"/>
93 </enumlist>
94 </parameter>
95 <parameter name="Muted">
96 <para>The joining mute status.</para>
97 <enumlist>
98 <enum name="Yes"/>
99 <enum name="No"/>
100 </enumlist>
101 </parameter>
102 </syntax>
103 <see-also>
104 <ref type="managerEvent">ConfbridgeLeave</ref>
105 <ref type="application">ConfBridge</ref>
106 </see-also>
107 </managerEventInstance>
108 </managerEvent>
109 <managerEvent language="en_US" name="ConfbridgeLeave">
110 <managerEventInstance class="EVENT_FLAG_CALL">
111 <since>
112 <version>12.0.0</version>
113 </since>
114 <synopsis>Raised when a channel leaves a Confbridge conference.</synopsis>
115 <syntax>
116 <parameter name="Conference">
117 <para>The name of the Confbridge conference.</para>
118 </parameter>
119 <bridge_snapshot/>
120 <channel_snapshot/>
121 <parameter name="Admin">
122 <para>Identifies this user as an admin user.</para>
123 <enumlist>
124 <enum name="Yes"/>
125 <enum name="No"/>
126 </enumlist>
127 </parameter>
128 </syntax>
129 <see-also>
130 <ref type="managerEvent">ConfbridgeJoin</ref>
131 <ref type="application">ConfBridge</ref>
132 </see-also>
133 </managerEventInstance>
134 </managerEvent>
135 <managerEvent language="en_US" name="ConfbridgeRecord">
136 <managerEventInstance class="EVENT_FLAG_CALL">
137 <since>
138 <version>12.0.0</version>
139 </since>
140 <synopsis>Raised when a conference starts recording.</synopsis>
141 <syntax>
142 <parameter name="Conference">
143 <para>The name of the Confbridge conference.</para>
144 </parameter>
145 <bridge_snapshot/>
146 </syntax>
147 <see-also>
148 <ref type="managerEvent">ConfbridgeStopRecord</ref>
149 <ref type="application">ConfBridge</ref>
150 </see-also>
151 </managerEventInstance>
152 </managerEvent>
153 <managerEvent language="en_US" name="ConfbridgeStopRecord">
154 <managerEventInstance class="EVENT_FLAG_CALL">
155 <since>
156 <version>12.0.0</version>
157 </since>
158 <synopsis>Raised when a conference that was recording stops recording.</synopsis>
159 <syntax>
160 <parameter name="Conference">
161 <para>The name of the Confbridge conference.</para>
162 </parameter>
163 <bridge_snapshot/>
164 </syntax>
165 <see-also>
166 <ref type="managerEvent">ConfbridgeRecord</ref>
167 <ref type="application">ConfBridge</ref>
168 </see-also>
169 </managerEventInstance>
170 </managerEvent>
171 <managerEvent language="en_US" name="ConfbridgeMute">
172 <managerEventInstance class="EVENT_FLAG_CALL">
173 <since>
174 <version>12.0.0</version>
175 </since>
176 <synopsis>Raised when a Confbridge participant mutes.</synopsis>
177 <syntax>
178 <parameter name="Conference">
179 <para>The name of the Confbridge conference.</para>
180 </parameter>
181 <bridge_snapshot/>
182 <channel_snapshot/>
183 <parameter name="Admin">
184 <para>Identifies this user as an admin user.</para>
185 <enumlist>
186 <enum name="Yes"/>
187 <enum name="No"/>
188 </enumlist>
189 </parameter>
190 </syntax>
191 <see-also>
192 <ref type="managerEvent">ConfbridgeUnmute</ref>
193 <ref type="application">ConfBridge</ref>
194 </see-also>
195 </managerEventInstance>
196 </managerEvent>
197 <managerEvent language="en_US" name="ConfbridgeUnmute">
198 <managerEventInstance class="EVENT_FLAG_CALL">
199 <since>
200 <version>12.0.0</version>
201 </since>
202 <synopsis>Raised when a confbridge participant unmutes.</synopsis>
203 <syntax>
204 <parameter name="Conference">
205 <para>The name of the Confbridge conference.</para>
206 </parameter>
207 <bridge_snapshot/>
208 <channel_snapshot/>
209 <parameter name="Admin">
210 <para>Identifies this user as an admin user.</para>
211 <enumlist>
212 <enum name="Yes"/>
213 <enum name="No"/>
214 </enumlist>
215 </parameter>
216 </syntax>
217 <see-also>
218 <ref type="managerEvent">ConfbridgeMute</ref>
219 <ref type="application">ConfBridge</ref>
220 </see-also>
221 </managerEventInstance>
222 </managerEvent>
223 <managerEvent language="en_US" name="ConfbridgeTalking">
224 <managerEventInstance class="EVENT_FLAG_CALL">
225 <since>
226 <version>12.0.0</version>
227 </since>
228 <synopsis>Raised when a confbridge participant begins or ends talking.</synopsis>
229 <syntax>
230 <parameter name="Conference">
231 <para>The name of the Confbridge conference.</para>
232 </parameter>
233 <bridge_snapshot/>
234 <channel_snapshot/>
235 <parameter name="TalkingStatus">
236 <enumlist>
237 <enum name="on"/>
238 <enum name="off"/>
239 </enumlist>
240 </parameter>
241 <parameter name="Admin">
242 <para>Identifies this user as an admin user.</para>
243 <enumlist>
244 <enum name="Yes"/>
245 <enum name="No"/>
246 </enumlist>
247 </parameter>
248 </syntax>
249 <see-also>
250 <ref type="application">ConfBridge</ref>
251 </see-also>
252 </managerEventInstance>
253 </managerEvent>
254***/
255
258
268/*
269 * The welcome message is defined here but is only sent
270 * to participants and only when events are enabled.
271 * At the current time, no actual stasis or AMI events
272 * are generated for this type.
273 */
275
277{
278 if (event_type == confbridge_start_type()) {
279 return "ConfbridgeStart";
280 } else if (event_type == confbridge_end_type()) {
281 return "ConfbridgeEnd";
282 } else if (event_type == confbridge_join_type()) {
283 return "ConfbridgeJoin";
284 } else if (event_type == confbridge_leave_type()) {
285 return "ConfbridgeLeave";
286 } else if (event_type == confbridge_start_record_type()) {
287 return "ConfbridgeRecord";
288 } else if (event_type == confbridge_stop_record_type()) {
289 return "ConfbridgeStopRecord";
290 } else if (event_type == confbridge_mute_type()) {
291 return "ConfbridgeMute";
292 } else if (event_type == confbridge_unmute_type()) {
293 return "ConfbridgeUnmute";
294 } else if (event_type == confbridge_talking_type()) {
295 return "ConfbridgeTalking";
296 } else if (event_type == confbridge_welcome_type()) {
297 return "ConfbridgeWelcome";
298 } else {
299 return "unknown";
300 }
301}
302
303static struct ast_json *channel_to_json(struct ast_channel_snapshot *channel_snapshot,
304 struct ast_json *conf_blob, struct ast_json *labels_blob)
305{
306 struct ast_json *json_channel = ast_channel_snapshot_to_json(channel_snapshot, NULL);
307
308 if (!json_channel) {
309 return NULL;
310 }
311
312 /* These items are removed for privacy reasons. */
313 ast_json_object_del(json_channel, "dialplan");
314 ast_json_object_del(json_channel, "connected");
315 ast_json_object_del(json_channel, "accountcode");
316
317 /* conf_blob contains flags such as talking, admin, mute, etc. */
318 if (conf_blob) {
319 struct ast_json *conf_copy = ast_json_copy(conf_blob);
320
321 if (!conf_copy) {
322 ast_json_unref(json_channel);
323 return NULL;
324 }
325 ast_json_object_del(conf_copy, "conference");
326 ast_json_object_update(json_channel, conf_copy);
327 ast_json_unref(conf_copy);
328 }
329
330 /* labels_blob contains the msid labels to correlate to streams. */
331 if (labels_blob) {
332 ast_json_object_update(json_channel, labels_blob);
333 }
334
335 return json_channel;
336}
337
338static struct ast_json *bridge_to_json(struct ast_bridge_snapshot *bridge_snapshot)
339{
340 struct ast_json *json_bridge = ast_bridge_snapshot_to_json(bridge_snapshot, NULL);
341
342 if (!json_bridge) {
343 return NULL;
344 }
345
346 /* These items have no use in the context of bridge participant info. */
347 ast_json_object_del(json_bridge, "technology");
348 ast_json_object_del(json_bridge, "bridge_type");
349 ast_json_object_del(json_bridge, "bridge_class");
350 ast_json_object_del(json_bridge, "creator");
351 ast_json_object_del(json_bridge, "channels");
352
353 return json_bridge;
354}
355
357 struct ast_json *json_bridge, struct ast_json *json_channel,
358 struct stasis_message *msg)
359{
360 const struct timeval *tv = stasis_message_timestamp(msg);
361 const char *msg_name = confbridge_event_type_to_string(stasis_message_type(msg));
362
363 return ast_json_pack("{s: s, s: o, s: o, s: [o*]}",
364 "type", msg_name,
365 "timestamp", ast_json_timeval(*tv, NULL),
366 "bridge", json_bridge,
367 "channels", json_channel);
368}
369
371 struct ast_json *json_bridge, struct ast_json *json_channels,
372 struct stasis_message *msg)
373{
374 const struct timeval *tv = stasis_message_timestamp(msg);
375 const char *msg_name = confbridge_event_type_to_string(stasis_message_type(msg));
376
377 return ast_json_pack("{s: s, s: o, s: o, s: o}",
378 "type", msg_name,
379 "timestamp", ast_json_timeval(*tv, NULL),
380 "bridge", json_bridge,
381 "channels", json_channels);
382}
383
384static struct ast_json *pack_snapshots( struct ast_bridge_snapshot *bridge_snapshot,
385 struct ast_channel_snapshot *channel_snapshot, struct ast_json *conf_blob,
386 struct ast_json *labels_blob, struct stasis_message * msg)
387{
388 struct ast_json *json_bridge;
389 struct ast_json *json_channel;
390
391 json_bridge = bridge_to_json(bridge_snapshot);
392 json_channel = channel_to_json(channel_snapshot, conf_blob, labels_blob);
393
394 return pack_bridge_and_channel(json_bridge, json_channel, msg);
395}
396
397static void send_message(const char *msg_name, char *conf_name, struct ast_json *json_object,
398 struct ast_channel *chan)
399{
400 struct ast_msg_data *data_msg;
401 struct ast_msg_data_attribute attrs[] = {
402 { .type = AST_MSG_DATA_ATTR_FROM, conf_name },
403 { .type = AST_MSG_DATA_ATTR_CONTENT_TYPE, .value = "application/x-asterisk-confbridge-event+json"},
404 { .type = AST_MSG_DATA_ATTR_BODY, },
405 };
406 char *json;
407 int rc = 0;
408 struct ast_frame f;
409 RAII_VAR(struct ast_bridge_channel *, bridge_chan, NULL, ao2_cleanup);
410
411 bridge_chan = ast_channel_get_bridge_channel(chan);
412 if (!bridge_chan) {
413 /* Don't complain if we can't get the bridge_chan. The channel is probably gone. */
414 return;
415 }
416
417 json = ast_json_dump_string_format(json_object, AST_JSON_PRETTY);
418 if (!json) {
419 ast_log(LOG_ERROR, "Unable to convert json_object for %s message to string\n", msg_name);
420 return;
421 }
422 attrs[2].value = json;
423
425 if (!data_msg) {
426 ast_log(LOG_ERROR, "Unable to create %s message for channel '%s'\n", msg_name,
427 ast_channel_name(chan));
428 ast_json_free(json);
429 return;
430 }
431
432 memset(&f, 0, sizeof(f));
434 f.data.ptr = data_msg;
435 f.datalen = ast_msg_data_get_length(data_msg);
436
437 rc = ast_bridge_channel_queue_frame(bridge_chan, &f);
438 ast_free(data_msg);
439 if (rc != 0) {
440 /* Don't complain if we can't send a leave message. The channel is probably gone. */
441 if (strcmp(confbridge_event_type_to_string(confbridge_leave_type()), msg_name) != 0) {
442 ast_log(LOG_ERROR, "Failed to queue %s message to '%s'\n%s\n", msg_name,
443 ast_channel_name(chan), json);
444 }
445 ast_json_free(json);
446 return;
447 }
448
449 ast_debug(3, "Queued %s message to '%s'\n%s\n", msg_name, ast_channel_name(chan), json);
450 ast_json_free(json);
451}
452
454 struct ast_channel *chan, struct stasis_message *msg)
455{
456 struct ast_bridge_blob *obj = stasis_message_data(msg);
457 struct ast_json *extras = obj->blob;
458 struct user_profile u_profile = {{0}};
459 int source_send_events = 0;
460 int source_echo_events = 0;
461 struct ast_json* json_channels = NULL;
462 struct confbridge_user *user;
463 const char *msg_name = confbridge_event_type_to_string(stasis_message_type(msg));
464
465 ast_debug(3, "Distributing %s event to participants\n", msg_name);
466
467 /* This could be a channel level event or a bridge level event */
468 if (chan) {
470 ast_log(LOG_ERROR, "Unable to retrieve user profile for channel '%s'\n",
472 return;
473 }
474 source_send_events = ast_test_flag(&u_profile, USER_OPT_SEND_EVENTS);
475 source_echo_events = ast_test_flag(&u_profile, USER_OPT_ECHO_EVENTS);
476 ast_debug(3, "send_events: %d echo_events: %d for profile %s\n",
477 source_send_events, source_echo_events, u_profile.name);
478 }
479
480 /* Now send a message to the participants with the json string. */
483 struct ast_json *json_object;
484
485 /*
486 * If the msg type is join, we need to capture all targets channel info so we can
487 * send a welcome message to the source channel with all current participants.
488 */
489 if (source_send_events && stasis_message_type(msg) == confbridge_join_type()) {
490 struct ast_channel_snapshot *target_snapshot;
491 struct ast_json *target_json_channel;
492
494 if (!target_snapshot) {
495 ast_log(LOG_ERROR, "Unable to get a channel snapshot for '%s'\n",
496 ast_channel_name(user->chan));
497 continue;
498 }
499
500 target_json_channel = channel_to_json(target_snapshot, extras, NULL);
501 ao2_ref(target_snapshot, -1);
502
503 if (!json_channels) {
504 json_channels = ast_json_array_create();
505 if (!json_channels) {
506 ast_log(LOG_ERROR, "Unable to allocate json array\n");
507 ast_json_unref(target_json_channel);
508 return;
509 }
510 }
511
512 ast_json_array_append(json_channels, target_json_channel);
513 }
514
515 /* Don't send a message to the user that triggered the event. */
516 if (!source_echo_events && user->chan == chan) {
517 ast_debug(3, "Skipping queueing %s message to '%s'. Same channel.\n", msg_name,
518 ast_channel_name(user->chan));
519 continue;
520 }
521
522 /* Don't send a message to users in profiles not sending events. */
523 if (!ast_test_flag(&user->u_profile, USER_OPT_SEND_EVENTS)) {
524 ast_debug(3, "Skipping queueing %s message to '%s'. Not receiving events.\n", msg_name,
525 ast_channel_name(user->chan));
526 continue;
527 }
528
529 json_object = pack_snapshots(obj->bridge, obj->channel, extras, NULL, msg);
530
531 if (!json_object) {
532 ast_log(LOG_ERROR, "Unable to convert %s message to json\n", msg_name);
533 continue;
534 }
535
536 send_message(msg_name, conference->name, json_object, user->chan);
537 ast_json_unref(json_object);
538 }
539 ao2_unlock(conference);
540
541 /*
542 * If this is a join event, send the welcome message to just the joining user
543 * if it's not audio-only or otherwise restricted.
544 */
545 if (source_send_events && json_channels
547 struct ast_json *json_object;
548 struct ast_json *json_bridge;
549 const char *welcome_msg_name = confbridge_event_type_to_string(confbridge_welcome_type());
550
551 json_bridge = bridge_to_json(obj->bridge);
552 json_object = pack_bridge_and_channels(json_bridge, json_channels, msg);
553 if (!json_object) {
554 ast_log(LOG_ERROR, "Unable to convert ConfbridgeWelcome message to json\n");
555 return;
556 }
557 ast_json_string_set(ast_json_object_get(json_object, "type"), welcome_msg_name);
558
559 send_message(welcome_msg_name, conference->name, json_object, chan);
560 ast_json_unref(json_object);
561 }
562}
563
565 struct stasis_message *message,
566 struct ast_str *extra_text)
567{
570 const char *conference_name;
571 RAII_VAR(struct ast_str *, bridge_text, NULL, ast_free);
572 RAII_VAR(struct ast_str *, channel_text, NULL, ast_free);
573
574 ast_assert(blob != NULL);
576
577 bridge_text = ast_manager_build_bridge_state_string(blob->bridge);
578 if (!bridge_text) {
579 return;
580 }
581
582 conference_name = ast_json_string_get(ast_json_object_get(blob->blob, "conference"));
583 ast_assert(conference_name != NULL);
584
585 if (blob->channel) {
586 struct confbridge_conference *conference = conf_find_bridge(conference_name);
587
589 ao2_cleanup(conference);
590 }
591
593 "Conference: %s\r\n"
594 "%s"
595 "%s"
596 "%s",
597 conference_name,
598 ast_str_buffer(bridge_text),
599 channel_text ? ast_str_buffer(channel_text) : "",
600 extra_text ? ast_str_buffer(extra_text) : "");
601}
602
603static int get_bool_header(struct ast_str **extra_text, struct stasis_message *message,
604 const char *json_key, const char *ami_header)
605{
607 const struct ast_json *obj;
608
609 obj = ast_json_object_get(blob->blob, json_key);
610 if (!obj) {
611 return -1;
612 }
613
614 return ast_str_append_event_header(extra_text, ami_header,
616}
617
618static int get_admin_header(struct ast_str **extra_text, struct stasis_message *message)
619{
620 return get_bool_header(extra_text, message, "admin", "Admin");
621}
622
623static int get_muted_header(struct ast_str **extra_text, struct stasis_message *message)
624{
625 return get_bool_header(extra_text, message, "muted", "Muted");
626}
627
628static void confbridge_start_cb(void *data, struct stasis_subscription *sub,
629 struct stasis_message *message)
630{
632}
633
634static void confbridge_end_cb(void *data, struct stasis_subscription *sub,
635 struct stasis_message *message)
636{
638}
639
640static void confbridge_leave_cb(void *data, struct stasis_subscription *sub,
641 struct stasis_message *message)
642{
643 struct ast_str *extra_text = NULL;
644
645 if (!get_admin_header(&extra_text, message)) {
647 }
648 ast_free(extra_text);
649}
650
651static void confbridge_join_cb(void *data, struct stasis_subscription *sub,
652 struct stasis_message *message)
653{
654 struct ast_str *extra_text = NULL;
655
656 if (!get_admin_header(&extra_text, message)
657 && !get_muted_header(&extra_text, message)) {
659 }
660 ast_free(extra_text);
661}
662
663static void confbridge_atxfer_cb(void *data, struct stasis_subscription *sub,
664 struct stasis_message *message)
665{
667
669 return;
670 }
671
672 /*
673 * This callback will get called for ALL attended transfers
674 * so we need to make sure this transfer belongs to
675 * a conference bridge before trying to handle it.
676 */
678 && strcmp(msg->dest.app, "ConfBridge") == 0) {
680 }
681}
682
683static void confbridge_start_record_cb(void *data, struct stasis_subscription *sub,
684 struct stasis_message *message)
685{
687}
688
689static void confbridge_stop_record_cb(void *data, struct stasis_subscription *sub,
690 struct stasis_message *message)
691{
693}
694
695static void confbridge_mute_cb(void *data, struct stasis_subscription *sub,
696 struct stasis_message *message)
697{
698 struct ast_str *extra_text = NULL;
699
700 if (!get_admin_header(&extra_text, message)) {
702 }
703 ast_free(extra_text);
704}
705
706static void confbridge_unmute_cb(void *data, struct stasis_subscription *sub,
707 struct stasis_message *message)
708{
709 struct ast_str *extra_text = NULL;
710
711 if (!get_admin_header(&extra_text, message)) {
713 }
714 ast_free(extra_text);
715}
716
717static void confbridge_talking_cb(void *data, struct stasis_subscription *sub,
718 struct stasis_message *message)
719{
720 RAII_VAR(struct ast_str *, extra_text, NULL, ast_free);
722 const char *talking_status = ast_json_string_get(ast_json_object_get(blob->blob, "talking_status"));
723 if (!talking_status) {
724 return;
725 }
726
727 ast_str_append_event_header(&extra_text, "TalkingStatus", talking_status);
728 if (!extra_text) {
729 return;
730 }
731
732 if (!get_admin_header(&extra_text, message)) {
734 }
735}
736
748
752 }
753
757 }
758}
759
761{
772
775
776 if (!bridge_state_router) {
777 return -1;
778 }
779
783 NULL)) {
785 return -1;
786 }
790 NULL)) {
792 return -1;
793 }
797 NULL)) {
799 return -1;
800 }
804 NULL)) {
806 return -1;
807 }
811 NULL)) {
813 return -1;
814 }
818 NULL)) {
820 return -1;
821 }
825 NULL)) {
827 return -1;
828 }
832 NULL)) {
834 return -1;
835 }
839 NULL)) {
841 return -1;
842 }
846 NULL)) {
848 return -1;
849 }
850
853
856 return -1;
857 }
858
862 NULL)) {
864 return -1;
865 }
869 NULL)) {
871 return -1;
872 }
876 NULL)) {
878 return -1;
879 }
883 NULL)) {
885 return -1;
886 }
890 NULL)) {
892 return -1;
893 }
897 NULL)) {
899 return -1;
900 }
904 NULL)) {
906 return -1;
907 }
911 NULL)) {
913 return -1;
914 }
918 NULL)) {
920 return -1;
921 }
922
923 /* FYI: confbridge_welcome_type is never routed */
924
925 return 0;
926}
void confbridge_handle_atxfer(struct ast_attended_transfer_message *msg)
Create join/leave events for attended transfers.
struct confbridge_conference * conf_find_bridge(const char *conference_name)
Find a confbridge by name.
Asterisk main include file. File version handling, generic pbx functions.
#define ast_free(a)
Definition: astmm.h:180
#define ast_log
Definition: astobj2.c:42
#define ao2_cleanup(obj)
Definition: astobj2.h:1934
#define ao2_unlock(a)
Definition: astobj2.h:729
#define ao2_lock(a)
Definition: astobj2.h:717
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
Bridging API.
@ AST_BRIDGE_TRANSFER_SUCCESS
Definition: bridge.h:1104
int ast_bridge_channel_queue_frame(struct ast_bridge_channel *bridge_channel, struct ast_frame *fr)
Write a frame to the specified bridge_channel.
General Asterisk PBX channel definitions.
const char * ast_channel_name(const struct ast_channel *chan)
const char * ast_channel_uniqueid(const struct ast_channel *chan)
struct ast_bridge_channel * ast_channel_get_bridge_channel(struct ast_channel *chan)
Get a reference to the channel's bridge pointer.
Definition: channel.c:10608
const struct user_profile * conf_find_user_profile(struct ast_channel *chan, const char *user_profile_name, struct user_profile *result)
find a user profile given a user profile's name and store that profile in result structure.
struct stasis_message_type * confbridge_mute_type(void)
get the confbridge mute stasis message type
struct stasis_message_type * confbridge_talking_type(void)
get the confbridge talking stasis message type
struct stasis_message_type * confbridge_stop_record_type(void)
get the confbridge stop_record stasis message type
@ USER_OPT_SEND_EVENTS
Definition: confbridge.h:69
@ USER_OPT_ECHO_EVENTS
Definition: confbridge.h:70
struct stasis_message_type * confbridge_end_type(void)
get the confbridge end stasis message type
struct stasis_message_type * confbridge_start_type(void)
get the confbridge start stasis message type
struct stasis_message_type * confbridge_welcome_type(void)
get the confbridge welcome stasis message type
struct stasis_message_type * confbridge_start_record_type(void)
get the confbridge start_record stasis message type
struct stasis_message_type * confbridge_unmute_type(void)
get the confbridge unmute stasis message type
struct stasis_message_type * confbridge_join_type(void)
get the confbridge join stasis message type
struct stasis_message_type * confbridge_leave_type(void)
get the confbridge leave stasis message type
static void confbridge_unmute_cb(void *data, struct stasis_subscription *sub, struct stasis_message *message)
static int get_admin_header(struct ast_str **extra_text, struct stasis_message *message)
int manager_confbridge_init(void)
register stasis message routers to handle manager events for confbridge messages
static void confbridge_start_cb(void *data, struct stasis_subscription *sub, struct stasis_message *message)
static int get_muted_header(struct ast_str **extra_text, struct stasis_message *message)
const char * confbridge_event_type_to_string(struct stasis_message_type *event_type)
Get the string representation of a confbridge stasis message type.
static void confbridge_atxfer_cb(void *data, struct stasis_subscription *sub, struct stasis_message *message)
void conf_send_event_to_participants(struct confbridge_conference *conference, struct ast_channel *chan, struct stasis_message *msg)
Send events to bridge participants.
static struct stasis_message_router * bridge_state_router
static struct ast_json * bridge_to_json(struct ast_bridge_snapshot *bridge_snapshot)
static struct ast_json * channel_to_json(struct ast_channel_snapshot *channel_snapshot, struct ast_json *conf_blob, struct ast_json *labels_blob)
void manager_confbridge_shutdown(void)
unregister stasis message routers to handle manager events for confbridge messages
static void confbridge_stop_record_cb(void *data, struct stasis_subscription *sub, struct stasis_message *message)
static void confbridge_end_cb(void *data, struct stasis_subscription *sub, struct stasis_message *message)
static void confbridge_leave_cb(void *data, struct stasis_subscription *sub, struct stasis_message *message)
static void confbridge_start_record_cb(void *data, struct stasis_subscription *sub, struct stasis_message *message)
static struct ast_json * pack_bridge_and_channel(struct ast_json *json_bridge, struct ast_json *json_channel, struct stasis_message *msg)
static struct ast_json * pack_snapshots(struct ast_bridge_snapshot *bridge_snapshot, struct ast_channel_snapshot *channel_snapshot, struct ast_json *conf_blob, struct ast_json *labels_blob, struct stasis_message *msg)
static void confbridge_publish_manager_event(struct stasis_message *message, struct ast_str *extra_text)
static void confbridge_talking_cb(void *data, struct stasis_subscription *sub, struct stasis_message *message)
static void confbridge_join_cb(void *data, struct stasis_subscription *sub, struct stasis_message *message)
STASIS_MESSAGE_TYPE_DEFN(confbridge_start_type)
static struct stasis_message_router * channel_state_router
static void send_message(const char *msg_name, char *conf_name, struct ast_json *json_object, struct ast_channel *chan)
static int get_bool_header(struct ast_str **extra_text, struct stasis_message *message, const char *json_key, const char *ami_header)
static struct ast_json * pack_bridge_and_channels(struct ast_json *json_bridge, struct ast_json *json_channels, struct stasis_message *msg)
static void confbridge_mute_cb(void *data, struct stasis_subscription *sub, struct stasis_message *message)
struct stasis_topic * ast_channel_topic_all(void)
A topic which publishes the events for all channels.
struct ast_channel_snapshot * ast_channel_snapshot_get_latest(const char *uniqueid)
Obtain the latest ast_channel_snapshot from the Stasis Message Bus API cache. This is an ao2 object,...
struct ast_msg_data * ast_msg_data_alloc(enum ast_msg_data_source_type source, struct ast_msg_data_attribute attributes[], size_t count)
Allocates an ast_msg_data structure.
size_t ast_msg_data_get_length(struct ast_msg_data *msg)
Get length of the structure.
@ AST_MSG_DATA_ATTR_BODY
Definition: message.h:458
@ AST_MSG_DATA_ATTR_FROM
Definition: message.h:456
@ AST_MSG_DATA_ATTR_CONTENT_TYPE
Definition: message.h:457
@ AST_MSG_DATA_SOURCE_TYPE_IN_DIALOG
Definition: message.h:449
@ AST_FRAME_TEXT_DATA
#define ast_debug(level,...)
Log a DEBUG message.
#define LOG_ERROR
void ast_json_unref(struct ast_json *value)
Decrease refcount on value. If refcount reaches zero, value is freed.
Definition: json.c:73
void ast_json_free(void *p)
Asterisk's custom JSON allocator. Exposed for use by unit tests.
Definition: json.c:52
int ast_json_array_append(struct ast_json *array, struct ast_json *value)
Append to an array.
Definition: json.c:378
struct ast_json * ast_json_pack(char const *format,...)
Helper for creating complex JSON values.
Definition: json.c:612
struct ast_json * ast_json_timeval(const struct timeval tv, const char *zone)
Construct a timeval as JSON.
Definition: json.c:670
struct ast_json * ast_json_array_create(void)
Create a empty JSON array.
Definition: json.c:362
int ast_json_object_del(struct ast_json *object, const char *key)
Delete a field from a JSON object.
Definition: json.c:418
@ AST_JSON_PRETTY
Definition: json.h:795
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
char * ast_json_dump_string_format(struct ast_json *root, enum ast_json_encoding_format format)
Encode a JSON value to a string.
Definition: json.c:484
struct ast_json * ast_json_copy(const struct ast_json *value)
Copy a JSON value, but not its children.
Definition: json.c:637
int ast_json_is_true(const struct ast_json *value)
Check if value is JSON true.
Definition: json.c:263
int ast_json_object_update(struct ast_json *object, struct ast_json *other)
Update object with all of the fields of other.
Definition: json.c:426
int ast_json_string_set(struct ast_json *string, const char *value)
Change the value of a JSON string.
Definition: json.c:288
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:491
The AMI - Asterisk Manager Interface - is a TCP protocol created to manage Asterisk with third-party ...
#define manager_event(category, event, contents,...)
External routines may send asterisk manager events this way.
Definition: manager.h:254
struct ast_str * ast_manager_build_channel_state_string(const struct ast_channel_snapshot *snapshot)
Generate the AMI message body from a channel snapshot.
int ast_str_append_event_header(struct ast_str **fields_string, const char *header, const char *value)
append an event header to an ast string
Definition: manager.c:10215
#define EVENT_FLAG_CALL
Definition: manager.h:76
struct ast_str * ast_manager_build_bridge_state_string(const struct ast_bridge_snapshot *snapshot)
Generate the AMI message body from a bridge snapshot.
Out-of-call text message support.
static char user[512]
struct stasis_forward * sub
Definition: res_corosync.c:240
#define NULL
Definition: resample.c:96
Stasis Message Bus API. See Stasis Message Bus API for detailed documentation.
struct stasis_message_type * stasis_message_type(const struct stasis_message *msg)
Get the message type for a stasis_message.
#define STASIS_MESSAGE_TYPE_CLEANUP(name)
Boiler-plate messaging macro for cleaning up message types.
Definition: stasis.h:1515
#define STASIS_MESSAGE_TYPE_INIT(name)
Boiler-plate messaging macro for initializing message types.
Definition: stasis.h:1493
void * stasis_message_data(const struct stasis_message *msg)
Get the data contained in a message.
const struct timeval * stasis_message_timestamp(const struct stasis_message *msg)
Get the time when a message was created.
struct ast_json * ast_bridge_snapshot_to_json(const struct ast_bridge_snapshot *snapshot, const struct stasis_message_sanitizer *sanitize)
Build a JSON object from a ast_bridge_snapshot.
struct stasis_message_type * ast_attended_transfer_type(void)
Message type for ast_attended_transfer_message.
struct stasis_topic * ast_bridge_topic_all(void)
A topic which publishes the events for all bridges.
@ AST_ATTENDED_TRANSFER_DEST_APP
struct ast_json * ast_channel_snapshot_to_json(const struct ast_channel_snapshot *snapshot, const struct stasis_message_sanitizer *sanitize)
Build a JSON object from a ast_channel_snapshot.
#define stasis_message_router_create(topic)
Create a new message router object.
void stasis_message_router_unsubscribe(struct stasis_message_router *router)
Unsubscribe the router from the upstream topic.
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.
Media Stream API.
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:761
#define AST_YESNO(x)
return Yes or No depending on the argument.
Definition: strings.h:143
Message representing attended transfer.
enum ast_attended_transfer_dest_type dest_type
union ast_attended_transfer_message::@286 dest
enum ast_transfer_result result
Blob of data associated with a bridge.
struct ast_bridge_snapshot * bridge
struct ast_channel_snapshot * channel
struct ast_json * blob
Structure that contains information regarding a channel in a bridge.
Structure that contains a snapshot of information about a bridge.
Definition: bridge.h:318
Structure representing a snapshot of channel state.
Main Channel structure associated with a channel.
Data structure associated with a single frame of data.
union ast_frame::@228 data
enum ast_frame_type frametype
Abstract JSON element (object, array, string, int, ...).
enum ast_msg_data_attribute_type type
Definition: message.h:463
Structure used to transport a message through the frame core.
Support for dynamic strings.
Definition: strings.h:623
The structure that represents a conference bridge.
Definition: confbridge.h:246
char name[MAX_CONF_NAME]
Definition: confbridge.h:247
struct confbridge_conference::@94 active_list
The structure that represents a conference bridge user.
Definition: confbridge.h:273
struct confbridge_conference * conference
Definition: confbridge.h:274
struct confbridge_user::@98 list
struct ast_channel * chan
Definition: confbridge.h:279
struct user_profile u_profile
Definition: confbridge.h:276
Definition: astman.c:222
char name[MAX_PROFILE_NAME]
Definition: confbridge.h:155
structure to hold users read from users.conf
#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