Improve call forwarding reporting, especially with regards to ARI.
[asterisk/asterisk.git] / res / ari / resource_channels.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_app_playback</depend>
28         <support_level>core</support_level>
29  ***/
30
31 #include "asterisk.h"
32
33 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
34
35 #include "asterisk/file.h"
36 #include "asterisk/pbx.h"
37 #include "asterisk/bridge.h"
38 #include "asterisk/callerid.h"
39 #include "asterisk/stasis_app.h"
40 #include "asterisk/stasis_app_playback.h"
41 #include "asterisk/stasis_app_recording.h"
42 #include "asterisk/stasis_app_snoop.h"
43 #include "asterisk/stasis_channels.h"
44 #include "asterisk/causes.h"
45 #include "asterisk/format_cache.h"
46 #include "asterisk/core_local.h"
47 #include "resource_channels.h"
48
49 #include <limits.h>
50
51 /*!
52  * \brief Finds the control object for a channel, filling the response with an
53  * error, if appropriate.
54  * \param[out] response Response to fill with an error if control is not found.
55  * \param channel_id ID of the channel to lookup.
56  * \return Channel control object.
57  * \return \c NULL if control object does not exist.
58  */
59 static struct stasis_app_control *find_control(
60         struct ast_ari_response *response,
61         const char *channel_id)
62 {
63         RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
64
65         ast_assert(response != NULL);
66
67         control = stasis_app_control_find_by_channel_id(channel_id);
68         if (control == NULL) {
69                 /* Distinguish between 404 and 409 errors */
70                 RAII_VAR(struct ast_channel *, chan, NULL, ao2_cleanup);
71                 chan = ast_channel_get_by_name(channel_id);
72                 if (chan == NULL) {
73                         ast_ari_response_error(response, 404, "Not Found",
74                                    "Channel not found");
75                         return NULL;
76                 }
77
78                 ast_ari_response_error(response, 409, "Conflict",
79                            "Channel not in Stasis application");
80                 return NULL;
81         }
82
83         ao2_ref(control, +1);
84         return control;
85 }
86
87 void ast_ari_channels_continue_in_dialplan(
88         struct ast_variable *headers,
89         struct ast_ari_channels_continue_in_dialplan_args *args,
90         struct ast_ari_response *response)
91 {
92         RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
93
94         ast_assert(response != NULL);
95
96         control = find_control(response, args->channel_id);
97         if (control == NULL) {
98                 return;
99         }
100
101         if (stasis_app_control_continue(control, args->context, args->extension, args->priority)) {
102                 ast_ari_response_alloc_failed(response);
103                 return;
104         }
105
106         ast_ari_response_no_content(response);
107 }
108
109 void ast_ari_channels_answer(struct ast_variable *headers,
110         struct ast_ari_channels_answer_args *args,
111         struct ast_ari_response *response)
112 {
113         RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
114
115         control = find_control(response, args->channel_id);
116         if (control == NULL) {
117                 return;
118         }
119
120         if (stasis_app_control_answer(control) != 0) {
121                 ast_ari_response_error(
122                         response, 500, "Internal Server Error",
123                         "Failed to answer channel");
124                 return;
125         }
126
127         ast_ari_response_no_content(response);
128 }
129
130 void ast_ari_channels_ring(struct ast_variable *headers,
131         struct ast_ari_channels_ring_args *args,
132         struct ast_ari_response *response)
133 {
134         RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
135
136         control = find_control(response, args->channel_id);
137         if (control == NULL) {
138                 return;
139         }
140
141         stasis_app_control_ring(control);
142
143         ast_ari_response_no_content(response);
144 }
145
146 void ast_ari_channels_ring_stop(struct ast_variable *headers,
147         struct ast_ari_channels_ring_stop_args *args,
148         struct ast_ari_response *response)
149 {
150         RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
151
152         control = find_control(response, args->channel_id);
153         if (control == NULL) {
154                 return;
155         }
156
157         stasis_app_control_ring_stop(control);
158
159         ast_ari_response_no_content(response);
160 }
161
162 void ast_ari_channels_mute(struct ast_variable *headers,
163         struct ast_ari_channels_mute_args *args,
164         struct ast_ari_response *response)
165 {
166         RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
167         unsigned int direction = 0;
168         enum ast_frame_type frametype = AST_FRAME_VOICE;
169
170         control = find_control(response, args->channel_id);
171         if (control == NULL) {
172                 return;
173         }
174
175         if (ast_strlen_zero(args->direction)) {
176                 ast_ari_response_error(
177                         response, 400, "Bad Request",
178                         "Direction is required");
179                 return;
180         }
181
182         if (!strcmp(args->direction, "in")) {
183                 direction = AST_MUTE_DIRECTION_READ;
184         } else if (!strcmp(args->direction, "out")) {
185                 direction = AST_MUTE_DIRECTION_WRITE;
186         } else if (!strcmp(args->direction, "both")) {
187                 direction = AST_MUTE_DIRECTION_READ | AST_MUTE_DIRECTION_WRITE;
188         } else {
189                 ast_ari_response_error(
190                         response, 400, "Bad Request",
191                         "Invalid direction specified");
192                 return;
193         }
194
195         stasis_app_control_mute(control, direction, frametype);
196
197         ast_ari_response_no_content(response);
198 }
199
200 void ast_ari_channels_unmute(struct ast_variable *headers,
201         struct ast_ari_channels_unmute_args *args,
202         struct ast_ari_response *response)
203 {
204         RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
205         unsigned int direction = 0;
206         enum ast_frame_type frametype = AST_FRAME_VOICE;
207
208         control = find_control(response, args->channel_id);
209         if (control == NULL) {
210                 return;
211         }
212
213         if (ast_strlen_zero(args->direction)) {
214                 ast_ari_response_error(
215                         response, 400, "Bad Request",
216                         "Direction is required");
217                 return;
218         }
219
220         if (!strcmp(args->direction, "in")) {
221                 direction = AST_MUTE_DIRECTION_READ;
222         } else if (!strcmp(args->direction, "out")) {
223                 direction = AST_MUTE_DIRECTION_WRITE;
224         } else if (!strcmp(args->direction, "both")) {
225                 direction = AST_MUTE_DIRECTION_READ | AST_MUTE_DIRECTION_WRITE;
226         } else {
227                 ast_ari_response_error(
228                         response, 400, "Bad Request",
229                         "Invalid direction specified");
230                 return;
231         }
232
233         stasis_app_control_unmute(control, direction, frametype);
234
235         ast_ari_response_no_content(response);
236 }
237
238 void ast_ari_channels_send_dtmf(struct ast_variable *headers,
239         struct ast_ari_channels_send_dtmf_args *args,
240         struct ast_ari_response *response)
241 {
242         RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
243
244         control = find_control(response, args->channel_id);
245         if (control == NULL) {
246                 return;
247         }
248
249         if (ast_strlen_zero(args->dtmf)) {
250                 ast_ari_response_error(
251                         response, 400, "Bad Request",
252                         "DTMF is required");
253                 return;
254         }
255
256         stasis_app_control_dtmf(control, args->dtmf, args->before, args->between, args->duration, args->after);
257
258         ast_ari_response_no_content(response);
259 }
260
261 void ast_ari_channels_hold(struct ast_variable *headers,
262         struct ast_ari_channels_hold_args *args,
263         struct ast_ari_response *response)
264 {
265         RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
266
267         control = find_control(response, args->channel_id);
268         if (control == NULL) {
269                 /* Response filled in by find_control */
270                 return;
271         }
272
273         stasis_app_control_hold(control);
274
275         ast_ari_response_no_content(response);
276 }
277
278 void ast_ari_channels_unhold(struct ast_variable *headers,
279         struct ast_ari_channels_unhold_args *args,
280         struct ast_ari_response *response)
281 {
282         RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
283
284         control = find_control(response, args->channel_id);
285         if (control == NULL) {
286                 /* Response filled in by find_control */
287                 return;
288         }
289
290         stasis_app_control_unhold(control);
291
292         ast_ari_response_no_content(response);
293 }
294
295 void ast_ari_channels_start_moh(struct ast_variable *headers,
296         struct ast_ari_channels_start_moh_args *args,
297         struct ast_ari_response *response)
298 {
299         RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
300
301         control = find_control(response, args->channel_id);
302         if (control == NULL) {
303                 /* Response filled in by find_control */
304                 return;
305         }
306
307         stasis_app_control_moh_start(control, args->moh_class);
308         ast_ari_response_no_content(response);
309 }
310
311 void ast_ari_channels_stop_moh(struct ast_variable *headers,
312         struct ast_ari_channels_stop_moh_args *args,
313         struct ast_ari_response *response)
314 {
315         RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
316
317         control = find_control(response, args->channel_id);
318         if (control == NULL) {
319                 /* Response filled in by find_control */
320                 return;
321         }
322
323         stasis_app_control_moh_stop(control);
324         ast_ari_response_no_content(response);
325 }
326
327 void ast_ari_channels_start_silence(struct ast_variable *headers,
328         struct ast_ari_channels_start_silence_args *args,
329         struct ast_ari_response *response)
330 {
331         RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
332
333         control = find_control(response, args->channel_id);
334         if (control == NULL) {
335                 /* Response filled in by find_control */
336                 return;
337         }
338
339         stasis_app_control_silence_start(control);
340         ast_ari_response_no_content(response);
341 }
342
343 void ast_ari_channels_stop_silence(struct ast_variable *headers,
344         struct ast_ari_channels_stop_silence_args *args,
345         struct ast_ari_response *response)
346 {
347         RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
348
349         control = find_control(response, args->channel_id);
350         if (control == NULL) {
351                 /* Response filled in by find_control */
352                 return;
353         }
354
355         stasis_app_control_silence_stop(control);
356         ast_ari_response_no_content(response);
357 }
358
359 static void ari_channels_handle_play(
360         const char *args_channel_id,
361         const char *args_media,
362         const char *args_lang,
363         int args_offsetms,
364         int args_skipms,
365         const char *args_playback_id,
366         struct ast_ari_response *response)
367 {
368         RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
369         RAII_VAR(struct ast_channel_snapshot *, snapshot, NULL, ao2_cleanup);
370         RAII_VAR(struct stasis_app_playback *, playback, NULL, ao2_cleanup);
371         RAII_VAR(char *, playback_url, NULL, ast_free);
372         struct ast_json *json;
373         const char *language;
374
375         ast_assert(response != NULL);
376
377         control = find_control(response, args_channel_id);
378         if (control == NULL) {
379                 /* Response filled in by find_control */
380                 return;
381         }
382
383         snapshot = stasis_app_control_get_snapshot(control);
384         if (!snapshot) {
385                 ast_ari_response_error(
386                         response, 404, "Not Found",
387                         "Channel not found");
388                 return;
389         }
390
391         if (args_skipms < 0) {
392                 ast_ari_response_error(
393                         response, 400, "Bad Request",
394                         "skipms cannot be negative");
395                 return;
396         }
397
398         if (args_offsetms < 0) {
399                 ast_ari_response_error(
400                         response, 400, "Bad Request",
401                         "offsetms cannot be negative");
402                 return;
403         }
404
405         language = S_OR(args_lang, snapshot->language);
406
407         playback = stasis_app_control_play_uri(control, args_media, language,
408                 args_channel_id, STASIS_PLAYBACK_TARGET_CHANNEL, args_skipms, args_offsetms, args_playback_id);
409         if (!playback) {
410                 ast_ari_response_error(
411                         response, 500, "Internal Server Error",
412                         "Failed to queue media for playback");
413                 return;
414         }
415
416         if (ast_asprintf(&playback_url, "/playback/%s",
417                         stasis_app_playback_get_id(playback)) == -1) {
418                 playback_url = NULL;
419                 ast_ari_response_error(
420                         response, 500, "Internal Server Error",
421                         "Out of memory");
422                 return;
423         }
424
425         json = stasis_app_playback_to_json(playback);
426         if (!json) {
427                 ast_ari_response_error(
428                         response, 500, "Internal Server Error",
429                         "Out of memory");
430                 return;
431         }
432
433         ast_ari_response_created(response, playback_url, json);
434 }
435
436 void ast_ari_channels_play(struct ast_variable *headers,
437         struct ast_ari_channels_play_args *args,
438         struct ast_ari_response *response)
439 {
440         ari_channels_handle_play(
441                 args->channel_id,
442                 args->media,
443                 args->lang,
444                 args->offsetms,
445                 args->skipms,
446                 args->playback_id,
447                 response);
448 }
449
450 void ast_ari_channels_play_with_id(struct ast_variable *headers,
451         struct ast_ari_channels_play_with_id_args *args,
452         struct ast_ari_response *response)
453 {
454         ari_channels_handle_play(
455                 args->channel_id,
456                 args->media,
457                 args->lang,
458                 args->offsetms,
459                 args->skipms,
460                 args->playback_id,
461                 response);
462 }
463
464 void ast_ari_channels_record(struct ast_variable *headers,
465         struct ast_ari_channels_record_args *args,
466         struct ast_ari_response *response)
467 {
468         RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
469         RAII_VAR(struct stasis_app_recording *, recording, NULL, ao2_cleanup);
470         RAII_VAR(char *, recording_url, NULL, ast_free);
471         struct ast_json *json;
472         RAII_VAR(struct stasis_app_recording_options *, options, NULL,
473                 ao2_cleanup);
474         RAII_VAR(char *, uri_encoded_name, NULL, ast_free);
475         size_t uri_name_maxlen;
476
477         ast_assert(response != NULL);
478
479         if (args->max_duration_seconds < 0) {
480                 ast_ari_response_error(
481                         response, 400, "Bad Request",
482                         "max_duration_seconds cannot be negative");
483                 return;
484         }
485
486         if (args->max_silence_seconds < 0) {
487                 ast_ari_response_error(
488                         response, 400, "Bad Request",
489                         "max_silence_seconds cannot be negative");
490                 return;
491         }
492
493         control = find_control(response, args->channel_id);
494         if (control == NULL) {
495                 /* Response filled in by find_control */
496                 return;
497         }
498
499         options = stasis_app_recording_options_create(args->name, args->format);
500         if (options == NULL) {
501                 ast_ari_response_error(
502                         response, 500, "Internal Server Error",
503                         "Out of memory");
504         }
505         ast_string_field_build(options, target, "channel:%s", args->channel_id);
506         options->max_silence_seconds = args->max_silence_seconds;
507         options->max_duration_seconds = args->max_duration_seconds;
508         options->terminate_on =
509                 stasis_app_recording_termination_parse(args->terminate_on);
510         options->if_exists =
511                 stasis_app_recording_if_exists_parse(args->if_exists);
512         options->beep = args->beep;
513
514         if (options->terminate_on == STASIS_APP_RECORDING_TERMINATE_INVALID) {
515                 ast_ari_response_error(
516                         response, 400, "Bad Request",
517                         "terminateOn invalid");
518                 return;
519         }
520
521         if (options->if_exists == -1) {
522                 ast_ari_response_error(
523                         response, 400, "Bad Request",
524                         "ifExists invalid");
525                 return;
526         }
527
528         if (!ast_get_format_for_file_ext(options->format)) {
529                 ast_ari_response_error(
530                         response, 422, "Unprocessable Entity",
531                         "specified format is unknown on this system");
532                 return;
533         }
534
535         recording = stasis_app_control_record(control, options);
536         if (recording == NULL) {
537                 switch(errno) {
538                 case EINVAL:
539                         /* While the arguments are invalid, we should have
540                          * caught them prior to calling record.
541                          */
542                         ast_ari_response_error(
543                                 response, 500, "Internal Server Error",
544                                 "Error parsing request");
545                         break;
546                 case EEXIST:
547                         ast_ari_response_error(response, 409, "Conflict",
548                                 "Recording '%s' already exists and can not be overwritten",
549                                 args->name);
550                         break;
551                 case ENOMEM:
552                         ast_ari_response_error(
553                                 response, 500, "Internal Server Error",
554                                 "Out of memory");
555                         break;
556                 case EPERM:
557                         ast_ari_response_error(
558                                 response, 400, "Bad Request",
559                                 "Recording name invalid");
560                         break;
561                 default:
562                         ast_log(LOG_WARNING,
563                                 "Unrecognized recording error: %s\n",
564                                 strerror(errno));
565                         ast_ari_response_error(
566                                 response, 500, "Internal Server Error",
567                                 "Internal Server Error");
568                         break;
569                 }
570                 return;
571         }
572
573         uri_name_maxlen = strlen(args->name) * 3;
574         uri_encoded_name = ast_malloc(uri_name_maxlen);
575         if (!uri_encoded_name) {
576                 ast_ari_response_error(
577                         response, 500, "Internal Server Error",
578                         "Out of memory");
579                 return;
580         }
581         ast_uri_encode(args->name, uri_encoded_name, uri_name_maxlen,
582                 ast_uri_http);
583
584         if (ast_asprintf(&recording_url, "/recordings/live/%s",
585                         uri_encoded_name) == -1) {
586                 recording_url = NULL;
587                 ast_ari_response_error(
588                         response, 500, "Internal Server Error",
589                         "Out of memory");
590                 return;
591         }
592
593         json = stasis_app_recording_to_json(recording);
594         if (!json) {
595                 ast_ari_response_error(
596                         response, 500, "Internal Server Error",
597                         "Out of memory");
598                 return;
599         }
600
601         ast_ari_response_created(response, recording_url, json);
602 }
603
604 void ast_ari_channels_get(struct ast_variable *headers,
605         struct ast_ari_channels_get_args *args,
606         struct ast_ari_response *response)
607 {
608         RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
609         struct stasis_cache *cache;
610         struct ast_channel_snapshot *snapshot;
611
612         cache = ast_channel_cache();
613         if (!cache) {
614                 ast_ari_response_error(
615                         response, 500, "Internal Server Error",
616                         "Message bus not initialized");
617                 return;
618         }
619
620         msg = stasis_cache_get(cache, ast_channel_snapshot_type(),
621                                    args->channel_id);
622         if (!msg) {
623                 ast_ari_response_error(
624                         response, 404, "Not Found",
625                         "Channel not found");
626                 return;
627         }
628
629         snapshot = stasis_message_data(msg);
630         ast_assert(snapshot != NULL);
631
632         ast_ari_response_ok(response,
633                                 ast_channel_snapshot_to_json(snapshot, NULL));
634 }
635
636 void ast_ari_channels_hangup(struct ast_variable *headers,
637         struct ast_ari_channels_hangup_args *args,
638         struct ast_ari_response *response)
639 {
640         RAII_VAR(struct ast_channel *, chan, NULL, ao2_cleanup);
641         int cause;
642
643         chan = ast_channel_get_by_name(args->channel_id);
644         if (chan == NULL) {
645                 ast_ari_response_error(
646                         response, 404, "Not Found",
647                         "Channel not found");
648                 return;
649         }
650
651         if (ast_strlen_zero(args->reason) || !strcmp(args->reason, "normal")) {
652                 cause = AST_CAUSE_NORMAL;
653         } else if (!strcmp(args->reason, "busy")) {
654                 cause = AST_CAUSE_BUSY;
655         } else if (!strcmp(args->reason, "congestion")) {
656                 cause = AST_CAUSE_CONGESTION;
657         } else {
658                 ast_ari_response_error(
659                         response, 400, "Invalid Reason",
660                         "Invalid reason for hangup provided");
661                 return;
662         }
663
664         ast_channel_hangupcause_set(chan, cause);
665         ast_softhangup(chan, AST_SOFTHANGUP_EXPLICIT);
666
667         ast_ari_response_no_content(response);
668 }
669
670 void ast_ari_channels_list(struct ast_variable *headers,
671         struct ast_ari_channels_list_args *args,
672         struct ast_ari_response *response)
673 {
674         RAII_VAR(struct stasis_cache *, cache, NULL, ao2_cleanup);
675         RAII_VAR(struct ao2_container *, snapshots, NULL, ao2_cleanup);
676         RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
677         struct ao2_iterator i;
678         void *obj;
679         struct stasis_message_sanitizer *sanitize = stasis_app_get_sanitizer();
680
681         cache = ast_channel_cache();
682         if (!cache) {
683                 ast_ari_response_error(
684                         response, 500, "Internal Server Error",
685                         "Message bus not initialized");
686                 return;
687         }
688         ao2_ref(cache, +1);
689
690         snapshots = stasis_cache_dump(cache, ast_channel_snapshot_type());
691         if (!snapshots) {
692                 ast_ari_response_alloc_failed(response);
693                 return;
694         }
695
696         json = ast_json_array_create();
697         if (!json) {
698                 ast_ari_response_alloc_failed(response);
699                 return;
700         }
701
702         i = ao2_iterator_init(snapshots, 0);
703         while ((obj = ao2_iterator_next(&i))) {
704                 RAII_VAR(struct stasis_message *, msg, obj, ao2_cleanup);
705                 struct ast_channel_snapshot *snapshot = stasis_message_data(msg);
706                 int r;
707
708                 if (sanitize && sanitize->channel_snapshot
709                         && sanitize->channel_snapshot(snapshot)) {
710                         continue;
711                 }
712
713                 r = ast_json_array_append(
714                         json, ast_channel_snapshot_to_json(snapshot, NULL));
715                 if (r != 0) {
716                         ast_ari_response_alloc_failed(response);
717                         ao2_iterator_destroy(&i);
718                         return;
719                 }
720         }
721         ao2_iterator_destroy(&i);
722
723         ast_ari_response_ok(response, ast_json_ref(json));
724 }
725
726 static void ari_channels_handle_originate_with_id(const char *args_endpoint,
727         const char *args_extension,
728         const char *args_context,
729         long args_priority,
730         const char *args_app,
731         const char *args_app_args,
732         const char *args_caller_id,
733         int args_timeout,
734         struct ast_variable *variables,
735         const char *args_channel_id,
736         const char *args_other_channel_id,
737         struct ast_ari_response *response)
738 {
739         char *dialtech;
740         char dialdevice[AST_CHANNEL_NAME];
741         char *caller_id = NULL;
742         char *cid_num = NULL;
743         char *cid_name = NULL;
744         int timeout = 30000;
745         RAII_VAR(struct ast_format_cap *, cap,
746                 ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT), ao2_cleanup);
747         char *stuff;
748         struct ast_channel *chan;
749         RAII_VAR(struct ast_channel_snapshot *, snapshot, NULL, ao2_cleanup);
750         struct ast_assigned_ids assignedids = {
751                 .uniqueid = args_channel_id,
752                 .uniqueid2 = args_other_channel_id,
753         };
754
755         if (!cap) {
756                 ast_ari_response_alloc_failed(response);
757                 return;
758         }
759         ast_format_cap_append(cap, ast_format_slin, 0);
760
761         if ((assignedids.uniqueid && AST_MAX_PUBLIC_UNIQUEID < strlen(assignedids.uniqueid))
762                 || (assignedids.uniqueid2 && AST_MAX_PUBLIC_UNIQUEID < strlen(assignedids.uniqueid2))) {
763                 ast_ari_response_error(response, 400, "Bad Request",
764                         "Uniqueid length exceeds maximum of %d", AST_MAX_PUBLIC_UNIQUEID);
765                 return;
766         }
767
768         if (ast_strlen_zero(args_endpoint)) {
769                 ast_ari_response_error(response, 400, "Bad Request",
770                         "Endpoint must be specified");
771                 return;
772         }
773
774         dialtech = ast_strdupa(args_endpoint);
775         if ((stuff = strchr(dialtech, '/'))) {
776                 *stuff++ = '\0';
777                 ast_copy_string(dialdevice, stuff, sizeof(dialdevice));
778         }
779
780         if (ast_strlen_zero(dialtech) || ast_strlen_zero(dialdevice)) {
781                 ast_ari_response_error(response, 400, "Bad Request",
782                         "Invalid endpoint specified");
783                 return;
784         }
785
786         if (args_timeout > 0) {
787                 timeout = args_timeout * 1000;
788         } else if (args_timeout == -1) {
789                 timeout = -1;
790         }
791
792         if (!ast_strlen_zero(args_caller_id)) {
793                 caller_id = ast_strdupa(args_caller_id);
794                 ast_callerid_parse(caller_id, &cid_name, &cid_num);
795
796                 if (ast_is_shrinkable_phonenumber(cid_num)) {
797                         ast_shrink_phone_number(cid_num);
798                 }
799         }
800
801         if (!ast_strlen_zero(args_app)) {
802                 const char *app = "Stasis";
803
804                 RAII_VAR(struct ast_str *, appdata, ast_str_create(64), ast_free);
805
806                 if (!appdata) {
807                         ast_ari_response_alloc_failed(response);
808                         return;
809                 }
810
811                 ast_str_set(&appdata, 0, "%s", args_app);
812                 if (!ast_strlen_zero(args_app_args)) {
813                         ast_str_append(&appdata, 0, ",%s", args_app_args);
814                 }
815
816                 /* originate a channel, putting it into an application */
817                 if (ast_pbx_outgoing_app(dialtech, cap, dialdevice, timeout, app, ast_str_buffer(appdata), NULL, 0, cid_num, cid_name, variables, NULL, &chan, &assignedids)) {
818                         ast_ari_response_alloc_failed(response);
819                         return;
820                 }
821         } else if (!ast_strlen_zero(args_extension)) {
822                 /* originate a channel, sending it to an extension */
823                 if (ast_pbx_outgoing_exten(dialtech, cap, dialdevice, timeout, S_OR(args_context, "default"), args_extension, args_priority ? args_priority : 1, NULL, 0, cid_num, cid_name, variables, NULL, &chan, 0, &assignedids)) {
824                         ast_ari_response_alloc_failed(response);
825                         return;
826                 }
827         } else {
828                 ast_ari_response_error(response, 400, "Bad Request",
829                         "Application or extension must be specified");
830                 return;
831         }
832
833         if (!ast_strlen_zero(args_app)) {
834                 struct ast_channel *local_peer;
835
836                 stasis_app_subscribe_channel(args_app, chan);
837
838                 /* Subscribe to the Local channel peer also. */
839                 local_peer = ast_local_get_peer(chan);
840                 if (local_peer) {
841                         stasis_app_subscribe_channel(args_app, local_peer);
842                         ast_channel_unref(local_peer);
843                 }
844         }
845
846         snapshot = ast_channel_snapshot_get_latest(ast_channel_uniqueid(chan));
847         ast_channel_unlock(chan);
848
849         ast_ari_response_ok(response, ast_channel_snapshot_to_json(snapshot, NULL));
850         ast_channel_unref(chan);
851 }
852
853 void ast_ari_channels_originate_with_id(struct ast_variable *headers,
854         struct ast_ari_channels_originate_with_id_args *args,
855         struct ast_ari_response *response)
856 {
857         RAII_VAR(struct ast_variable *, variables, NULL, ast_variables_destroy);
858
859         /* Parse any query parameters out of the body parameter */
860         if (args->variables) {
861                 struct ast_json *json_variables;
862
863                 ast_ari_channels_originate_with_id_parse_body(args->variables, args);
864                 json_variables = ast_json_object_get(args->variables, "variables");
865                 if (json_variables) {
866                         if (ast_json_to_ast_variables(json_variables, &variables)) {
867                                 ast_log(AST_LOG_ERROR, "Unable to convert 'variables' in JSON body to channel variables\n");
868                                 ast_ari_response_alloc_failed(response);
869                                 return;
870                         }
871                 }
872         }
873
874         ari_channels_handle_originate_with_id(
875                 args->endpoint,
876                 args->extension,
877                 args->context,
878                 args->priority,
879                 args->app,
880                 args->app_args,
881                 args->caller_id,
882                 args->timeout,
883                 variables,
884                 args->channel_id,
885                 args->other_channel_id,
886                 response);
887 }
888
889 void ast_ari_channels_originate(struct ast_variable *headers,
890         struct ast_ari_channels_originate_args *args,
891         struct ast_ari_response *response)
892 {
893         RAII_VAR(struct ast_variable *, variables, NULL, ast_variables_destroy);
894
895         /* Parse any query parameters out of the body parameter */
896         if (args->variables) {
897                 struct ast_json *json_variables;
898
899                 ast_ari_channels_originate_parse_body(args->variables, args);
900                 json_variables = ast_json_object_get(args->variables, "variables");
901                 if (json_variables) {
902                         if (ast_json_to_ast_variables(json_variables, &variables)) {
903                                 ast_log(AST_LOG_ERROR, "Unable to convert 'variables' in JSON body to channel variables\n");
904                                 ast_ari_response_alloc_failed(response);
905                                 return;
906                         }
907                 }
908         }
909
910         ari_channels_handle_originate_with_id(
911                 args->endpoint,
912                 args->extension,
913                 args->context,
914                 args->priority,
915                 args->app,
916                 args->app_args,
917                 args->caller_id,
918                 args->timeout,
919                 variables,
920                 args->channel_id,
921                 args->other_channel_id,
922                 response);
923 }
924
925 void ast_ari_channels_get_channel_var(struct ast_variable *headers,
926         struct ast_ari_channels_get_channel_var_args *args,
927         struct ast_ari_response *response)
928 {
929         RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
930         RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
931         RAII_VAR(struct ast_str *, value, ast_str_create(32), ast_free);
932         RAII_VAR(struct ast_channel *, channel, NULL, ast_channel_cleanup);
933
934         ast_assert(response != NULL);
935
936         if (ast_strlen_zero(args->variable)) {
937                 ast_ari_response_error(
938                         response, 400, "Bad Request",
939                         "Variable name is required");
940                 return;
941         }
942
943         if (ast_strlen_zero(args->channel_id)) {
944                 ast_ari_response_error(
945                         response, 400, "Bad Request",
946                         "Channel ID is required");
947                 return;
948         }
949
950         channel = ast_channel_get_by_name(args->channel_id);
951         if (!channel) {
952                 ast_ari_response_error(
953                         response, 404, "Channel Not Found",
954                         "Provided channel was not found");
955                 return;
956         }
957
958         /* You may be tempted to lock the channel you're about to read from. You
959          * would be wrong. Some dialplan functions put the channel into
960          * autoservice, which deadlocks if the channel is already locked.
961          * ast_str_retrieve_variable() does its own locking, and the dialplan
962          * functions need to as well. We should be fine without the lock.
963          */
964
965         if (args->variable[strlen(args->variable) - 1] == ')') {
966                 if (ast_func_read2(channel, args->variable, &value, 0)) {
967                         ast_ari_response_alloc_failed(response);
968                         return;
969                 }
970         } else {
971                 if (!ast_str_retrieve_variable(&value, 0, channel, NULL, args->variable)) {
972                         ast_ari_response_alloc_failed(response);
973                         return;
974                 }
975         }
976
977         if (!(json = ast_json_pack("{s: s}", "value", S_OR(ast_str_buffer(value), "")))) {
978                 ast_ari_response_alloc_failed(response);
979                 return;
980         }
981
982         ast_ari_response_ok(response, ast_json_ref(json));
983 }
984
985 void ast_ari_channels_set_channel_var(struct ast_variable *headers,
986         struct ast_ari_channels_set_channel_var_args *args,
987         struct ast_ari_response *response)
988 {
989         RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
990
991         ast_assert(response != NULL);
992
993         if (ast_strlen_zero(args->variable)) {
994                 ast_ari_response_error(
995                         response, 400, "Bad Request",
996                         "Variable name is required");
997                 return;
998         }
999
1000         control = find_control(response, args->channel_id);
1001         if (control == NULL) {
1002                 /* response filled in by find_control */
1003                 return;
1004         }
1005
1006         if (stasis_app_control_set_channel_var(control, args->variable, args->value)) {
1007                 ast_ari_response_error(
1008                         response, 400, "Bad Request",
1009                         "Failed to execute function");
1010                 return;
1011         }
1012
1013         ast_ari_response_no_content(response);
1014 }
1015
1016 static void ari_channels_handle_snoop_channel(
1017         const char *args_channel_id,
1018         const char *args_spy,
1019         const char *args_whisper,
1020         const char *args_app,
1021         const char *args_app_args,
1022         const char *args_snoop_id,
1023         struct ast_ari_response *response)
1024 {
1025         enum stasis_app_snoop_direction spy, whisper;
1026         RAII_VAR(struct ast_channel *, chan, NULL, ast_channel_cleanup);
1027         RAII_VAR(struct ast_channel *, snoop, NULL, ast_channel_cleanup);
1028         RAII_VAR(struct ast_channel_snapshot *, snapshot, NULL, ao2_cleanup);
1029
1030         ast_assert(response != NULL);
1031
1032         if (ast_strlen_zero(args_spy) || !strcmp(args_spy, "none")) {
1033                 spy = STASIS_SNOOP_DIRECTION_NONE;
1034         } else if (!strcmp(args_spy, "both")) {
1035                 spy = STASIS_SNOOP_DIRECTION_BOTH;
1036         } else if (!strcmp(args_spy, "out")) {
1037                 spy = STASIS_SNOOP_DIRECTION_OUT;
1038         } else if (!strcmp(args_spy, "in")) {
1039                 spy = STASIS_SNOOP_DIRECTION_IN;
1040         } else {
1041                 ast_ari_response_error(
1042                         response, 400, "Bad Request",
1043                         "Invalid direction specified for spy");
1044                 return;
1045         }
1046
1047         if (ast_strlen_zero(args_whisper) || !strcmp(args_whisper, "none")) {
1048                 whisper = STASIS_SNOOP_DIRECTION_NONE;
1049         } else if (!strcmp(args_whisper, "both")) {
1050                 whisper = STASIS_SNOOP_DIRECTION_BOTH;
1051         } else if (!strcmp(args_whisper, "out")) {
1052                 whisper = STASIS_SNOOP_DIRECTION_OUT;
1053         } else if (!strcmp(args_whisper, "in")) {
1054                 whisper = STASIS_SNOOP_DIRECTION_IN;
1055         } else {
1056                 ast_ari_response_error(
1057                         response, 400, "Bad Request",
1058                         "Invalid direction specified for whisper");
1059                 return;
1060         }
1061
1062         if (spy == STASIS_SNOOP_DIRECTION_NONE && whisper == STASIS_SNOOP_DIRECTION_NONE) {
1063                 ast_ari_response_error(
1064                         response, 400, "Bad Request",
1065                         "Direction must be specified for at least spy or whisper");
1066                 return;
1067         } else if (ast_strlen_zero(args_app)) {
1068                 ast_ari_response_error(
1069                         response, 400, "Bad Request",
1070                         "Application name is required");
1071                 return;
1072         }
1073
1074         chan = ast_channel_get_by_name(args_channel_id);
1075         if (chan == NULL) {
1076                 ast_ari_response_error(
1077                         response, 404, "Channel Not Found",
1078                         "Provided channel was not found");
1079                 return;
1080         }
1081
1082         snoop = stasis_app_control_snoop(chan, spy, whisper, args_app, args_app_args,
1083                 args_snoop_id);
1084         if (snoop == NULL) {
1085                 ast_ari_response_error(
1086                         response, 500, "Internal error",
1087                         "Snoop channel could not be created");
1088                 return;
1089         }
1090
1091         snapshot = ast_channel_snapshot_get_latest(ast_channel_uniqueid(snoop));
1092         ast_ari_response_ok(response, ast_channel_snapshot_to_json(snapshot, NULL));
1093 }
1094
1095 void ast_ari_channels_snoop_channel(struct ast_variable *headers,
1096         struct ast_ari_channels_snoop_channel_args *args,
1097         struct ast_ari_response *response)
1098 {
1099         ari_channels_handle_snoop_channel(
1100                 args->channel_id,
1101                 args->spy,
1102                 args->whisper,
1103                 args->app,
1104                 args->app_args,
1105                 args->snoop_id,
1106                 response);
1107 }
1108
1109 void ast_ari_channels_snoop_channel_with_id(struct ast_variable *headers,
1110         struct ast_ari_channels_snoop_channel_with_id_args *args,
1111         struct ast_ari_response *response)
1112 {
1113         ari_channels_handle_snoop_channel(
1114                 args->channel_id,
1115                 args->spy,
1116                 args->whisper,
1117                 args->app,
1118                 args->app_args,
1119                 args->snoop_id,
1120                 response);
1121 }