Asterisk - The Open Source Telephony Project  18.5.0
manager_bridges.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  * Kinsey Moore <[email protected]>
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 (bridge event handling)
22  *
23  * \author Kinsey Moore <[email protected]>
24  */
25 
26 #include "asterisk.h"
27 
30 #include "asterisk/manager.h"
32 
33 /*! \brief Message router for cached bridge state snapshot updates */
35 
36 /*** DOCUMENTATION
37  <managerEvent language="en_US" name="BridgeCreate">
38  <managerEventInstance class="EVENT_FLAG_CALL">
39  <synopsis>Raised when a bridge is created.</synopsis>
40  <syntax>
41  <bridge_snapshot/>
42  </syntax>
43  <see-also>
44  <ref type="managerEvent">BridgeDestroy</ref>
45  <ref type="managerEvent">BridgeEnter</ref>
46  <ref type="managerEvent">BridgeLeave</ref>
47  </see-also>
48  </managerEventInstance>
49  </managerEvent>
50  <managerEvent language="en_US" name="BridgeDestroy">
51  <managerEventInstance class="EVENT_FLAG_CALL">
52  <synopsis>Raised when a bridge is destroyed.</synopsis>
53  <syntax>
54  <bridge_snapshot/>
55  </syntax>
56  <see-also>
57  <ref type="managerEvent">BridgeCreate</ref>
58  <ref type="managerEvent">BridgeEnter</ref>
59  <ref type="managerEvent">BridgeLeave</ref>
60  </see-also>
61  </managerEventInstance>
62  </managerEvent>
63  <managerEvent language="en_US" name="BridgeEnter">
64  <managerEventInstance class="EVENT_FLAG_CALL">
65  <synopsis>Raised when a channel enters a bridge.</synopsis>
66  <syntax>
67  <bridge_snapshot/>
68  <channel_snapshot/>
69  <parameter name="SwapUniqueid">
70  <para>The uniqueid of the channel being swapped out of the bridge</para>
71  </parameter>
72  </syntax>
73  <see-also>
74  <ref type="managerEvent">BridgeCreate</ref>
75  <ref type="managerEvent">BridgeDestroy</ref>
76  <ref type="managerEvent">BridgeLeave</ref>
77  </see-also>
78  </managerEventInstance>
79  </managerEvent>
80  <managerEvent language="en_US" name="BridgeLeave">
81  <managerEventInstance class="EVENT_FLAG_CALL">
82  <synopsis>Raised when a channel leaves a bridge.</synopsis>
83  <syntax>
84  <bridge_snapshot/>
85  <channel_snapshot/>
86  </syntax>
87  <see-also>
88  <ref type="managerEvent">BridgeCreate</ref>
89  <ref type="managerEvent">BridgeDestroy</ref>
90  <ref type="managerEvent">BridgeEnter</ref>
91  </see-also>
92  </managerEventInstance>
93  </managerEvent>
94  <managerEvent language="en_US" name="BridgeVideoSourceUpdate">
95  <managerEventInstance class="EVENT_FLAG_CALL">
96  <synopsis>Raised when the channel that is the source of video in a bridge changes.</synopsis>
97  <syntax>
98  <bridge_snapshot/>
99  <parameter name="BridgePreviousVideoSource">
100  <para>The unique ID of the channel that was the video source.</para>
101  </parameter>
102  </syntax>
103  <see-also>
104  <ref type="managerEvent">BridgeCreate</ref>
105  <ref type="managerEvent">BridgeDestroy</ref>
106  </see-also>
107  </managerEventInstance>
108  </managerEvent>
109  <manager name="BridgeList" language="en_US">
110  <synopsis>
111  Get a list of bridges in the system.
112  </synopsis>
113  <syntax>
114  <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
115  <parameter name="BridgeType">
116  <para>Optional type for filtering the resulting list of bridges.</para>
117  </parameter>
118  </syntax>
119  <description>
120  <para>Returns a list of bridges, optionally filtering on a bridge type.</para>
121  </description>
122  <see-also>
123  <ref type="manager">Bridge</ref>
124  <ref type="manager">BridgeDestroy</ref>
125  <ref type="manager">BridgeInfo</ref>
126  <ref type="manager">BridgeKick</ref>
127  </see-also>
128  </manager>
129  <manager name="BridgeInfo" language="en_US">
130  <synopsis>
131  Get information about a bridge.
132  </synopsis>
133  <syntax>
134  <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
135  <parameter name="BridgeUniqueid" required="true">
136  <para>The unique ID of the bridge about which to retrieve information.</para>
137  </parameter>
138  </syntax>
139  <description>
140  <para>Returns detailed information about a bridge and the channels in it.</para>
141  </description>
142  <see-also>
143  <ref type="manager">Bridge</ref>
144  <ref type="manager">BridgeDestroy</ref>
145  <ref type="manager">BridgeKick</ref>
146  <ref type="manager">BridgeList</ref>
147  </see-also>
148  <responses>
149  <list-elements>
150  <managerEvent language="en_US" name="BridgeInfoChannel">
151  <managerEventInstance class="EVENT_FLAG_COMMAND">
152  <synopsis>Information about a channel in a bridge.</synopsis>
153  <syntax>
154  <channel_snapshot/>
155  </syntax>
156  </managerEventInstance>
157  </managerEvent>
158  </list-elements>
159  <managerEvent language="en_US" name="BridgeInfoComplete">
160  <managerEventInstance class="EVENT_FLAG_COMMAND">
161  <synopsis>Information about a bridge.</synopsis>
162  <syntax>
163  <bridge_snapshot/>
164  </syntax>
165  </managerEventInstance>
166  </managerEvent>
167  </responses>
168  </manager>
169  <manager name="BridgeDestroy" language="en_US">
170  <synopsis>
171  Destroy a bridge.
172  </synopsis>
173  <syntax>
174  <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
175  <parameter name="BridgeUniqueid" required="true">
176  <para>The unique ID of the bridge to destroy.</para>
177  </parameter>
178  </syntax>
179  <description>
180  <para>Deletes the bridge, causing channels to continue or hang up.</para>
181  </description>
182  <see-also>
183  <ref type="manager">Bridge</ref>
184  <ref type="manager">BridgeInfo</ref>
185  <ref type="manager">BridgeKick</ref>
186  <ref type="manager">BridgeList</ref>
187  <ref type="managerEvent">BridgeDestroy</ref>
188  </see-also>
189  </manager>
190  <manager name="BridgeKick" language="en_US">
191  <synopsis>
192  Kick a channel from a bridge.
193  </synopsis>
194  <syntax>
195  <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
196  <parameter name="BridgeUniqueid" required="false">
197  <para>The unique ID of the bridge containing the channel to
198  destroy. This parameter can be omitted, or supplied to insure
199  that the channel is not removed from the wrong bridge.</para>
200  </parameter>
201  <parameter name="Channel" required="true">
202  <para>The channel to kick out of a bridge.</para>
203  </parameter>
204  </syntax>
205  <description>
206  <para>The channel is removed from the bridge.</para>
207  </description>
208  <see-also>
209  <ref type="manager">Bridge</ref>
210  <ref type="manager">BridgeDestroy</ref>
211  <ref type="manager">BridgeInfo</ref>
212  <ref type="manager">BridgeList</ref>
213  <ref type="managerEvent">BridgeLeave</ref>
214  </see-also>
215  </manager>
216  ***/
217 
218 /*! \brief The \ref stasis subscription returned by the forwarding of the channel topic
219  * to the manager topic
220  */
222 
224  const struct ast_bridge_snapshot *snapshot,
225  const char *prefix)
226 {
227  struct ast_str *out = ast_str_create(128);
228  int res;
229 
230  if (!out) {
231  return NULL;
232  }
233 
234  res = ast_str_set(&out, 0,
235  "%sBridgeUniqueid: %s\r\n"
236  "%sBridgeType: %s\r\n"
237  "%sBridgeTechnology: %s\r\n"
238  "%sBridgeCreator: %s\r\n"
239  "%sBridgeName: %s\r\n"
240  "%sBridgeNumChannels: %u\r\n"
241  "%sBridgeVideoSourceMode: %s\r\n",
242  prefix, snapshot->uniqueid,
243  prefix, snapshot->subclass,
244  prefix, snapshot->technology,
245  prefix, ast_strlen_zero(snapshot->creator) ? "<unknown>": snapshot->creator,
246  prefix, ast_strlen_zero(snapshot->name) ? "<unknown>": snapshot->name,
247  prefix, snapshot->num_channels,
248  prefix, ast_bridge_video_mode_to_string(snapshot->video_mode));
249  if (!res) {
250  ast_free(out);
251  return NULL;
252  }
253 
254  if (snapshot->video_mode != AST_BRIDGE_VIDEO_MODE_NONE
255  && !ast_strlen_zero(snapshot->video_source_id)) {
256  res = ast_str_append(&out, 0, "%sBridgeVideoSource: %s\r\n",
257  prefix, snapshot->video_source_id);
258  if (!res) {
259  ast_free(out);
260  return NULL;
261  }
262  }
263 
264  return out;
265 }
266 
268  const struct ast_bridge_snapshot *snapshot)
269 {
271 }
272 
273 /*! \brief Typedef for callbacks that get called on channel snapshot updates */
274 typedef struct ast_manager_event_blob *(*bridge_snapshot_monitor)(
275  struct ast_bridge_snapshot *old_snapshot,
276  struct ast_bridge_snapshot *new_snapshot);
277 
278 /*! \brief Handle bridge creation */
280  struct ast_bridge_snapshot *old_snapshot,
281  struct ast_bridge_snapshot *new_snapshot)
282 {
283  if (!new_snapshot || old_snapshot) {
284  return NULL;
285  }
286 
288  EVENT_FLAG_CALL, "BridgeCreate", NO_EXTRA_FIELDS);
289 }
290 
291 /* \brief Handle video source updates */
293  struct ast_bridge_snapshot *old_snapshot,
294  struct ast_bridge_snapshot *new_snapshot)
295 {
296  if (!new_snapshot || !old_snapshot) {
297  return NULL;
298  }
299 
300  if (!strcmp(old_snapshot->video_source_id, new_snapshot->video_source_id)) {
301  return NULL;
302  }
303 
305  EVENT_FLAG_CALL, "BridgeVideoSourceUpdate",
306  "BridgePreviousVideoSource: %s\r\n",
307  old_snapshot->video_source_id);
308 }
309 
310 /*! \brief Handle bridge destruction */
312  struct ast_bridge_snapshot *old_snapshot,
313  struct ast_bridge_snapshot *new_snapshot)
314 {
315  if (new_snapshot || !old_snapshot) {
316  return NULL;
317  }
318 
320  EVENT_FLAG_CALL, "BridgeDestroy", NO_EXTRA_FIELDS);
321 }
322 
327 };
328 
329 static void bridge_snapshot_update(void *data, struct stasis_subscription *sub,
330  struct stasis_message *message)
331 {
332  RAII_VAR(struct ast_str *, bridge_event_string, NULL, ast_free);
334  size_t i;
335 
336  update = stasis_message_data(message);
337 
338  for (i = 0; i < ARRAY_LEN(bridge_monitors); ++i) {
340 
341  event = bridge_monitors[i](update->old_snapshot, update->new_snapshot);
342  if (!event) {
343  continue;
344  }
345 
346  /* If we haven't already, build the channel event string */
347  if (!bridge_event_string) {
348  bridge_event_string =
350  update->new_snapshot ? update->new_snapshot : update->old_snapshot);
351  if (!bridge_event_string) {
352  return;
353  }
354  }
355 
356  manager_event(event->event_flags, event->manager_event, "%s%s",
357  ast_str_buffer(bridge_event_string),
358  event->extra_fields);
359  }
360 }
361 
362 static void bridge_merge_cb(void *data, struct stasis_subscription *sub,
363  struct stasis_message *message)
364 {
365  struct ast_bridge_merge_message *merge_msg = stasis_message_data(message);
366  RAII_VAR(struct ast_str *, to_text, NULL, ast_free);
367  RAII_VAR(struct ast_str *, from_text, NULL, ast_free);
368 
369  ast_assert(merge_msg->to != NULL);
370  ast_assert(merge_msg->from != NULL);
371 
372  to_text = ast_manager_build_bridge_state_string_prefix(merge_msg->to, "To");
373  from_text = ast_manager_build_bridge_state_string_prefix(merge_msg->from, "From");
374  if (!to_text || !from_text) {
375  return;
376  }
377 
378  /*** DOCUMENTATION
379  <managerEventInstance>
380  <synopsis>Raised when two bridges are merged.</synopsis>
381  <syntax>
382  <bridge_snapshot prefix="To"/>
383  <bridge_snapshot prefix="From"/>
384  </syntax>
385  </managerEventInstance>
386  ***/
387  manager_event(EVENT_FLAG_CALL, "BridgeMerge",
388  "%s"
389  "%s",
390  ast_str_buffer(to_text),
391  ast_str_buffer(from_text));
392 }
393 
394 static void channel_enter_cb(void *data, struct stasis_subscription *sub,
395  struct stasis_message *message)
396 {
397  static const char *swap_name = "SwapUniqueid: ";
398  struct ast_bridge_blob *blob = stasis_message_data(message);
399  RAII_VAR(struct ast_str *, bridge_text, NULL, ast_free);
400  RAII_VAR(struct ast_str *, channel_text, NULL, ast_free);
401  const char *swap_id;
402 
403  bridge_text = ast_manager_build_bridge_state_string(blob->bridge);
404  channel_text = ast_manager_build_channel_state_string(blob->channel);
405  if (!bridge_text || !channel_text) {
406  return;
407  }
408 
409  swap_id = ast_json_string_get(ast_json_object_get(blob->blob, "swap"));
410 
411  manager_event(EVENT_FLAG_CALL, "BridgeEnter",
412  "%s"
413  "%s"
414  "%s%s%s",
415  ast_str_buffer(bridge_text),
416  ast_str_buffer(channel_text),
417  swap_id ? swap_name : "",
418  S_OR(swap_id, ""),
419  swap_id ? "\r\n" : "");
420 }
421 
422 static void channel_leave_cb(void *data, struct stasis_subscription *sub,
423  struct stasis_message *message)
424 {
425  struct ast_bridge_blob *blob = stasis_message_data(message);
426  RAII_VAR(struct ast_str *, bridge_text, NULL, ast_free);
427  RAII_VAR(struct ast_str *, channel_text, NULL, ast_free);
428 
429  bridge_text = ast_manager_build_bridge_state_string(blob->bridge);
430  channel_text = ast_manager_build_channel_state_string(blob->channel);
431  if (!bridge_text || !channel_text) {
432  return;
433  }
434 
435  manager_event(EVENT_FLAG_CALL, "BridgeLeave",
436  "%s"
437  "%s",
438  ast_str_buffer(bridge_text),
439  ast_str_buffer(channel_text));
440 }
441 
443  struct ast_str *id_text;
444  const char *type_filter;
445  int count;
446 };
447 
448 static int send_bridge_list_item_cb(void *obj, void *arg, void *data, int flags)
449 {
450  struct ast_bridge *bridge = obj;
451  RAII_VAR(struct ast_bridge_snapshot *, snapshot, ast_bridge_get_snapshot(bridge), ao2_cleanup);
452  struct mansession *s = arg;
453  struct bridge_list_data *list_data = data;
454  struct ast_str * bridge_info;
455 
456  if (!snapshot) {
457  return 0;
458  }
459 
460  if (!ast_strlen_zero(list_data->type_filter)
461  && strcmp(list_data->type_filter, snapshot->technology)) {
462  return 0;
463  }
464 
465  bridge_info = ast_manager_build_bridge_state_string(snapshot);
466  if (!bridge_info) {
467  return 0;
468  }
469 
470  astman_append(s,
471  "Event: BridgeListItem\r\n"
472  "%s"
473  "%s"
474  "\r\n",
475  ast_str_buffer(list_data->id_text),
476  ast_str_buffer(bridge_info));
477  ++list_data->count;
478 
479  ast_free(bridge_info);
480 
481  return 0;
482 }
483 
484 static int manager_bridges_list(struct mansession *s, const struct message *m)
485 {
486  const char *id = astman_get_header(m, "ActionID");
487  const char *type_filter = astman_get_header(m, "BridgeType");
488  struct ao2_container *bridges;
489  struct bridge_list_data list_data = { 0 };
490 
491  bridges = ast_bridges();
492  if (!bridges) {
493  astman_send_error(s, m, "Internal error");
494  return -1;
495  }
496 
497  list_data.id_text = ast_str_create(128);
498  if (!list_data.id_text) {
499  ao2_ref(bridges, -1);
500  astman_send_error(s, m, "Internal error");
501  return -1;
502  }
503 
504  if (!ast_strlen_zero(id)) {
505  ast_str_set(&list_data.id_text, 0, "ActionID: %s\r\n", id);
506  }
507  list_data.type_filter = type_filter;
508 
509  astman_send_listack(s, m, "Bridge listing will follow", "start");
510 
511  ao2_callback_data(bridges, OBJ_NODATA, send_bridge_list_item_cb, s, &list_data);
512 
513  astman_send_list_complete_start(s, m, "BridgeListComplete", list_data.count);
515 
516  ast_free(list_data.id_text);
517  ao2_ref(bridges, -1);
518 
519  return 0;
520 }
521 
522 static int send_bridge_info_item_cb(void *obj, void *arg, void *data, int flags)
523 {
524  char *uniqueid = obj;
525  struct mansession *s = arg;
526  struct bridge_list_data *list_data = data;
527  RAII_VAR(struct ast_channel_snapshot *, snapshot, NULL, ao2_cleanup);
528  RAII_VAR(struct ast_str *, channel_text, NULL, ast_free);
529 
530  snapshot = ast_channel_snapshot_get_latest(uniqueid);
531  if (!snapshot) {
532  return 0;
533  }
534 
535  if (snapshot->base->tech_properties & AST_CHAN_TP_INTERNAL) {
536  return 0;
537  }
538 
539  channel_text = ast_manager_build_channel_state_string(snapshot);
540  if (!channel_text) {
541  return 0;
542  }
543 
544  astman_append(s,
545  "Event: BridgeInfoChannel\r\n"
546  "%s"
547  "%s"
548  "\r\n",
549  ast_str_buffer(list_data->id_text),
550  ast_str_buffer(channel_text));
551  ++list_data->count;
552  return 0;
553 }
554 
555 static int manager_bridge_info(struct mansession *s, const struct message *m)
556 {
557  const char *id = astman_get_header(m, "ActionID");
558  const char *bridge_uniqueid = astman_get_header(m, "BridgeUniqueid");
559  RAII_VAR(struct ast_str *, bridge_info, NULL, ast_free);
560  RAII_VAR(struct ast_bridge_snapshot *, snapshot, NULL, ao2_cleanup);
561  struct bridge_list_data list_data = { 0 };
562 
563  if (ast_strlen_zero(bridge_uniqueid)) {
564  astman_send_error(s, m, "BridgeUniqueid must be provided");
565  return 0;
566  }
567 
568  snapshot = ast_bridge_get_snapshot_by_uniqueid(bridge_uniqueid);
569  if (!snapshot) {
570  astman_send_error(s, m, "Specified BridgeUniqueid not found");
571  return 0;
572  }
573 
574  bridge_info = ast_manager_build_bridge_state_string(snapshot);
575  if (!bridge_info) {
576  astman_send_error(s, m, "Internal error");
577  return -1;
578  }
579 
580  list_data.id_text = ast_str_create(128);
581  if (!list_data.id_text) {
582  astman_send_error(s, m, "Internal error");
583  return -1;
584  }
585 
586  if (!ast_strlen_zero(id)) {
587  ast_str_set(&list_data.id_text, 0, "ActionID: %s\r\n", id);
588  }
589 
590  astman_send_listack(s, m, "Bridge channel listing will follow", "start");
591 
592  ao2_callback_data(snapshot->channels, OBJ_NODATA, send_bridge_info_item_cb, s, &list_data);
593 
594  astman_send_list_complete_start(s, m, "BridgeInfoComplete", list_data.count);
595  if (!ast_strlen_zero(ast_str_buffer(bridge_info))) {
596  astman_append(s, "%s", ast_str_buffer(bridge_info));
597  }
599  ast_free(list_data.id_text);
600 
601  return 0;
602 }
603 
604 static int manager_bridge_destroy(struct mansession *s, const struct message *m)
605 {
606  const char *bridge_uniqueid = astman_get_header(m, "BridgeUniqueid");
607  struct ast_bridge *bridge;
608 
609  if (ast_strlen_zero(bridge_uniqueid)) {
610  astman_send_error(s, m, "BridgeUniqueid must be provided");
611  return 0;
612  }
613 
614  bridge = ast_bridge_find_by_id(bridge_uniqueid);
615  if (!bridge) {
616  astman_send_error(s, m, "Specified BridgeUniqueid not found");
617  return 0;
618  }
619  ast_bridge_destroy(bridge, 0);
620 
621  astman_send_ack(s, m, "Bridge has been destroyed");
622 
623  return 0;
624 }
625 
626 static int manager_bridge_kick(struct mansession *s, const struct message *m)
627 {
628  const char *bridge_uniqueid = astman_get_header(m, "BridgeUniqueid");
629  const char *channel_name = astman_get_header(m, "Channel");
630  RAII_VAR(struct ast_bridge *, bridge, NULL, ao2_cleanup);
632 
633  if (ast_strlen_zero(channel_name)) {
634  astman_send_error(s, m, "Channel must be provided");
635  return 0;
636  }
637 
638  channel = ast_channel_get_by_name(channel_name);
639  if (!channel) {
640  astman_send_error(s, m, "Channel does not exist");
641  return 0;
642  }
643 
644  if (ast_strlen_zero(bridge_uniqueid)) {
645  /* get the bridge from the channel */
649  if (!bridge) {
650  astman_send_error(s, m, "Channel is not in a bridge");
651  return 0;
652  }
653  } else {
654  bridge = ast_bridge_find_by_id(bridge_uniqueid);
655  if (!bridge || ast_test_flag(&bridge->feature_flags, AST_BRIDGE_FLAG_INVISIBLE)) {
656  astman_send_error(s, m, "Bridge not found");
657  return 0;
658  }
659  }
660 
661  if (ast_bridge_kick(bridge, channel)) {
662  astman_send_error(s, m, "Channel kick from bridge failed");
663  return 0;
664  }
665 
666  astman_send_ack(s, m, "Channel has been kicked");
667  return 0;
668 }
669 
670 static void manager_bridging_cleanup(void)
671 {
672  stasis_forward_cancel(topic_forwarder);
673  topic_forwarder = NULL;
674 
675  ast_manager_unregister("BridgeList");
676  ast_manager_unregister("BridgeInfo");
677  ast_manager_unregister("BridgeDestroy");
678  ast_manager_unregister("BridgeKick");
679 }
680 
682 {
683  int ret = 0;
684  struct stasis_topic *manager_topic;
685  struct stasis_topic *bridge_topic;
686 
687  if (bridge_state_router) {
688  /* Already initialized */
689  return 0;
690  }
691 
693 
694  manager_topic = ast_manager_get_topic();
695  if (!manager_topic) {
696  return -1;
697  }
698 
699  bridge_topic = ast_bridge_topic_all();
700  if (!bridge_topic) {
701  return -1;
702  }
703 
704  topic_forwarder = stasis_forward_all(bridge_topic, manager_topic);
705  if (!topic_forwarder) {
706  return -1;
707  }
708 
709  bridge_state_router = ast_manager_get_message_router();
710  if (!bridge_state_router) {
711  return -1;
712  }
713 
714  ret |= stasis_message_router_add(bridge_state_router,
716 
717  ret |= stasis_message_router_add(bridge_state_router,
719 
720  ret |= stasis_message_router_add(bridge_state_router,
722 
723  ret |= stasis_message_router_add(bridge_state_router,
725 
726  ret |= ast_manager_register_xml_core("BridgeList", 0, manager_bridges_list);
727  ret |= ast_manager_register_xml_core("BridgeInfo", 0, manager_bridge_info);
728  ret |= ast_manager_register_xml_core("BridgeDestroy", 0, manager_bridge_destroy);
729  ret |= ast_manager_register_xml_core("BridgeKick", 0, manager_bridge_kick);
730 
731  /* If somehow we failed to add any routes, just shut down the whole
732  * thing and fail it.
733  */
734  if (ret) {
736  return -1;
737  }
738 
739  return 0;
740 }
struct stasis_message_type * ast_bridge_snapshot_type(void)
Message type for ast_bridge_snapshot.
Struct containing info for an AMI event to send out.
Definition: manager.h:491
#define ast_channel_lock(chan)
Definition: channel.h:2945
Main Channel structure associated with a channel.
struct ao2_container * ast_bridges(void)
Returns the global bridges container.
Definition: bridge.c:174
void astman_append(struct mansession *s, const char *fmt,...)
Definition: manager.c:3080
Asterisk main include file. File version handling, generic pbx functions.
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
const char * type_filter
struct stasis_message_type * ast_channel_entered_bridge_type(void)
Message type for channel enter bridge blob messages.
struct ast_channel_snapshot * channel
struct ast_bridge * ast_bridge_find_by_id(const char *bridge_id)
Find bridge by id.
Definition: bridge.c:5070
#define ast_test_flag(p, flag)
Definition: utils.h:63
static void channel_enter_cb(void *data, struct stasis_subscription *sub, struct stasis_message *message)
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
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.
struct stasis_message_type * ast_channel_left_bridge_type(void)
Message type for channel leave bridge blob messages.
void astman_send_list_complete_start(struct mansession *s, const struct message *m, const char *event_name, int count)
Start the list complete event.
Definition: manager.c:3237
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:714
Structure that contains a snapshot of information about a bridge.
Definition: bridge.h:322
const ast_string_field video_source_id
Definition: bridge.h:336
int manager_bridging_init(void)
Initialize support for AMI channel events.
Structure representing a snapshot of channel state.
struct ast_json * blob
#define EVENT_FLAG_CALL
Definition: manager.h:72
int ast_bridge_destroy(struct ast_bridge *bridge, int cause)
Destroy a bridge.
Definition: bridge.c:970
Definition: astman.c:222
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:1091
#define ast_assert(a)
Definition: utils.h:695
void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
Send ack in manager transaction.
Definition: manager.c:3191
Definition: muted.c:95
#define NULL
Definition: resample.c:96
static struct stasis_topic * manager_topic
A stasis_topic that all topics AMI cares about will be forwarded to.
Definition: manager.c:1490
#define ast_manager_register_xml_core(action, authority, func)
Register a manager callback using XML documentation to describe the manager.
Definition: manager.h:197
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:9727
const ast_string_field creator
Definition: bridge.h:336
const char * astman_get_header(const struct message *m, char *var)
Get header from mananger transaction.
Definition: manager.c:2820
#define ast_strlen_zero(foo)
Definition: strings.h:52
static int manager_bridge_destroy(struct mansession *s, const struct message *m)
static struct ast_manager_event_blob * bridge_create(struct ast_bridge_snapshot *old_snapshot, struct ast_bridge_snapshot *new_snapshot)
Handle bridge creation.
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:1065
static int manager_bridge_info(struct mansession *s, const struct message *m)
struct ast_bridge_snapshot * bridge
struct stasis_message_type * ast_bridge_merge_message_type(void)
Message type for ast_bridge_merge_message.
struct ast_bridge * ast_channel_get_bridge(const struct ast_channel *chan)
Get the bridge associated with a channel.
Definition: channel.c:10735
const ast_string_field technology
Definition: bridge.h:336
static void bridge_snapshot_update(void *data, struct stasis_subscription *sub, struct stasis_message *message)
struct ast_bridge_snapshot * ast_bridge_get_snapshot(struct ast_bridge *bridge)
Returns the current snapshot for the bridge.
int ast_register_cleanup(void(*func)(void))
Register a function to be executed before Asterisk gracefully exits.
Definition: clicompat.c:19
void astman_send_list_complete_end(struct mansession *s)
End the list complete event.
Definition: manager.c:3245
#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:911
static void manager_bridging_cleanup(void)
const char * ast_bridge_video_mode_to_string(enum ast_bridge_video_mode_type video_mode)
Converts an enum representation of a bridge video mode to string.
Definition: bridge.c:4018
struct ast_str * ast_manager_build_bridge_state_string(const struct ast_bridge_snapshot *snapshot)
Generate the AMI message body from a bridge snapshot.
#define ao2_ref(o, delta)
Definition: astobj2.h:464
In case you didn&#39;t read that giant block of text above the mansession_session struct, the struct mansession is named this solely to keep the API the same in Asterisk. This structure really represents data that is different from Manager action to Manager action. The mansession_session pointer contained within points to session-specific data.
Definition: manager.c:1625
#define NO_EXTRA_FIELDS
Definition: manager.h:522
static int send_bridge_list_item_cb(void *obj, void *arg, void *data, int flags)
const char * ast_json_string_get(const struct ast_json *string)
Get the value of a JSON string.
Definition: json.c:273
struct ast_str * id_text
struct ast_bridge_snapshot * old_snapshot
Blob of data associated with a bridge.
Channels with this particular technology are an implementation detail of Asterisk and should generall...
Definition: channel.h:972
struct ast_str * ast_manager_build_channel_state_string(const struct ast_channel_snapshot *snapshot)
Generate the AMI message body from a channel snapshot.
bridge_snapshot_monitor bridge_monitors[]
static int manager_bridge_kick(struct mansession *s, const struct message *m)
int ast_manager_unregister(const char *action)
Unregister a registered manager command.
Definition: manager.c:7258
The AMI - Asterisk Manager Interface - is a TCP protocol created to manage Asterisk with third-party ...
Structure that contains information about a bridge.
Definition: bridge.h:357
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:584
const ast_string_field name
Definition: bridge.h:336
void * stasis_message_data(const struct stasis_message *msg)
Get the data contained in a message.
enum ast_bridge_video_mode_type video_mode
Definition: bridge.h:349
#define ao2_callback_data(container, flags, cb_fn, arg, data)
Definition: astobj2.h:1743
struct stasis_message_router * ast_manager_get_message_router(void)
Get the stasis_message_router for AMI.
Definition: manager.c:1725
static void bridge_merge_cb(void *data, struct stasis_subscription *sub, struct stasis_message *message)
static int send_bridge_info_item_cb(void *obj, void *arg, void *data, int flags)
static struct ao2_container * bridges
Definition: bridge.c:123
#define ast_channel_unlock(chan)
Definition: channel.h:2946
#define ast_free(a)
Definition: astmm.h:182
int ast_bridge_kick(struct ast_bridge *bridge, struct ast_channel *chan)
Kick a channel from a bridge.
Definition: bridge.c:2025
struct stasis_forward * stasis_forward_cancel(struct stasis_forward *forward)
Definition: stasis.c:1548
struct ast_manager_event_blob *(* bridge_snapshot_monitor)(struct ast_bridge_snapshot *old_snapshot, struct ast_bridge_snapshot *new_snapshot)
Typedef for callbacks that get called on channel snapshot updates.
const ast_string_field uniqueid
Definition: bridge.h:336
struct ast_bridge_snapshot * new_snapshot
unsigned int num_channels
Definition: bridge.h:345
struct stasis_topic * ast_manager_get_topic(void)
Get the Stasis Message Bus API topic for AMI.
Definition: manager.c:1720
struct ast_bridge_snapshot * from
struct stasis_topic * ast_bridge_topic_all(void)
A topic which publishes the events for all bridges.
Message representing the merge of two bridges.
static struct ast_manager_event_blob * bridge_video_update(struct ast_bridge_snapshot *old_snapshot, struct ast_bridge_snapshot *new_snapshot)
static int manager_bridges_list(struct mansession *s, const struct message *m)
FILE * out
Definition: utils/frame.c:33
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...
static struct ast_manager_event_blob * bridge_destroy(struct ast_bridge_snapshot *old_snapshot, struct ast_bridge_snapshot *new_snapshot)
Handle bridge destruction.
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
struct ast_json * ast_json_object_get(struct ast_json *object, const char *key)
Get a field from a JSON object.
Definition: json.c:397
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:79
static struct stasis_message_router * bridge_state_router
Message router for cached bridge state snapshot updates.
struct stasis_forward * sub
Definition: res_corosync.c:240
Forwarding information.
Definition: stasis.c:1531
struct ast_str * ast_manager_build_bridge_state_string_prefix(const struct ast_bridge_snapshot *snapshot, const char *prefix)
Generate the AMI message body from a bridge snapshot.
static struct stasis_forward * topic_forwarder
The Stasis Message Bus API subscription returned by the forwarding of the channel topic to the manage...
Generic container type.
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:1578
#define manager_event(category, event, contents,...)
External routines may send asterisk manager events this way.
Definition: manager.h:248
struct ast_channel * ast_channel_get_by_name(const char *name)
Find a channel by name.
Definition: channel.c:1454
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
Definition: manager.c:3159
const ast_string_field subclass
Definition: bridge.h:336
struct ast_bridge_snapshot * ast_bridge_get_snapshot_by_uniqueid(const char *bridge_id)
Returns the current snapshot for the bridge.
struct ast_bridge_snapshot * to
#define ast_str_create(init_len)
Create a malloc&#39;ed dynamic length string.
Definition: strings.h:620
static void channel_leave_cb(void *data, struct stasis_subscription *sub, struct stasis_message *message)
static char prefix[MAX_PREFIX]
Definition: http.c:141
void astman_send_listack(struct mansession *s, const struct message *m, char *msg, char *listflag)
Send ack in manager transaction to begin a list.
Definition: manager.c:3201