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