aab78ce189c755362bc2b8dac8d60bf701500dd9
[asterisk/asterisk.git] / res / ari / resource_bridges.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2012 - 2013, Digium, Inc.
5  *
6  * David M. Lee, II <dlee@digium.com>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18
19 /*! \file
20  *
21  * \brief Implementation for ARI stubs.
22  *
23  * \author David M. Lee, II <dlee@digium.com>
24  */
25
26 /*** MODULEINFO
27         <depend type="module">res_stasis_recording</depend>
28         <depend type="module">res_stasis_playback</depend>
29         <support_level>core</support_level>
30  ***/
31
32 #include "asterisk.h"
33
34 #include "resource_bridges.h"
35 #include "asterisk/stasis.h"
36 #include "asterisk/stasis_bridges.h"
37 #include "asterisk/stasis_app.h"
38 #include "asterisk/stasis_app_impl.h"
39 #include "asterisk/stasis_app_playback.h"
40 #include "asterisk/stasis_app_recording.h"
41 #include "asterisk/stasis_channels.h"
42 #include "asterisk/core_unreal.h"
43 #include "asterisk/channel.h"
44 #include "asterisk/bridge.h"
45 #include "asterisk/format_cap.h"
46 #include "asterisk/file.h"
47 #include "asterisk/musiconhold.h"
48 #include "asterisk/format_cache.h"
49
50 /*!
51  * \brief Finds a bridge, filling the response with an error, if appropriate.
52  *
53  * \param[out] response Response to fill with an error if control is not found.
54  * \param bridge_id ID of the bridge to lookup.
55  *
56  * \return Bridget.
57  * \return \c NULL if bridge does not exist.
58  */
59 static struct ast_bridge *find_bridge(
60         struct ast_ari_response *response,
61         const char *bridge_id)
62 {
63         RAII_VAR(struct ast_bridge *, bridge, NULL, ao2_cleanup);
64
65         ast_assert(response != NULL);
66
67         bridge = stasis_app_bridge_find_by_id(bridge_id);
68         if (bridge == NULL) {
69                 RAII_VAR(struct ast_bridge_snapshot *, snapshot,
70                         ast_bridge_snapshot_get_latest(bridge_id), ao2_cleanup);
71                 if (!snapshot) {
72                         ast_ari_response_error(response, 404, "Not found",
73                                 "Bridge not found");
74                         return NULL;
75                 }
76
77                 ast_ari_response_error(response, 409, "Conflict",
78                         "Bridge not in Stasis application");
79                 return NULL;
80         }
81
82         ao2_ref(bridge, +1);
83         return bridge;
84 }
85
86 /*!
87  * \brief Finds the control object for a channel, filling the response with an
88  * error, if appropriate.
89  * \param[out] response Response to fill with an error if control is not found.
90  * \param channel_id ID of the channel to lookup.
91  * \return Channel control object.
92  * \return \c NULL if control object does not exist.
93  */
94 static struct stasis_app_control *find_channel_control(
95         struct ast_ari_response *response,
96         const char *channel_id)
97 {
98         RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
99
100         ast_assert(response != NULL);
101
102         control = stasis_app_control_find_by_channel_id(channel_id);
103         if (control == NULL) {
104                 /* Distinguish between 400 and 422 errors */
105                 RAII_VAR(struct ast_channel_snapshot *, snapshot, NULL,
106                         ao2_cleanup);
107                 snapshot = ast_channel_snapshot_get_latest(channel_id);
108                 if (snapshot == NULL) {
109                         ast_log(LOG_DEBUG, "Couldn't find '%s'\n", channel_id);
110                         ast_ari_response_error(response, 400, "Bad Request",
111                                 "Channel not found");
112                         return NULL;
113                 }
114
115                 ast_log(LOG_DEBUG, "Found non-stasis '%s'\n", channel_id);
116                 ast_ari_response_error(response, 422, "Unprocessable Entity",
117                         "Channel not in Stasis application");
118                 return NULL;
119         }
120
121         ao2_ref(control, +1);
122         return control;
123 }
124
125 struct control_list {
126         size_t count;
127         struct stasis_app_control *controls[];
128 };
129
130 static void control_list_dtor(void *obj) {
131         struct control_list *list = obj;
132         size_t i;
133
134         for (i = 0; i < list->count; ++i) {
135                 ao2_cleanup(list->controls[i]);
136                 list->controls[i] = NULL;
137         }
138 }
139
140 static struct control_list *control_list_create(struct ast_ari_response *response, size_t count, const char **channels) {
141         RAII_VAR(struct control_list *, list, NULL, ao2_cleanup);
142         size_t i;
143
144         if (count == 0 || !channels) {
145                 ast_ari_response_error(response, 400, "Bad Request", "Missing parameter channel");
146                 return NULL;
147         }
148
149         list = ao2_alloc(sizeof(*list) + count * sizeof(list->controls[0]), control_list_dtor);
150         if (!list) {
151                 ast_ari_response_alloc_failed(response);
152                 return NULL;
153         }
154
155         for (i = 0; i < count; ++i) {
156                 if (ast_strlen_zero(channels[i])) {
157                         continue;
158                 }
159                 list->controls[list->count] =
160                         find_channel_control(response, channels[i]);
161                 if (!list->controls[list->count]) {
162                         /* response filled in by find_channel_control() */
163                         return NULL;
164                 }
165                 ++list->count;
166         }
167
168         if (list->count == 0) {
169                 ast_ari_response_error(response, 400, "Bad Request", "Missing parameter channel");
170                 return NULL;
171         }
172
173         ao2_ref(list, +1);
174         return list;
175 }
176
177 static int check_add_remove_channel(struct ast_ari_response *response,
178                                     struct stasis_app_control *control,
179                                     enum stasis_app_control_channel_result result)
180 {
181         switch (result) {
182         case STASIS_APP_CHANNEL_RECORDING :
183                 ast_ari_response_error(
184                         response, 409, "Conflict", "Channel %s currently recording",
185                         stasis_app_control_get_channel_id(control));
186                 return -1;
187         case STASIS_APP_CHANNEL_OKAY:
188                 return 0;
189         }
190         return 0;
191 }
192
193 void ast_ari_bridges_add_channel(struct ast_variable *headers,
194         struct ast_ari_bridges_add_channel_args *args,
195         struct ast_ari_response *response)
196 {
197         RAII_VAR(struct ast_bridge *, bridge, find_bridge(response, args->bridge_id), ao2_cleanup);
198         RAII_VAR(struct control_list *, list, NULL, ao2_cleanup);
199         size_t i;
200         int has_error = 0;
201
202         if (!bridge) {
203                 /* Response filled in by find_bridge() */
204                 return;
205         }
206
207         list = control_list_create(response, args->channel_count, args->channel);
208         if (!list) {
209                 /* Response filled in by control_list_create() */
210                 return;
211         }
212
213         for (i = 0; i < list->count; ++i) {
214                 stasis_app_control_clear_roles(list->controls[i]);
215                 if (!ast_strlen_zero(args->role)) {
216                         if (stasis_app_control_add_role(list->controls[i], args->role)) {
217                                 ast_ari_response_alloc_failed(response);
218                                 return;
219                         }
220                 }
221
222                 /* Apply bridge features to each of the channel controls */
223                 if (!stasis_app_control_bridge_features_init(list->controls[i])) {
224                         stasis_app_control_absorb_dtmf_in_bridge(list->controls[i], args->absorb_dtmf);
225                         stasis_app_control_mute_in_bridge(list->controls[i], args->mute);
226                 }
227         }
228
229         for (i = 0; i < list->count; ++i) {
230                 if ((has_error = check_add_remove_channel(response, list->controls[i],
231                              stasis_app_control_add_channel_to_bridge(
232                                     list->controls[i], bridge)))) {
233                         break;
234                 }
235         }
236
237         if (!has_error) {
238                 ast_ari_response_no_content(response);
239         }
240 }
241
242 void ast_ari_bridges_remove_channel(struct ast_variable *headers,
243         struct ast_ari_bridges_remove_channel_args *args,
244         struct ast_ari_response *response)
245 {
246         RAII_VAR(struct ast_bridge *, bridge, find_bridge(response, args->bridge_id), ao2_cleanup);
247         RAII_VAR(struct control_list *, list, NULL, ao2_cleanup);
248         size_t i;
249
250         if (!bridge) {
251                 /* Response filled in by find_bridge() */
252                 return;
253         }
254
255         list = control_list_create(response, args->channel_count, args->channel);
256         if (!list) {
257                 /* Response filled in by control_list_create() */
258                 return;
259         }
260
261         /* Make sure all of the channels are in this bridge */
262         for (i = 0; i < list->count; ++i) {
263                 if (stasis_app_get_bridge(list->controls[i]) != bridge) {
264                         ast_log(LOG_WARNING, "Channel %s not in bridge %s\n",
265                                 args->channel[i], args->bridge_id);
266                         ast_ari_response_error(response, 422,
267                                 "Unprocessable Entity",
268                                 "Channel not in this bridge");
269                         return;
270                 }
271         }
272
273         /* Now actually remove it */
274         for (i = 0; i < list->count; ++i) {
275                 stasis_app_control_remove_channel_from_bridge(list->controls[i],
276                         bridge);
277         }
278
279         ast_ari_response_no_content(response);
280 }
281
282 struct bridge_channel_control_thread_data {
283         struct ast_channel *bridge_channel;
284         struct stasis_app_control *control;
285         struct stasis_forward *forward;
286         char bridge_id[0];
287 };
288
289 static void *bridge_channel_control_thread(void *data)
290 {
291         struct bridge_channel_control_thread_data *thread_data = data;
292         struct ast_channel *bridge_channel = thread_data->bridge_channel;
293         struct stasis_app_control *control = thread_data->control;
294         struct stasis_forward *forward = thread_data->forward;
295         ast_callid callid = ast_channel_callid(bridge_channel);
296         char *bridge_id = ast_strdupa(thread_data->bridge_id);
297
298         if (callid) {
299                 ast_callid_threadassoc_add(callid);
300         }
301
302         ast_free(thread_data);
303         thread_data = NULL;
304
305         stasis_app_control_execute_until_exhausted(bridge_channel, control);
306         stasis_app_control_flush_queue(control);
307
308         stasis_app_bridge_playback_channel_remove(bridge_id, control);
309         stasis_forward_cancel(forward);
310         ao2_cleanup(control);
311         ast_hangup(bridge_channel);
312         return NULL;
313 }
314
315 static struct ast_channel *prepare_bridge_media_channel(const char *type)
316 {
317         RAII_VAR(struct ast_format_cap *, cap, NULL, ao2_cleanup);
318         struct ast_channel *chan;
319
320         cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
321         if (!cap) {
322                 return NULL;
323         }
324
325         ast_format_cap_append(cap, ast_format_slin, 0);
326
327         chan = ast_request(type, cap, NULL, NULL, "ARI", NULL);
328         if (!chan) {
329                 return NULL;
330         }
331
332         if (stasis_app_channel_unreal_set_internal(chan)) {
333                 ast_channel_cleanup(chan);
334                 return NULL;
335         }
336         return chan;
337 }
338
339 /*!
340  * \brief Performs common setup for a bridge playback operation
341  * with both new controls and when existing controls are  found.
342  *
343  * \param args_media medias to play
344  * \param args_media_count number of media items in \c media
345  * \param args_lang language string split from arguments
346  * \param args_offset_ms milliseconds offset split from arguments
347  * \param args_playback_id string to use for playback split from
348  *        arguments (null valid)
349  * \param response ARI response being built
350  * \param bridge Bridge the playback is being peformed on
351  * \param control Control being used for the playback channel
352  * \param json contents of the response to ARI
353  * \param playback_url stores playback URL for use with response
354  *
355  * \retval -1 operation failed
356  * \retval operation was successful
357  */
358 static int ari_bridges_play_helper(const char **args_media,
359         size_t args_media_count,
360         const char *args_lang,
361         int args_offset_ms,
362         int args_skipms,
363         const char *args_playback_id,
364         struct ast_ari_response *response,
365         struct ast_bridge *bridge,
366         struct stasis_app_control *control,
367         struct ast_json **json,
368         char **playback_url)
369 {
370         RAII_VAR(struct ast_channel_snapshot *, snapshot, NULL, ao2_cleanup);
371         RAII_VAR(struct stasis_app_playback *, playback, NULL, ao2_cleanup);
372
373         const char *language;
374
375         snapshot = stasis_app_control_get_snapshot(control);
376         if (!snapshot) {
377                 ast_ari_response_error(
378                         response, 500, "Internal Error", "Failed to get control snapshot");
379                 return -1;
380         }
381
382         language = S_OR(args_lang, snapshot->language);
383
384         playback = stasis_app_control_play_uri(control, args_media, args_media_count,
385                 language, bridge->uniqueid, STASIS_PLAYBACK_TARGET_BRIDGE, args_skipms,
386                 args_offset_ms, args_playback_id);
387
388         if (!playback) {
389                 ast_ari_response_alloc_failed(response);
390                 return -1;
391         }
392
393         if (ast_asprintf(playback_url, "/playbacks/%s",
394                         stasis_app_playback_get_id(playback)) == -1) {
395                 playback_url = NULL;
396                 ast_ari_response_alloc_failed(response);
397                 return -1;
398         }
399
400         *json = stasis_app_playback_to_json(playback);
401         if (!*json) {
402                 ast_ari_response_alloc_failed(response);
403                 return -1;
404         }
405
406         return 0;
407 }
408
409 static void ari_bridges_play_new(const char **args_media,
410         size_t args_media_count,
411         const char *args_lang,
412         int args_offset_ms,
413         int args_skipms,
414         const char *args_playback_id,
415         struct ast_ari_response *response,
416         struct ast_bridge *bridge)
417 {
418         RAII_VAR(struct ast_channel *, play_channel, NULL, ast_hangup);
419         RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
420         RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
421         RAII_VAR(struct stasis_forward *, channel_forward, NULL, stasis_forward_cancel);
422         RAII_VAR(char *, playback_url, NULL, ast_free);
423
424         struct stasis_topic *channel_topic;
425         struct stasis_topic *bridge_topic;
426         struct bridge_channel_control_thread_data *thread_data;
427         pthread_t threadid;
428
429         if (!(play_channel = prepare_bridge_media_channel("Announcer"))) {
430                 ast_ari_response_error(
431                         response, 500, "Internal Error", "Could not create playback channel");
432                 return;
433         }
434         ast_debug(1, "Created announcer channel '%s'\n", ast_channel_name(play_channel));
435
436         bridge_topic = ast_bridge_topic(bridge);
437         channel_topic = ast_channel_topic(play_channel);
438
439         /* Forward messages from the playback channel topic to the bridge topic so that anything listening for
440          * messages on the bridge topic will receive the playback start/stop messages. Other messages that would
441          * go to this channel will be suppressed since the channel is marked as internal.
442          */
443         if (!bridge_topic || !channel_topic || !(channel_forward = stasis_forward_all(channel_topic, bridge_topic))) {
444                 ast_ari_response_error(
445                         response, 500, "Internal Error", "Could not forward playback channel stasis messages to bridge topic");
446                 return;
447         }
448
449         if (ast_unreal_channel_push_to_bridge(play_channel, bridge,
450                 AST_BRIDGE_CHANNEL_FLAG_IMMOVABLE | AST_BRIDGE_CHANNEL_FLAG_LONELY)) {
451                 ast_ari_response_error(
452                         response, 500, "Internal Error", "Failed to put playback channel into the bridge");
453                 return;
454         }
455
456         control = stasis_app_control_create(play_channel);
457         if (control == NULL) {
458                 ast_ari_response_alloc_failed(response);
459                 return;
460         }
461
462         ao2_lock(control);
463         if (ari_bridges_play_helper(args_media, args_media_count, args_lang,
464                         args_offset_ms, args_skipms, args_playback_id, response, bridge,
465                         control, &json, &playback_url)) {
466                 ao2_unlock(control);
467                 return;
468         }
469         ao2_unlock(control);
470
471         if (stasis_app_bridge_playback_channel_add(bridge, play_channel, control)) {
472                 ast_ari_response_alloc_failed(response);
473                 return;
474         }
475
476         /* Give play_channel and control reference to the thread data */
477         thread_data = ast_malloc(sizeof(*thread_data) + strlen(bridge->uniqueid) + 1);
478         if (!thread_data) {
479                 stasis_app_bridge_playback_channel_remove((char *)bridge->uniqueid, control);
480                 ast_ari_response_alloc_failed(response);
481                 return;
482         }
483
484         thread_data->bridge_channel = play_channel;
485         thread_data->control = control;
486         thread_data->forward = channel_forward;
487         /* Safe */
488         strcpy(thread_data->bridge_id, bridge->uniqueid);
489
490         if (ast_pthread_create_detached(&threadid, NULL, bridge_channel_control_thread, thread_data)) {
491                 stasis_app_bridge_playback_channel_remove((char *)bridge->uniqueid, control);
492                 ast_ari_response_alloc_failed(response);
493                 ast_free(thread_data);
494                 return;
495         }
496
497         /* These are owned by the other thread now, so we don't want RAII_VAR disposing of them. */
498         play_channel = NULL;
499         control = NULL;
500         channel_forward = NULL;
501
502         ast_ari_response_created(response, playback_url, ast_json_ref(json));
503 }
504
505 enum play_found_result {
506         PLAY_FOUND_SUCCESS,
507         PLAY_FOUND_FAILURE,
508         PLAY_FOUND_CHANNEL_UNAVAILABLE,
509 };
510
511 /*!
512  * \brief Performs common setup for a bridge playback operation
513  * with both new controls and when existing controls are  found.
514  *
515  * \param args_media medias to play
516  * \param args_media_count number of media items in \c media
517  * \param args_lang language string split from arguments
518  * \param args_offset_ms milliseconds offset split from arguments
519  * \param args_playback_id string to use for playback split from
520  *        arguments (null valid)
521  * \param response ARI response being built
522  * \param bridge Bridge the playback is being peformed on
523  * \param found_channel The channel that was found controlling playback
524  *
525  * \retval PLAY_FOUND_SUCCESS The operation was successful
526  * \retval PLAY_FOUND_FAILURE The operation failed (terminal failure)
527  * \retval PLAY_FOUND_CHANNEL_UNAVAILABLE The operation failed because
528  * the channel requested to playback with is breaking down.
529  */
530 static enum play_found_result ari_bridges_play_found(const char **args_media,
531         size_t args_media_count,
532         const char *args_lang,
533         int args_offset_ms,
534         int args_skipms,
535         const char *args_playback_id,
536         struct ast_ari_response *response,
537         struct ast_bridge *bridge,
538         struct ast_channel *found_channel)
539 {
540         RAII_VAR(struct ast_channel *, play_channel, found_channel, ao2_cleanup);
541         RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
542         RAII_VAR(char *, playback_url, NULL, ast_free);
543         RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
544
545         control = stasis_app_control_find_by_channel(play_channel);
546         if (!control) {
547                 return PLAY_FOUND_CHANNEL_UNAVAILABLE;
548         }
549
550         ao2_lock(control);
551         if (stasis_app_control_is_done(control)) {
552                 /* We failed to queue the action. Bailout and return that we aren't terminal. */
553                 ao2_unlock(control);
554                 return PLAY_FOUND_CHANNEL_UNAVAILABLE;
555         }
556
557         if (ari_bridges_play_helper(args_media, args_media_count,
558                         args_lang, args_offset_ms, args_skipms, args_playback_id,
559                         response, bridge, control, &json, &playback_url)) {
560                 ao2_unlock(control);
561                 return PLAY_FOUND_FAILURE;
562         }
563         ao2_unlock(control);
564
565         ast_ari_response_created(response, playback_url, ast_json_ref(json));
566         return PLAY_FOUND_SUCCESS;
567 }
568
569 static void ari_bridges_handle_play(
570         const char *args_bridge_id,
571         const char **args_media,
572         size_t args_media_count,
573         const char *args_lang,
574         int args_offset_ms,
575         int args_skipms,
576         const char *args_playback_id,
577         struct ast_ari_response *response)
578 {
579         RAII_VAR(struct ast_bridge *, bridge, find_bridge(response, args_bridge_id), ao2_cleanup);
580         struct ast_channel *play_channel;
581
582         ast_assert(response != NULL);
583
584         if (!bridge) {
585                 return;
586         }
587
588         while ((play_channel = stasis_app_bridge_playback_channel_find(bridge))) {
589                 /* If ari_bridges_play_found fails because the channel is unavailable for
590                  * playback, The channel will be removed from the playback list soon. We
591                  * can keep trying to get channels from the list until we either get one
592                  * that will work or else there isn't a channel for this bridge anymore,
593                  * in which case we'll revert to ari_bridges_play_new.
594                  */
595                 if (ari_bridges_play_found(args_media, args_media_count, args_lang,
596                                 args_offset_ms, args_skipms, args_playback_id, response,bridge,
597                                 play_channel) == PLAY_FOUND_CHANNEL_UNAVAILABLE) {
598                         continue;
599                 }
600                 return;
601         }
602
603         ari_bridges_play_new(args_media, args_media_count, args_lang, args_offset_ms,
604                 args_skipms, args_playback_id, response, bridge);
605 }
606
607
608 void ast_ari_bridges_play(struct ast_variable *headers,
609         struct ast_ari_bridges_play_args *args,
610         struct ast_ari_response *response)
611 {
612         ari_bridges_handle_play(args->bridge_id,
613         args->media,
614         args->media_count,
615         args->lang,
616         args->offsetms,
617         args->skipms,
618         args->playback_id,
619         response);
620 }
621
622 void ast_ari_bridges_play_with_id(struct ast_variable *headers,
623         struct ast_ari_bridges_play_with_id_args *args,
624         struct ast_ari_response *response)
625 {
626         ari_bridges_handle_play(args->bridge_id,
627         args->media,
628         args->media_count,
629         args->lang,
630         args->offsetms,
631         args->skipms,
632         args->playback_id,
633         response);
634 }
635
636 void ast_ari_bridges_record(struct ast_variable *headers,
637         struct ast_ari_bridges_record_args *args,
638         struct ast_ari_response *response)
639 {
640         RAII_VAR(struct ast_bridge *, bridge, find_bridge(response, args->bridge_id), ao2_cleanup);
641         RAII_VAR(struct ast_channel *, record_channel, NULL, ast_hangup);
642         RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
643         RAII_VAR(struct stasis_app_recording *, recording, NULL, ao2_cleanup);
644         RAII_VAR(char *, recording_url, NULL, ast_free);
645         RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
646         RAII_VAR(struct stasis_app_recording_options *, options, NULL, ao2_cleanup);
647         RAII_VAR(char *, uri_encoded_name, NULL, ast_free);
648         RAII_VAR(struct stasis_forward *, channel_forward, NULL, stasis_forward_cancel);
649
650         struct stasis_topic *channel_topic;
651         struct stasis_topic *bridge_topic;
652         size_t uri_name_maxlen;
653         struct bridge_channel_control_thread_data *thread_data;
654         pthread_t threadid;
655
656         ast_assert(response != NULL);
657
658         if (bridge == NULL) {
659                 return;
660         }
661
662         if (!(record_channel = prepare_bridge_media_channel("Recorder"))) {
663                 ast_ari_response_error(
664                         response, 500, "Internal Server Error", "Failed to create recording channel");
665                 return;
666         }
667
668         bridge_topic = ast_bridge_topic(bridge);
669         channel_topic = ast_channel_topic(record_channel);
670
671         /* Forward messages from the recording channel topic to the bridge topic so that anything listening for
672          * messages on the bridge topic will receive the recording start/stop messages. Other messages that would
673          * go to this channel will be suppressed since the channel is marked as internal.
674          */
675         if (!bridge_topic || !channel_topic || !(channel_forward = stasis_forward_all(channel_topic, bridge_topic))) {
676                 ast_ari_response_error(
677                         response, 500, "Internal Error", "Could not forward record channel stasis messages to bridge topic");
678                 return;
679         }
680
681         if (ast_unreal_channel_push_to_bridge(record_channel, bridge,
682                 AST_BRIDGE_CHANNEL_FLAG_IMMOVABLE | AST_BRIDGE_CHANNEL_FLAG_LONELY)) {
683                 ast_ari_response_error(
684                         response, 500, "Internal Error", "Failed to put recording channel into the bridge");
685                 return;
686         }
687
688         control = stasis_app_control_create(record_channel);
689         if (control == NULL) {
690                 ast_ari_response_alloc_failed(response);
691                 return;
692         }
693
694         options = stasis_app_recording_options_create(args->name, args->format);
695         if (options == NULL) {
696                 ast_ari_response_alloc_failed(response);
697                 return;
698         }
699
700         ast_string_field_build(options, target, "bridge:%s", args->bridge_id);
701         options->max_silence_seconds = args->max_silence_seconds;
702         options->max_duration_seconds = args->max_duration_seconds;
703         options->terminate_on =
704                 stasis_app_recording_termination_parse(args->terminate_on);
705         options->if_exists =
706                 stasis_app_recording_if_exists_parse(args->if_exists);
707         options->beep = args->beep;
708
709         if (options->terminate_on == STASIS_APP_RECORDING_TERMINATE_INVALID) {
710                 ast_ari_response_error(
711                         response, 400, "Bad Request",
712                         "terminateOn invalid");
713                 return;
714         }
715
716         if (options->if_exists == AST_RECORD_IF_EXISTS_ERROR) {
717                 ast_ari_response_error(
718                         response, 400, "Bad Request",
719                         "ifExists invalid");
720                 return;
721         }
722
723         if (!ast_get_format_for_file_ext(options->format)) {
724                 ast_ari_response_error(
725                         response, 422, "Unprocessable Entity",
726                         "specified format is unknown on this system");
727                 return;
728         }
729
730         recording = stasis_app_control_record(control, options);
731         if (recording == NULL) {
732                 switch(errno) {
733                 case EINVAL:
734                         /* While the arguments are invalid, we should have
735                          * caught them prior to calling record.
736                          */
737                         ast_ari_response_error(
738                                 response, 500, "Internal Server Error",
739                                 "Error parsing request");
740                         break;
741                 case EEXIST:
742                         ast_ari_response_error(response, 409, "Conflict",
743                                 "Recording '%s' already exists and can not be overwritten",
744                                 args->name);
745                         break;
746                 case ENOMEM:
747                         ast_ari_response_alloc_failed(response);
748                         break;
749                 case EPERM:
750                         ast_ari_response_error(
751                                 response, 400, "Bad Request",
752                                 "Recording name invalid");
753                         break;
754                 default:
755                         ast_log(LOG_WARNING,
756                                 "Unrecognized recording error: %s\n",
757                                 strerror(errno));
758                         ast_ari_response_error(
759                                 response, 500, "Internal Server Error",
760                                 "Internal Server Error");
761                         break;
762                 }
763                 return;
764         }
765
766         uri_name_maxlen = strlen(args->name) * 3;
767         uri_encoded_name = ast_malloc(uri_name_maxlen);
768         if (!uri_encoded_name) {
769                 ast_ari_response_alloc_failed(response);
770                 return;
771         }
772         ast_uri_encode(args->name, uri_encoded_name, uri_name_maxlen, ast_uri_http);
773
774         if (ast_asprintf(&recording_url, "/recordings/live/%s",
775                         uri_encoded_name) == -1) {
776                 recording_url = NULL;
777                 ast_ari_response_alloc_failed(response);
778                 return;
779         }
780
781         json = stasis_app_recording_to_json(recording);
782         if (!json) {
783                 ast_ari_response_alloc_failed(response);
784                 return;
785         }
786
787         thread_data = ast_calloc(1, sizeof(*thread_data));
788         if (!thread_data) {
789                 ast_ari_response_alloc_failed(response);
790                 return;
791         }
792
793         thread_data->bridge_channel = record_channel;
794         thread_data->control = control;
795         thread_data->forward = channel_forward;
796
797         if (ast_pthread_create_detached(&threadid, NULL, bridge_channel_control_thread, thread_data)) {
798                 ast_ari_response_alloc_failed(response);
799                 ast_free(thread_data);
800                 return;
801         }
802
803         /* These are owned by the other thread now, so we don't want RAII_VAR disposing of them. */
804         record_channel = NULL;
805         control = NULL;
806         channel_forward = NULL;
807
808         ast_ari_response_created(response, recording_url, ast_json_ref(json));
809 }
810
811 void ast_ari_bridges_start_moh(struct ast_variable *headers,
812         struct ast_ari_bridges_start_moh_args *args,
813         struct ast_ari_response *response)
814 {
815         RAII_VAR(struct ast_bridge *, bridge, find_bridge(response, args->bridge_id), ao2_cleanup);
816         struct ast_channel *moh_channel;
817         const char *moh_class = args->moh_class;
818
819         if (!bridge) {
820                 /* The response is provided by find_bridge() */
821                 return;
822         }
823
824         moh_channel = stasis_app_bridge_moh_channel(bridge);
825         if (!moh_channel) {
826                 ast_ari_response_alloc_failed(response);
827                 return;
828         }
829
830         ast_moh_start(moh_channel, moh_class, NULL);
831
832         ast_ari_response_no_content(response);
833
834 }
835
836 void ast_ari_bridges_stop_moh(struct ast_variable *headers,
837         struct ast_ari_bridges_stop_moh_args *args,
838         struct ast_ari_response *response)
839 {
840         RAII_VAR(struct ast_bridge *, bridge, find_bridge(response, args->bridge_id), ao2_cleanup);
841
842         if (!bridge) {
843                 /* the response is provided by find_bridge() */
844                 return;
845         }
846
847         if (stasis_app_bridge_moh_stop(bridge)) {
848                 ast_ari_response_error(
849                         response, 409, "Conflict",
850                         "Bridge isn't playing music");
851                 return;
852         }
853
854         ast_ari_response_no_content(response);
855 }
856
857 void ast_ari_bridges_get(struct ast_variable *headers,
858         struct ast_ari_bridges_get_args *args,
859         struct ast_ari_response *response)
860 {
861         RAII_VAR(struct ast_bridge_snapshot *, snapshot, ast_bridge_snapshot_get_latest(args->bridge_id), ao2_cleanup);
862         if (!snapshot) {
863                 ast_ari_response_error(
864                         response, 404, "Not Found",
865                         "Bridge not found");
866                 return;
867         }
868
869         ast_ari_response_ok(response,
870                 ast_bridge_snapshot_to_json(snapshot, stasis_app_get_sanitizer()));
871 }
872
873 void ast_ari_bridges_destroy(struct ast_variable *headers,
874         struct ast_ari_bridges_destroy_args *args,
875         struct ast_ari_response *response)
876 {
877         RAII_VAR(struct ast_bridge *, bridge, find_bridge(response, args->bridge_id), ao2_cleanup);
878         if (!bridge) {
879                 return;
880         }
881
882         stasis_app_bridge_destroy(args->bridge_id);
883         ast_ari_response_no_content(response);
884 }
885
886 void ast_ari_bridges_list(struct ast_variable *headers,
887         struct ast_ari_bridges_list_args *args,
888         struct ast_ari_response *response)
889 {
890         RAII_VAR(struct stasis_cache *, cache, NULL, ao2_cleanup);
891         RAII_VAR(struct ao2_container *, snapshots, NULL, ao2_cleanup);
892         RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
893         struct ao2_iterator i;
894         void *obj;
895
896         cache = ast_bridge_cache();
897         if (!cache) {
898                 ast_ari_response_error(
899                         response, 500, "Internal Server Error",
900                         "Message bus not initialized");
901                 return;
902         }
903         ao2_ref(cache, +1);
904
905         snapshots = stasis_cache_dump(cache, ast_bridge_snapshot_type());
906         if (!snapshots) {
907                 ast_ari_response_alloc_failed(response);
908                 return;
909         }
910
911         json = ast_json_array_create();
912         if (!json) {
913                 ast_ari_response_alloc_failed(response);
914                 return;
915         }
916
917         i = ao2_iterator_init(snapshots, 0);
918         while ((obj = ao2_iterator_next(&i))) {
919                 RAII_VAR(struct stasis_message *, msg, obj, ao2_cleanup);
920                 struct ast_bridge_snapshot *snapshot = stasis_message_data(msg);
921                 struct ast_json *json_bridge = ast_bridge_snapshot_to_json(snapshot, stasis_app_get_sanitizer());
922
923                 if (!json_bridge || ast_json_array_append(json, json_bridge)) {
924                         ao2_iterator_destroy(&i);
925                         ast_ari_response_alloc_failed(response);
926                         return;
927                 }
928         }
929         ao2_iterator_destroy(&i);
930
931         ast_ari_response_ok(response, ast_json_ref(json));
932 }
933
934 void ast_ari_bridges_create(struct ast_variable *headers,
935         struct ast_ari_bridges_create_args *args,
936         struct ast_ari_response *response)
937 {
938         RAII_VAR(struct ast_bridge *, bridge, stasis_app_bridge_create(args->type, args->name, args->bridge_id), ao2_cleanup);
939         RAII_VAR(struct ast_bridge_snapshot *, snapshot, NULL, ao2_cleanup);
940
941         if (!bridge) {
942                 ast_ari_response_error(
943                         response, 500, "Internal Error",
944                         "Unable to create bridge");
945                 return;
946         }
947
948         ast_bridge_lock(bridge);
949         snapshot = ast_bridge_snapshot_create(bridge);
950         ast_bridge_unlock(bridge);
951
952         if (!snapshot) {
953                 ast_ari_response_error(
954                         response, 500, "Internal Error",
955                         "Unable to create snapshot for new bridge");
956                 return;
957         }
958
959         ast_ari_response_ok(response,
960                 ast_bridge_snapshot_to_json(snapshot, stasis_app_get_sanitizer()));
961 }
962
963 void ast_ari_bridges_create_with_id(struct ast_variable *headers,
964         struct ast_ari_bridges_create_with_id_args *args,
965         struct ast_ari_response *response)
966 {
967         RAII_VAR(struct ast_bridge *, bridge, find_bridge(response, args->bridge_id), ao2_cleanup);
968         RAII_VAR(struct ast_bridge_snapshot *, snapshot, NULL, ao2_cleanup);
969
970         if (bridge) {
971                 /* update */
972                 if (!ast_strlen_zero(args->name)) {
973                         if (!strcmp(args->name, bridge->name)) {
974                                 ast_ari_response_error(
975                                         response, 500, "Internal Error",
976                                         "Changing bridge name is not implemented");
977                                 return;
978                         }
979                 }
980                 if (!ast_strlen_zero(args->type)) {
981                         ast_ari_response_error(
982                                 response, 500, "Internal Error",
983                                 "Supplying a bridge type when updating a bridge is not allowed.");
984                         return;
985                 }
986                 ast_ari_response_ok(response,
987                         ast_bridge_snapshot_to_json(snapshot, stasis_app_get_sanitizer()));
988                 return;
989         }
990
991         bridge = stasis_app_bridge_create(args->type, args->name, args->bridge_id);
992         if (!bridge) {
993                 ast_ari_response_error(
994                         response, 500, "Internal Error",
995                         "Unable to create bridge");
996                 return;
997         }
998
999         ast_bridge_lock(bridge);
1000         snapshot = ast_bridge_snapshot_create(bridge);
1001         ast_bridge_unlock(bridge);
1002
1003         if (!snapshot) {
1004                 ast_ari_response_error(
1005                         response, 500, "Internal Error",
1006                         "Unable to create snapshot for new bridge");
1007                 return;
1008         }
1009
1010         ast_ari_response_ok(response,
1011                 ast_bridge_snapshot_to_json(snapshot, stasis_app_get_sanitizer()));
1012 }
1013
1014 static int bridge_set_video_source_cb(struct stasis_app_control *control,
1015         struct ast_channel *chan, void *data)
1016 {
1017         struct ast_bridge *bridge = data;
1018
1019         ast_bridge_lock(bridge);
1020         ast_bridge_set_single_src_video_mode(bridge, chan);
1021         ast_bridge_unlock(bridge);
1022
1023         return 0;
1024 }
1025
1026 void ast_ari_bridges_set_video_source(struct ast_variable *headers,
1027         struct ast_ari_bridges_set_video_source_args *args, struct ast_ari_response *response)
1028 {
1029         struct ast_bridge *bridge;
1030         struct stasis_app_control *control;
1031
1032         bridge = find_bridge(response, args->bridge_id);
1033         if (!bridge) {
1034                 return;
1035         }
1036
1037         control = find_channel_control(response, args->channel_id);
1038         if (!control) {
1039                 ao2_ref(bridge, -1);
1040                 return;
1041         }
1042
1043         if (stasis_app_get_bridge(control) != bridge) {
1044                 ast_ari_response_error(response, 422,
1045                         "Unprocessable Entity",
1046                         "Channel not in this bridge");
1047                 ao2_ref(bridge, -1);
1048                 ao2_ref(control, -1);
1049                 return;
1050         }
1051
1052         stasis_app_send_command(control, bridge_set_video_source_cb,
1053                 ao2_bump(bridge), __ao2_cleanup);
1054
1055         ao2_ref(bridge, -1);
1056         ao2_ref(control, -1);
1057
1058         ast_ari_response_no_content(response);
1059 }
1060
1061 void ast_ari_bridges_clear_video_source(struct ast_variable *headers,
1062         struct ast_ari_bridges_clear_video_source_args *args, struct ast_ari_response *response)
1063 {
1064         struct ast_bridge *bridge;
1065
1066         bridge = find_bridge(response, args->bridge_id);
1067         if (!bridge) {
1068                 return;
1069         }
1070
1071         ast_bridge_lock(bridge);
1072         ast_bridge_set_talker_src_video_mode(bridge);
1073         ast_bridge_unlock(bridge);
1074
1075         ao2_ref(bridge, -1);
1076         ast_ari_response_no_content(response);
1077 }