Fix ast_(v)asprintf() malloc failure usage conditions.
[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                 ast_ari_response_alloc_failed(response);
396                 return -1;
397         }
398
399         *json = stasis_app_playback_to_json(playback);
400         if (!*json) {
401                 ast_ari_response_alloc_failed(response);
402                 return -1;
403         }
404
405         return 0;
406 }
407
408 static void ari_bridges_play_new(const char **args_media,
409         size_t args_media_count,
410         const char *args_lang,
411         int args_offset_ms,
412         int args_skipms,
413         const char *args_playback_id,
414         struct ast_ari_response *response,
415         struct ast_bridge *bridge)
416 {
417         RAII_VAR(struct ast_channel *, play_channel, NULL, ast_hangup);
418         RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
419         RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
420         RAII_VAR(struct stasis_forward *, channel_forward, NULL, stasis_forward_cancel);
421         RAII_VAR(char *, playback_url, NULL, ast_free);
422
423         struct stasis_topic *channel_topic;
424         struct stasis_topic *bridge_topic;
425         struct bridge_channel_control_thread_data *thread_data;
426         pthread_t threadid;
427
428         if (!(play_channel = prepare_bridge_media_channel("Announcer"))) {
429                 ast_ari_response_error(
430                         response, 500, "Internal Error", "Could not create playback channel");
431                 return;
432         }
433         ast_debug(1, "Created announcer channel '%s'\n", ast_channel_name(play_channel));
434
435         bridge_topic = ast_bridge_topic(bridge);
436         channel_topic = ast_channel_topic(play_channel);
437
438         /* Forward messages from the playback channel topic to the bridge topic so that anything listening for
439          * messages on the bridge topic will receive the playback start/stop messages. Other messages that would
440          * go to this channel will be suppressed since the channel is marked as internal.
441          */
442         if (!bridge_topic || !channel_topic || !(channel_forward = stasis_forward_all(channel_topic, bridge_topic))) {
443                 ast_ari_response_error(
444                         response, 500, "Internal Error", "Could not forward playback channel stasis messages to bridge topic");
445                 return;
446         }
447
448         if (ast_unreal_channel_push_to_bridge(play_channel, bridge,
449                 AST_BRIDGE_CHANNEL_FLAG_IMMOVABLE | AST_BRIDGE_CHANNEL_FLAG_LONELY)) {
450                 ast_ari_response_error(
451                         response, 500, "Internal Error", "Failed to put playback channel into the bridge");
452                 return;
453         }
454
455         control = stasis_app_control_create(play_channel);
456         if (control == NULL) {
457                 ast_ari_response_alloc_failed(response);
458                 return;
459         }
460
461         ao2_lock(control);
462         if (ari_bridges_play_helper(args_media, args_media_count, args_lang,
463                         args_offset_ms, args_skipms, args_playback_id, response, bridge,
464                         control, &json, &playback_url)) {
465                 ao2_unlock(control);
466                 return;
467         }
468         ao2_unlock(control);
469
470         if (stasis_app_bridge_playback_channel_add(bridge, play_channel, control)) {
471                 ast_ari_response_alloc_failed(response);
472                 return;
473         }
474
475         /* Give play_channel and control reference to the thread data */
476         thread_data = ast_malloc(sizeof(*thread_data) + strlen(bridge->uniqueid) + 1);
477         if (!thread_data) {
478                 stasis_app_bridge_playback_channel_remove((char *)bridge->uniqueid, control);
479                 ast_ari_response_alloc_failed(response);
480                 return;
481         }
482
483         thread_data->bridge_channel = play_channel;
484         thread_data->control = control;
485         thread_data->forward = channel_forward;
486         /* Safe */
487         strcpy(thread_data->bridge_id, bridge->uniqueid);
488
489         if (ast_pthread_create_detached(&threadid, NULL, bridge_channel_control_thread, thread_data)) {
490                 stasis_app_bridge_playback_channel_remove((char *)bridge->uniqueid, control);
491                 ast_ari_response_alloc_failed(response);
492                 ast_free(thread_data);
493                 return;
494         }
495
496         /* These are owned by the other thread now, so we don't want RAII_VAR disposing of them. */
497         play_channel = NULL;
498         control = NULL;
499         channel_forward = NULL;
500
501         ast_ari_response_created(response, playback_url, ast_json_ref(json));
502 }
503
504 enum play_found_result {
505         PLAY_FOUND_SUCCESS,
506         PLAY_FOUND_FAILURE,
507         PLAY_FOUND_CHANNEL_UNAVAILABLE,
508 };
509
510 /*!
511  * \brief Performs common setup for a bridge playback operation
512  * with both new controls and when existing controls are  found.
513  *
514  * \param args_media medias to play
515  * \param args_media_count number of media items in \c media
516  * \param args_lang language string split from arguments
517  * \param args_offset_ms milliseconds offset split from arguments
518  * \param args_playback_id string to use for playback split from
519  *        arguments (null valid)
520  * \param response ARI response being built
521  * \param bridge Bridge the playback is being peformed on
522  * \param found_channel The channel that was found controlling playback
523  *
524  * \retval PLAY_FOUND_SUCCESS The operation was successful
525  * \retval PLAY_FOUND_FAILURE The operation failed (terminal failure)
526  * \retval PLAY_FOUND_CHANNEL_UNAVAILABLE The operation failed because
527  * the channel requested to playback with is breaking down.
528  */
529 static enum play_found_result ari_bridges_play_found(const char **args_media,
530         size_t args_media_count,
531         const char *args_lang,
532         int args_offset_ms,
533         int args_skipms,
534         const char *args_playback_id,
535         struct ast_ari_response *response,
536         struct ast_bridge *bridge,
537         struct ast_channel *found_channel)
538 {
539         RAII_VAR(struct ast_channel *, play_channel, found_channel, ao2_cleanup);
540         RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
541         RAII_VAR(char *, playback_url, NULL, ast_free);
542         RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
543
544         control = stasis_app_control_find_by_channel(play_channel);
545         if (!control) {
546                 return PLAY_FOUND_CHANNEL_UNAVAILABLE;
547         }
548
549         ao2_lock(control);
550         if (stasis_app_control_is_done(control)) {
551                 /* We failed to queue the action. Bailout and return that we aren't terminal. */
552                 ao2_unlock(control);
553                 return PLAY_FOUND_CHANNEL_UNAVAILABLE;
554         }
555
556         if (ari_bridges_play_helper(args_media, args_media_count,
557                         args_lang, args_offset_ms, args_skipms, args_playback_id,
558                         response, bridge, control, &json, &playback_url)) {
559                 ao2_unlock(control);
560                 return PLAY_FOUND_FAILURE;
561         }
562         ao2_unlock(control);
563
564         ast_ari_response_created(response, playback_url, ast_json_ref(json));
565         return PLAY_FOUND_SUCCESS;
566 }
567
568 static void ari_bridges_handle_play(
569         const char *args_bridge_id,
570         const char **args_media,
571         size_t args_media_count,
572         const char *args_lang,
573         int args_offset_ms,
574         int args_skipms,
575         const char *args_playback_id,
576         struct ast_ari_response *response)
577 {
578         RAII_VAR(struct ast_bridge *, bridge, find_bridge(response, args_bridge_id), ao2_cleanup);
579         struct ast_channel *play_channel;
580
581         ast_assert(response != NULL);
582
583         if (!bridge) {
584                 return;
585         }
586
587         while ((play_channel = stasis_app_bridge_playback_channel_find(bridge))) {
588                 /* If ari_bridges_play_found fails because the channel is unavailable for
589                  * playback, The channel will be removed from the playback list soon. We
590                  * can keep trying to get channels from the list until we either get one
591                  * that will work or else there isn't a channel for this bridge anymore,
592                  * in which case we'll revert to ari_bridges_play_new.
593                  */
594                 if (ari_bridges_play_found(args_media, args_media_count, args_lang,
595                                 args_offset_ms, args_skipms, args_playback_id, response,bridge,
596                                 play_channel) == PLAY_FOUND_CHANNEL_UNAVAILABLE) {
597                         continue;
598                 }
599                 return;
600         }
601
602         ari_bridges_play_new(args_media, args_media_count, args_lang, args_offset_ms,
603                 args_skipms, args_playback_id, response, bridge);
604 }
605
606
607 void ast_ari_bridges_play(struct ast_variable *headers,
608         struct ast_ari_bridges_play_args *args,
609         struct ast_ari_response *response)
610 {
611         ari_bridges_handle_play(args->bridge_id,
612         args->media,
613         args->media_count,
614         args->lang,
615         args->offsetms,
616         args->skipms,
617         args->playback_id,
618         response);
619 }
620
621 void ast_ari_bridges_play_with_id(struct ast_variable *headers,
622         struct ast_ari_bridges_play_with_id_args *args,
623         struct ast_ari_response *response)
624 {
625         ari_bridges_handle_play(args->bridge_id,
626         args->media,
627         args->media_count,
628         args->lang,
629         args->offsetms,
630         args->skipms,
631         args->playback_id,
632         response);
633 }
634
635 void ast_ari_bridges_record(struct ast_variable *headers,
636         struct ast_ari_bridges_record_args *args,
637         struct ast_ari_response *response)
638 {
639         RAII_VAR(struct ast_bridge *, bridge, find_bridge(response, args->bridge_id), ao2_cleanup);
640         RAII_VAR(struct ast_channel *, record_channel, NULL, ast_hangup);
641         RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
642         RAII_VAR(struct stasis_app_recording *, recording, NULL, ao2_cleanup);
643         RAII_VAR(char *, recording_url, NULL, ast_free);
644         RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
645         RAII_VAR(struct stasis_app_recording_options *, options, NULL, ao2_cleanup);
646         RAII_VAR(char *, uri_encoded_name, NULL, ast_free);
647         RAII_VAR(struct stasis_forward *, channel_forward, NULL, stasis_forward_cancel);
648
649         struct stasis_topic *channel_topic;
650         struct stasis_topic *bridge_topic;
651         size_t uri_name_maxlen;
652         struct bridge_channel_control_thread_data *thread_data;
653         pthread_t threadid;
654
655         ast_assert(response != NULL);
656
657         if (bridge == NULL) {
658                 return;
659         }
660
661         if (!(record_channel = prepare_bridge_media_channel("Recorder"))) {
662                 ast_ari_response_error(
663                         response, 500, "Internal Server Error", "Failed to create recording channel");
664                 return;
665         }
666
667         bridge_topic = ast_bridge_topic(bridge);
668         channel_topic = ast_channel_topic(record_channel);
669
670         /* Forward messages from the recording channel topic to the bridge topic so that anything listening for
671          * messages on the bridge topic will receive the recording start/stop messages. Other messages that would
672          * go to this channel will be suppressed since the channel is marked as internal.
673          */
674         if (!bridge_topic || !channel_topic || !(channel_forward = stasis_forward_all(channel_topic, bridge_topic))) {
675                 ast_ari_response_error(
676                         response, 500, "Internal Error", "Could not forward record channel stasis messages to bridge topic");
677                 return;
678         }
679
680         if (ast_unreal_channel_push_to_bridge(record_channel, bridge,
681                 AST_BRIDGE_CHANNEL_FLAG_IMMOVABLE | AST_BRIDGE_CHANNEL_FLAG_LONELY)) {
682                 ast_ari_response_error(
683                         response, 500, "Internal Error", "Failed to put recording channel into the bridge");
684                 return;
685         }
686
687         control = stasis_app_control_create(record_channel);
688         if (control == NULL) {
689                 ast_ari_response_alloc_failed(response);
690                 return;
691         }
692
693         options = stasis_app_recording_options_create(args->name, args->format);
694         if (options == NULL) {
695                 ast_ari_response_alloc_failed(response);
696                 return;
697         }
698
699         ast_string_field_build(options, target, "bridge:%s", args->bridge_id);
700         options->max_silence_seconds = args->max_silence_seconds;
701         options->max_duration_seconds = args->max_duration_seconds;
702         options->terminate_on =
703                 stasis_app_recording_termination_parse(args->terminate_on);
704         options->if_exists =
705                 stasis_app_recording_if_exists_parse(args->if_exists);
706         options->beep = args->beep;
707
708         if (options->terminate_on == STASIS_APP_RECORDING_TERMINATE_INVALID) {
709                 ast_ari_response_error(
710                         response, 400, "Bad Request",
711                         "terminateOn invalid");
712                 return;
713         }
714
715         if (options->if_exists == AST_RECORD_IF_EXISTS_ERROR) {
716                 ast_ari_response_error(
717                         response, 400, "Bad Request",
718                         "ifExists invalid");
719                 return;
720         }
721
722         if (!ast_get_format_for_file_ext(options->format)) {
723                 ast_ari_response_error(
724                         response, 422, "Unprocessable Entity",
725                         "specified format is unknown on this system");
726                 return;
727         }
728
729         recording = stasis_app_control_record(control, options);
730         if (recording == NULL) {
731                 switch(errno) {
732                 case EINVAL:
733                         /* While the arguments are invalid, we should have
734                          * caught them prior to calling record.
735                          */
736                         ast_ari_response_error(
737                                 response, 500, "Internal Server Error",
738                                 "Error parsing request");
739                         break;
740                 case EEXIST:
741                         ast_ari_response_error(response, 409, "Conflict",
742                                 "Recording '%s' already exists and can not be overwritten",
743                                 args->name);
744                         break;
745                 case ENOMEM:
746                         ast_ari_response_alloc_failed(response);
747                         break;
748                 case EPERM:
749                         ast_ari_response_error(
750                                 response, 400, "Bad Request",
751                                 "Recording name invalid");
752                         break;
753                 default:
754                         ast_log(LOG_WARNING,
755                                 "Unrecognized recording error: %s\n",
756                                 strerror(errno));
757                         ast_ari_response_error(
758                                 response, 500, "Internal Server Error",
759                                 "Internal Server Error");
760                         break;
761                 }
762                 return;
763         }
764
765         uri_name_maxlen = strlen(args->name) * 3;
766         uri_encoded_name = ast_malloc(uri_name_maxlen);
767         if (!uri_encoded_name) {
768                 ast_ari_response_alloc_failed(response);
769                 return;
770         }
771         ast_uri_encode(args->name, uri_encoded_name, uri_name_maxlen, ast_uri_http);
772
773         if (ast_asprintf(&recording_url, "/recordings/live/%s",
774                         uri_encoded_name) == -1) {
775                 recording_url = NULL;
776                 ast_ari_response_alloc_failed(response);
777                 return;
778         }
779
780         json = stasis_app_recording_to_json(recording);
781         if (!json) {
782                 ast_ari_response_alloc_failed(response);
783                 return;
784         }
785
786         thread_data = ast_calloc(1, sizeof(*thread_data));
787         if (!thread_data) {
788                 ast_ari_response_alloc_failed(response);
789                 return;
790         }
791
792         thread_data->bridge_channel = record_channel;
793         thread_data->control = control;
794         thread_data->forward = channel_forward;
795
796         if (ast_pthread_create_detached(&threadid, NULL, bridge_channel_control_thread, thread_data)) {
797                 ast_ari_response_alloc_failed(response);
798                 ast_free(thread_data);
799                 return;
800         }
801
802         /* These are owned by the other thread now, so we don't want RAII_VAR disposing of them. */
803         record_channel = NULL;
804         control = NULL;
805         channel_forward = NULL;
806
807         ast_ari_response_created(response, recording_url, ast_json_ref(json));
808 }
809
810 void ast_ari_bridges_start_moh(struct ast_variable *headers,
811         struct ast_ari_bridges_start_moh_args *args,
812         struct ast_ari_response *response)
813 {
814         RAII_VAR(struct ast_bridge *, bridge, find_bridge(response, args->bridge_id), ao2_cleanup);
815         struct ast_channel *moh_channel;
816         const char *moh_class = args->moh_class;
817
818         if (!bridge) {
819                 /* The response is provided by find_bridge() */
820                 return;
821         }
822
823         moh_channel = stasis_app_bridge_moh_channel(bridge);
824         if (!moh_channel) {
825                 ast_ari_response_alloc_failed(response);
826                 return;
827         }
828
829         ast_moh_start(moh_channel, moh_class, NULL);
830
831         ast_ari_response_no_content(response);
832
833 }
834
835 void ast_ari_bridges_stop_moh(struct ast_variable *headers,
836         struct ast_ari_bridges_stop_moh_args *args,
837         struct ast_ari_response *response)
838 {
839         RAII_VAR(struct ast_bridge *, bridge, find_bridge(response, args->bridge_id), ao2_cleanup);
840
841         if (!bridge) {
842                 /* the response is provided by find_bridge() */
843                 return;
844         }
845
846         if (stasis_app_bridge_moh_stop(bridge)) {
847                 ast_ari_response_error(
848                         response, 409, "Conflict",
849                         "Bridge isn't playing music");
850                 return;
851         }
852
853         ast_ari_response_no_content(response);
854 }
855
856 void ast_ari_bridges_get(struct ast_variable *headers,
857         struct ast_ari_bridges_get_args *args,
858         struct ast_ari_response *response)
859 {
860         RAII_VAR(struct ast_bridge_snapshot *, snapshot, ast_bridge_snapshot_get_latest(args->bridge_id), ao2_cleanup);
861         if (!snapshot) {
862                 ast_ari_response_error(
863                         response, 404, "Not Found",
864                         "Bridge not found");
865                 return;
866         }
867
868         ast_ari_response_ok(response,
869                 ast_bridge_snapshot_to_json(snapshot, stasis_app_get_sanitizer()));
870 }
871
872 void ast_ari_bridges_destroy(struct ast_variable *headers,
873         struct ast_ari_bridges_destroy_args *args,
874         struct ast_ari_response *response)
875 {
876         RAII_VAR(struct ast_bridge *, bridge, find_bridge(response, args->bridge_id), ao2_cleanup);
877         if (!bridge) {
878                 return;
879         }
880
881         stasis_app_bridge_destroy(args->bridge_id);
882         ast_ari_response_no_content(response);
883 }
884
885 void ast_ari_bridges_list(struct ast_variable *headers,
886         struct ast_ari_bridges_list_args *args,
887         struct ast_ari_response *response)
888 {
889         RAII_VAR(struct stasis_cache *, cache, NULL, ao2_cleanup);
890         RAII_VAR(struct ao2_container *, snapshots, NULL, ao2_cleanup);
891         RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
892         struct ao2_iterator i;
893         void *obj;
894
895         cache = ast_bridge_cache();
896         if (!cache) {
897                 ast_ari_response_error(
898                         response, 500, "Internal Server Error",
899                         "Message bus not initialized");
900                 return;
901         }
902         ao2_ref(cache, +1);
903
904         snapshots = stasis_cache_dump(cache, ast_bridge_snapshot_type());
905         if (!snapshots) {
906                 ast_ari_response_alloc_failed(response);
907                 return;
908         }
909
910         json = ast_json_array_create();
911         if (!json) {
912                 ast_ari_response_alloc_failed(response);
913                 return;
914         }
915
916         i = ao2_iterator_init(snapshots, 0);
917         while ((obj = ao2_iterator_next(&i))) {
918                 RAII_VAR(struct stasis_message *, msg, obj, ao2_cleanup);
919                 struct ast_bridge_snapshot *snapshot = stasis_message_data(msg);
920                 struct ast_json *json_bridge = ast_bridge_snapshot_to_json(snapshot, stasis_app_get_sanitizer());
921
922                 if (!json_bridge || ast_json_array_append(json, json_bridge)) {
923                         ao2_iterator_destroy(&i);
924                         ast_ari_response_alloc_failed(response);
925                         return;
926                 }
927         }
928         ao2_iterator_destroy(&i);
929
930         ast_ari_response_ok(response, ast_json_ref(json));
931 }
932
933 void ast_ari_bridges_create(struct ast_variable *headers,
934         struct ast_ari_bridges_create_args *args,
935         struct ast_ari_response *response)
936 {
937         RAII_VAR(struct ast_bridge *, bridge, stasis_app_bridge_create(args->type, args->name, args->bridge_id), ao2_cleanup);
938         RAII_VAR(struct ast_bridge_snapshot *, snapshot, NULL, ao2_cleanup);
939
940         if (!bridge) {
941                 ast_ari_response_error(
942                         response, 500, "Internal Error",
943                         "Unable to create bridge");
944                 return;
945         }
946
947         ast_bridge_lock(bridge);
948         snapshot = ast_bridge_snapshot_create(bridge);
949         ast_bridge_unlock(bridge);
950
951         if (!snapshot) {
952                 ast_ari_response_error(
953                         response, 500, "Internal Error",
954                         "Unable to create snapshot for new bridge");
955                 return;
956         }
957
958         ast_ari_response_ok(response,
959                 ast_bridge_snapshot_to_json(snapshot, stasis_app_get_sanitizer()));
960 }
961
962 void ast_ari_bridges_create_with_id(struct ast_variable *headers,
963         struct ast_ari_bridges_create_with_id_args *args,
964         struct ast_ari_response *response)
965 {
966         RAII_VAR(struct ast_bridge *, bridge, find_bridge(response, args->bridge_id), ao2_cleanup);
967         RAII_VAR(struct ast_bridge_snapshot *, snapshot, NULL, ao2_cleanup);
968
969         if (bridge) {
970                 /* update */
971                 if (!ast_strlen_zero(args->name)) {
972                         if (!strcmp(args->name, bridge->name)) {
973                                 ast_ari_response_error(
974                                         response, 500, "Internal Error",
975                                         "Changing bridge name is not implemented");
976                                 return;
977                         }
978                 }
979                 if (!ast_strlen_zero(args->type)) {
980                         ast_ari_response_error(
981                                 response, 500, "Internal Error",
982                                 "Supplying a bridge type when updating a bridge is not allowed.");
983                         return;
984                 }
985                 ast_ari_response_ok(response,
986                         ast_bridge_snapshot_to_json(snapshot, stasis_app_get_sanitizer()));
987                 return;
988         }
989
990         bridge = stasis_app_bridge_create(args->type, args->name, args->bridge_id);
991         if (!bridge) {
992                 ast_ari_response_error(
993                         response, 500, "Internal Error",
994                         "Unable to create bridge");
995                 return;
996         }
997
998         ast_bridge_lock(bridge);
999         snapshot = ast_bridge_snapshot_create(bridge);
1000         ast_bridge_unlock(bridge);
1001
1002         if (!snapshot) {
1003                 ast_ari_response_error(
1004                         response, 500, "Internal Error",
1005                         "Unable to create snapshot for new bridge");
1006                 return;
1007         }
1008
1009         ast_ari_response_ok(response,
1010                 ast_bridge_snapshot_to_json(snapshot, stasis_app_get_sanitizer()));
1011 }
1012
1013 static int bridge_set_video_source_cb(struct stasis_app_control *control,
1014         struct ast_channel *chan, void *data)
1015 {
1016         struct ast_bridge *bridge = data;
1017
1018         ast_bridge_lock(bridge);
1019         ast_bridge_set_single_src_video_mode(bridge, chan);
1020         ast_bridge_unlock(bridge);
1021
1022         return 0;
1023 }
1024
1025 void ast_ari_bridges_set_video_source(struct ast_variable *headers,
1026         struct ast_ari_bridges_set_video_source_args *args, struct ast_ari_response *response)
1027 {
1028         struct ast_bridge *bridge;
1029         struct stasis_app_control *control;
1030
1031         bridge = find_bridge(response, args->bridge_id);
1032         if (!bridge) {
1033                 return;
1034         }
1035
1036         control = find_channel_control(response, args->channel_id);
1037         if (!control) {
1038                 ao2_ref(bridge, -1);
1039                 return;
1040         }
1041
1042         if (stasis_app_get_bridge(control) != bridge) {
1043                 ast_ari_response_error(response, 422,
1044                         "Unprocessable Entity",
1045                         "Channel not in this bridge");
1046                 ao2_ref(bridge, -1);
1047                 ao2_ref(control, -1);
1048                 return;
1049         }
1050
1051         stasis_app_send_command(control, bridge_set_video_source_cb,
1052                 ao2_bump(bridge), __ao2_cleanup);
1053
1054         ao2_ref(bridge, -1);
1055         ao2_ref(control, -1);
1056
1057         ast_ari_response_no_content(response);
1058 }
1059
1060 void ast_ari_bridges_clear_video_source(struct ast_variable *headers,
1061         struct ast_ari_bridges_clear_video_source_args *args, struct ast_ari_response *response)
1062 {
1063         struct ast_bridge *bridge;
1064
1065         bridge = find_bridge(response, args->bridge_id);
1066         if (!bridge) {
1067                 return;
1068         }
1069
1070         ast_bridge_lock(bridge);
1071         ast_bridge_set_talker_src_video_mode(bridge);
1072         ast_bridge_unlock(bridge);
1073
1074         ao2_ref(bridge, -1);
1075         ast_ari_response_no_content(response);
1076 }