vector: Additional string vector definitions.
[asterisk/asterisk.git] / main / manager_bridges.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2013, Digium, Inc.
5  *
6  * Kinsey Moore <kmoore@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 (bridge event handling)
22  *
23  * \author Kinsey Moore <kmoore@digium.com>
24  */
25
26 #include "asterisk.h"
27
28 #include "asterisk/stasis_bridges.h"
29 #include "asterisk/stasis_channels.h"
30 #include "asterisk/manager.h"
31 #include "asterisk/stasis_message_router.h"
32
33 /*! \brief Message router for cached bridge state snapshot updates */
34 static struct stasis_message_router *bridge_state_router;
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  */
221 static struct stasis_forward *topic_forwarder;
222
223 struct ast_str *ast_manager_build_bridge_state_string_prefix(
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
267 struct ast_str *ast_manager_build_bridge_state_string(
268         const struct ast_bridge_snapshot *snapshot)
269 {
270         return ast_manager_build_bridge_state_string_prefix(snapshot, "");
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 */
279 static struct ast_manager_event_blob *bridge_create(
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
287         return ast_manager_event_blob_create(
288                 EVENT_FLAG_CALL, "BridgeCreate", NO_EXTRA_FIELDS);
289 }
290
291 /* \brief Handle video source updates */
292 static struct ast_manager_event_blob *bridge_video_update(
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
304         return ast_manager_event_blob_create(
305                 EVENT_FLAG_CALL, "BridgeVideoSourceUpdate",
306                 "BridgePreviousVideoSource: %s\r\n",
307                 old_snapshot->video_source_id);
308 }
309
310 /*! \brief Handle bridge destruction */
311 static struct ast_manager_event_blob *bridge_destroy(
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
319         return ast_manager_event_blob_create(
320                 EVENT_FLAG_CALL, "BridgeDestroy", NO_EXTRA_FIELDS);
321 }
322
323 bridge_snapshot_monitor bridge_monitors[] = {
324         bridge_create,
325         bridge_video_update,
326         bridge_destroy,
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);
333         struct stasis_cache_update *update;
334         struct ast_bridge_snapshot *old_snapshot;
335         struct ast_bridge_snapshot *new_snapshot;
336         size_t i;
337
338         update = stasis_message_data(message);
339
340         ast_assert(ast_bridge_snapshot_type() == update->type);
341
342         old_snapshot = stasis_message_data(update->old_snapshot);
343         new_snapshot = stasis_message_data(update->new_snapshot);
344
345         for (i = 0; i < ARRAY_LEN(bridge_monitors); ++i) {
346                 RAII_VAR(struct ast_manager_event_blob *, event, NULL, ao2_cleanup);
347
348                 event = bridge_monitors[i](old_snapshot, new_snapshot);
349                 if (!event) {
350                         continue;
351                 }
352
353                 /* If we haven't already, build the channel event string */
354                 if (!bridge_event_string) {
355                         bridge_event_string =
356                                 ast_manager_build_bridge_state_string(
357                                         new_snapshot ? new_snapshot : old_snapshot);
358                         if (!bridge_event_string) {
359                                 return;
360                         }
361                 }
362
363                 manager_event(event->event_flags, event->manager_event, "%s%s",
364                         ast_str_buffer(bridge_event_string),
365                         event->extra_fields);
366         }
367 }
368
369 static void bridge_merge_cb(void *data, struct stasis_subscription *sub,
370                                     struct stasis_message *message)
371 {
372         struct ast_bridge_merge_message *merge_msg = stasis_message_data(message);
373         RAII_VAR(struct ast_str *, to_text, NULL, ast_free);
374         RAII_VAR(struct ast_str *, from_text, NULL, ast_free);
375
376         ast_assert(merge_msg->to != NULL);
377         ast_assert(merge_msg->from != NULL);
378
379         to_text = ast_manager_build_bridge_state_string_prefix(merge_msg->to, "To");
380         from_text = ast_manager_build_bridge_state_string_prefix(merge_msg->from, "From");
381         if (!to_text || !from_text) {
382                 return;
383         }
384
385         /*** DOCUMENTATION
386                 <managerEventInstance>
387                         <synopsis>Raised when two bridges are merged.</synopsis>
388                         <syntax>
389                                 <bridge_snapshot prefix="To"/>
390                                 <bridge_snapshot prefix="From"/>
391                         </syntax>
392                 </managerEventInstance>
393         ***/
394         manager_event(EVENT_FLAG_CALL, "BridgeMerge",
395                 "%s"
396                 "%s",
397                 ast_str_buffer(to_text),
398                 ast_str_buffer(from_text));
399 }
400
401 static void channel_enter_cb(void *data, struct stasis_subscription *sub,
402                                     struct stasis_message *message)
403 {
404         static const char *swap_name = "SwapUniqueid: ";
405         struct ast_bridge_blob *blob = stasis_message_data(message);
406         RAII_VAR(struct ast_str *, bridge_text, NULL, ast_free);
407         RAII_VAR(struct ast_str *, channel_text, NULL, ast_free);
408         const char *swap_id;
409
410         bridge_text = ast_manager_build_bridge_state_string(blob->bridge);
411         channel_text = ast_manager_build_channel_state_string(blob->channel);
412         if (!bridge_text || !channel_text) {
413                 return;
414         }
415
416         swap_id = ast_json_string_get(ast_json_object_get(blob->blob, "swap"));
417
418         manager_event(EVENT_FLAG_CALL, "BridgeEnter",
419                 "%s"
420                 "%s"
421                 "%s%s%s",
422                 ast_str_buffer(bridge_text),
423                 ast_str_buffer(channel_text),
424                 swap_id ? swap_name : "",
425                 S_OR(swap_id, ""),
426                 swap_id ? "\r\n" : "");
427 }
428
429 static void channel_leave_cb(void *data, struct stasis_subscription *sub,
430                                     struct stasis_message *message)
431 {
432         struct ast_bridge_blob *blob = stasis_message_data(message);
433         RAII_VAR(struct ast_str *, bridge_text, NULL, ast_free);
434         RAII_VAR(struct ast_str *, channel_text, NULL, ast_free);
435
436         bridge_text = ast_manager_build_bridge_state_string(blob->bridge);
437         channel_text = ast_manager_build_channel_state_string(blob->channel);
438         if (!bridge_text || !channel_text) {
439                 return;
440         }
441
442         manager_event(EVENT_FLAG_CALL, "BridgeLeave",
443                 "%s"
444                 "%s",
445                 ast_str_buffer(bridge_text),
446                 ast_str_buffer(channel_text));
447 }
448
449 static int filter_bridge_type_cb(void *obj, void *arg, int flags)
450 {
451         char *bridge_type = arg;
452         struct ast_bridge_snapshot *snapshot = stasis_message_data(obj);
453         /* unlink all the snapshots that do not match the bridge type */
454         return strcmp(bridge_type, snapshot->technology) ? CMP_MATCH : 0;
455 }
456
457 struct bridge_list_data {
458         const char *id_text;
459         int count;
460 };
461
462 static int send_bridge_list_item_cb(void *obj, void *arg, void *data, int flags)
463 {
464         struct ast_bridge_snapshot *snapshot = stasis_message_data(obj);
465         struct mansession *s = arg;
466         struct bridge_list_data *list_data = data;
467         RAII_VAR(struct ast_str *, bridge_info, ast_manager_build_bridge_state_string(snapshot), ast_free);
468
469         if (!bridge_info) {
470                 return 0;
471         }
472
473         astman_append(s,
474                 "Event: BridgeListItem\r\n"
475                 "%s"
476                 "%s"
477                 "\r\n",
478                 list_data->id_text,
479                 ast_str_buffer(bridge_info));
480         ++list_data->count;
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         RAII_VAR(struct ast_str *, id_text, ast_str_create(128), ast_free);
489         RAII_VAR(struct ao2_container *, bridges, NULL, ao2_cleanup);
490         struct bridge_list_data list_data;
491
492         if (!id_text) {
493                 astman_send_error(s, m, "Internal error");
494                 return -1;
495         }
496
497         if (!ast_strlen_zero(id)) {
498                 ast_str_set(&id_text, 0, "ActionID: %s\r\n", id);
499         }
500
501         bridges = stasis_cache_dump(ast_bridge_cache(), ast_bridge_snapshot_type());
502         if (!bridges) {
503                 astman_send_error(s, m, "Internal error");
504                 return -1;
505         }
506
507         astman_send_listack(s, m, "Bridge listing will follow", "start");
508
509         if (!ast_strlen_zero(type_filter)) {
510                 char *type_filter_dup = ast_strdupa(type_filter);
511
512                 ao2_callback(bridges, OBJ_MULTIPLE | OBJ_NODATA | OBJ_UNLINK,
513                         filter_bridge_type_cb, type_filter_dup);
514         }
515
516         list_data.id_text = ast_str_buffer(id_text);
517         list_data.count = 0;
518         ao2_callback_data(bridges, OBJ_NODATA, send_bridge_list_item_cb, s, &list_data);
519
520         astman_send_list_complete_start(s, m, "BridgeListComplete", list_data.count);
521         astman_send_list_complete_end(s);
522
523         return 0;
524 }
525
526 static int send_bridge_info_item_cb(void *obj, void *arg, void *data, int flags)
527 {
528         char *uniqueid = obj;
529         struct mansession *s = arg;
530         struct bridge_list_data *list_data = data;
531         RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
532         struct ast_channel_snapshot *snapshot;
533         RAII_VAR(struct ast_str *, channel_text, NULL, ast_free);
534
535         msg = stasis_cache_get(ast_channel_cache(),
536                 ast_channel_snapshot_type(), uniqueid);
537         if (!msg) {
538                 return 0;
539         }
540
541         snapshot = stasis_message_data(msg);
542         if (snapshot->tech_properties & AST_CHAN_TP_INTERNAL) {
543                 return 0;
544         }
545
546         channel_text = ast_manager_build_channel_state_string(snapshot);
547         if (!channel_text) {
548                 return 0;
549         }
550
551         astman_append(s,
552                 "Event: BridgeInfoChannel\r\n"
553                 "%s"
554                 "%s"
555                 "\r\n",
556                 list_data->id_text,
557                 ast_str_buffer(channel_text));
558         ++list_data->count;
559         return 0;
560 }
561
562 static int manager_bridge_info(struct mansession *s, const struct message *m)
563 {
564         const char *id = astman_get_header(m, "ActionID");
565         const char *bridge_uniqueid = astman_get_header(m, "BridgeUniqueid");
566         RAII_VAR(struct ast_str *, id_text, ast_str_create(128), ast_free);
567         RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
568         RAII_VAR(struct ast_str *, bridge_info, NULL, ast_free);
569         struct ast_bridge_snapshot *snapshot;
570         struct bridge_list_data list_data;
571
572         if (!id_text) {
573                 astman_send_error(s, m, "Internal error");
574                 return -1;
575         }
576
577         if (ast_strlen_zero(bridge_uniqueid)) {
578                 astman_send_error(s, m, "BridgeUniqueid must be provided");
579                 return 0;
580         }
581
582         if (!ast_strlen_zero(id)) {
583                 ast_str_set(&id_text, 0, "ActionID: %s\r\n", id);
584         }
585
586         msg = stasis_cache_get(ast_bridge_cache(), ast_bridge_snapshot_type(), bridge_uniqueid);
587         if (!msg) {
588                 astman_send_error(s, m, "Specified BridgeUniqueid not found");
589                 return 0;
590         }
591
592         snapshot = stasis_message_data(msg);
593         bridge_info = ast_manager_build_bridge_state_string(snapshot);
594         if (!bridge_info) {
595                 astman_send_error(s, m, "Internal error");
596                 return -1;
597         }
598
599         astman_send_listack(s, m, "Bridge channel listing will follow", "start");
600
601         list_data.id_text = ast_str_buffer(id_text);
602         list_data.count = 0;
603         ao2_callback_data(snapshot->channels, OBJ_NODATA, send_bridge_info_item_cb, s, &list_data);
604
605         astman_send_list_complete_start(s, m, "BridgeInfoComplete", list_data.count);
606         if (!ast_strlen_zero(ast_str_buffer(bridge_info))) {
607                 astman_append(s, "%s", ast_str_buffer(bridge_info));
608         }
609         astman_send_list_complete_end(s);
610
611         return 0;
612 }
613
614 static int manager_bridge_destroy(struct mansession *s, const struct message *m)
615 {
616         const char *bridge_uniqueid = astman_get_header(m, "BridgeUniqueid");
617         struct ast_bridge *bridge;
618
619         if (ast_strlen_zero(bridge_uniqueid)) {
620                 astman_send_error(s, m, "BridgeUniqueid must be provided");
621                 return 0;
622         }
623
624         bridge = ast_bridge_find_by_id(bridge_uniqueid);
625         if (!bridge) {
626                 astman_send_error(s, m, "Specified BridgeUniqueid not found");
627                 return 0;
628         }
629         ast_bridge_destroy(bridge, 0);
630
631         astman_send_ack(s, m, "Bridge has been destroyed");
632
633         return 0;
634 }
635
636 static int manager_bridge_kick(struct mansession *s, const struct message *m)
637 {
638         const char *bridge_uniqueid = astman_get_header(m, "BridgeUniqueid");
639         const char *channel_name = astman_get_header(m, "Channel");
640         RAII_VAR(struct ast_bridge *, bridge, NULL, ao2_cleanup);
641         RAII_VAR(struct ast_channel *, channel, NULL, ao2_cleanup);
642
643         if (ast_strlen_zero(channel_name)) {
644                 astman_send_error(s, m, "Channel must be provided");
645                 return 0;
646         }
647
648         channel = ast_channel_get_by_name(channel_name);
649         if (!channel) {
650                 astman_send_error(s, m, "Channel does not exist");
651                 return 0;
652         }
653
654         if (ast_strlen_zero(bridge_uniqueid)) {
655                 /* get the bridge from the channel */
656                 ast_channel_lock(channel);
657                 bridge = ast_channel_get_bridge(channel);
658                 ast_channel_unlock(channel);
659                 if (!bridge) {
660                         astman_send_error(s, m, "Channel is not in a bridge");
661                         return 0;
662                 }
663         } else {
664                 bridge = ast_bridge_find_by_id(bridge_uniqueid);
665                 if (!bridge || ast_test_flag(&bridge->feature_flags, AST_BRIDGE_FLAG_INVISIBLE)) {
666                         astman_send_error(s, m, "Bridge not found");
667                         return 0;
668                 }
669         }
670
671         if (ast_bridge_kick(bridge, channel)) {
672                 astman_send_error(s, m, "Channel kick from bridge failed");
673                 return 0;
674         }
675
676         astman_send_ack(s, m, "Channel has been kicked");
677         return 0;
678 }
679
680 static void manager_bridging_cleanup(void)
681 {
682         stasis_forward_cancel(topic_forwarder);
683         topic_forwarder = NULL;
684
685         ast_manager_unregister("BridgeList");
686         ast_manager_unregister("BridgeInfo");
687         ast_manager_unregister("BridgeDestroy");
688         ast_manager_unregister("BridgeKick");
689 }
690
691 int manager_bridging_init(void)
692 {
693         int ret = 0;
694         struct stasis_topic *manager_topic;
695         struct stasis_topic *bridge_topic;
696
697         if (bridge_state_router) {
698                 /* Already initialized */
699                 return 0;
700         }
701
702         ast_register_cleanup(manager_bridging_cleanup);
703
704         manager_topic = ast_manager_get_topic();
705         if (!manager_topic) {
706                 return -1;
707         }
708
709         bridge_topic = ast_bridge_topic_all_cached();
710         if (!bridge_topic) {
711                 return -1;
712         }
713
714         topic_forwarder = stasis_forward_all(bridge_topic, manager_topic);
715         if (!topic_forwarder) {
716                 return -1;
717         }
718
719         bridge_state_router = ast_manager_get_message_router();
720         if (!bridge_state_router) {
721                 return -1;
722         }
723
724         ret |= stasis_message_router_add_cache_update(bridge_state_router,
725                 ast_bridge_snapshot_type(), bridge_snapshot_update, NULL);
726
727         ret |= stasis_message_router_add(bridge_state_router,
728                 ast_bridge_merge_message_type(), bridge_merge_cb, NULL);
729
730         ret |= stasis_message_router_add(bridge_state_router,
731                 ast_channel_entered_bridge_type(), channel_enter_cb, NULL);
732
733         ret |= stasis_message_router_add(bridge_state_router,
734                 ast_channel_left_bridge_type(), channel_leave_cb, NULL);
735
736         ret |= ast_manager_register_xml_core("BridgeList", 0, manager_bridges_list);
737         ret |= ast_manager_register_xml_core("BridgeInfo", 0, manager_bridge_info);
738         ret |= ast_manager_register_xml_core("BridgeDestroy", 0, manager_bridge_destroy);
739         ret |= ast_manager_register_xml_core("BridgeKick", 0, manager_bridge_kick);
740
741         /* If somehow we failed to add any routes, just shut down the whole
742          * thing and fail it.
743          */
744         if (ret) {
745                 manager_bridging_cleanup();
746                 return -1;
747         }
748
749         return 0;
750 }