Asterisk - The Open Source Telephony Project GIT-master-a358458
resource_channels.c
Go to the documentation of this file.
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#include "asterisk/file.h"
33#include "asterisk/pbx.h"
34#include "asterisk/bridge.h"
35#include "asterisk/callerid.h"
36#include "asterisk/stasis_app.h"
41#include "asterisk/causes.h"
43#include "asterisk/core_local.h"
44#include "asterisk/dial.h"
46#include "asterisk/rtp_engine.h"
47#include "resource_channels.h"
48
49#include <limits.h>
50
51
52/*! \brief Return the corresponded hangup code of the given reason */
53static int convert_reason_to_hangup_code(const char* reason)
54{
55 if (!strcmp(reason, "normal")) {
56 return AST_CAUSE_NORMAL;
57 } else if (!strcmp(reason, "busy")) {
58 return AST_CAUSE_BUSY;
59 } else if (!strcmp(reason, "congestion")) {
61 } else if (!strcmp(reason, "no_answer")) {
62 return AST_CAUSE_NOANSWER;
63 } else if (!strcmp(reason, "timeout")) {
65 } else if (!strcmp(reason, "rejected")) {
67 } else if (!strcmp(reason, "unallocated")) {
69 } else if (!strcmp(reason, "normal_unspecified")) {
71 } else if (!strcmp(reason, "number_incomplete")) {
73 } else if (!strcmp(reason, "codec_mismatch")) {
75 } else if (!strcmp(reason, "interworking")) {
77 } else if (!strcmp(reason, "failure")) {
78 return AST_CAUSE_FAILURE;
79 } else if(!strcmp(reason, "answered_elsewhere")) {
81 }
82
83 return -1;
84}
85
86/*!
87 * \brief Ensure channel is in a state that allows operation to be performed.
88 *
89 * Since Asterisk 14, it has been possible for down channels, as well as unanswered
90 * outbound channels to enter Stasis. While some operations are fine to perform on
91 * such channels, operations that
92 *
93 * - Attempt to manipulate channel state
94 * - Attempt to play media
95 * - Attempt to control the channel's location in the dialplan
96 *
97 * are invalid. This function can be used to determine if the channel is in an
98 * appropriate state.
99 *
100 * \note When this function returns an error, the HTTP response is taken care of.
101 *
102 * \param control The app control
103 * \param response Response to fill in if there is an error
104 *
105 * \retval 0 Channel is in a valid state. Continue on!
106 * \retval non-zero Channel is in an invalid state. Bail!
107 */
108static int channel_state_invalid(struct stasis_app_control *control,
109 struct ast_ari_response *response)
110{
111 struct ast_channel_snapshot *snapshot;
112
113 snapshot = stasis_app_control_get_snapshot(control);
114 if (!snapshot) {
115 ast_ari_response_error(response, 404, "Not Found", "Channel not found");
116 return -1;
117 }
118
119 /* These channel states apply only to outbound channels:
120 * - Down: Channel has been created, and nothing else has been done
121 * - Reserved: For a PRI, an underlying B-channel is reserved,
122 * but the channel is not yet dialed
123 * - Ringing: The channel has been dialed.
124 *
125 * This does not affect inbound channels. Inbound channels, when they
126 * enter the dialplan, are in the "Ring" state. If they have already
127 * been answered, then they are in the "Up" state.
128 */
129 if (snapshot->state == AST_STATE_DOWN
130 || snapshot->state == AST_STATE_RESERVED
131 || snapshot->state == AST_STATE_RINGING) {
132 ast_ari_response_error(response, 412, "Precondition Failed",
133 "Channel in invalid state");
134 ao2_ref(snapshot, -1);
135
136 return -1;
137 }
138
139 ao2_ref(snapshot, -1);
140
141 return 0;
142}
143
144/*!
145 * \brief Finds the control object for a channel, filling the response with an
146 * error, if appropriate.
147 * \param[out] response Response to fill with an error if control is not found.
148 * \param channel_id ID of the channel to lookup.
149 * \return Channel control object.
150 * \retval NULL if control object does not exist.
151 */
153 struct ast_ari_response *response,
154 const char *channel_id)
155{
156 RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
157
158 ast_assert(response != NULL);
159
160 control = stasis_app_control_find_by_channel_id(channel_id);
161 if (control == NULL) {
162 /* Distinguish between 404 and 409 errors */
163 RAII_VAR(struct ast_channel *, chan, NULL, ao2_cleanup);
164 chan = ast_channel_get_by_name(channel_id);
165 if (chan == NULL) {
166 ast_ari_response_error(response, 404, "Not Found",
167 "Channel not found");
168 return NULL;
169 }
170
171 ast_ari_response_error(response, 409, "Conflict",
172 "Channel not in Stasis application");
173 return NULL;
174 }
175
176 ao2_ref(control, +1);
177 return control;
178}
179
181 struct ast_variable *headers,
183 struct ast_ari_response *response)
184{
185 RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
186 RAII_VAR(struct ast_channel_snapshot *, snapshot, NULL, ao2_cleanup);
187 int ipri;
188 const char *context;
189 const char *exten;
190
191 ast_assert(response != NULL);
192
193 control = find_control(response, args->channel_id);
194 if (control == NULL) {
195 return;
196 }
197
198 if (channel_state_invalid(control, response)) {
199 return;
200 }
201
202 snapshot = stasis_app_control_get_snapshot(control);
203 if (!snapshot) {
204 ast_ari_response_error(response, 404, "Not Found", "Channel not found");
205 return;
206 }
207
208 if (ast_strlen_zero(args->context)) {
209 context = snapshot->dialplan->context;
210 exten = S_OR(args->extension, snapshot->dialplan->exten);
211 } else {
212 context = args->context;
213 exten = S_OR(args->extension, "s");
214 }
215
216 if (!ast_strlen_zero(args->label)) {
217 /* A label was provided in the request, use that */
218
219 if (sscanf(args->label, "%30d", &ipri) != 1) {
220 ipri = ast_findlabel_extension(NULL, context, exten, args->label, NULL);
221 if (ipri == -1) {
222 ast_log(AST_LOG_ERROR, "Requested label: %s can not be found in context: %s\n", args->label, context);
223 ast_ari_response_error(response, 404, "Not Found", "Requested label can not be found");
224 return;
225 }
226 } else {
227 ast_debug(3, "Numeric value provided for label, jumping to that priority\n");
228 }
229
230 if (ipri == 0) {
231 ast_log(AST_LOG_ERROR, "Invalid priority label '%s' specified for extension %s in context: %s\n",
232 args->label, exten, context);
233 ast_ari_response_error(response, 400, "Bad Request", "Requested priority is illegal");
234 return;
235 }
236
237 } else if (args->priority) {
238 /* No label provided, use provided priority */
239 ipri = args->priority;
240 } else if (ast_strlen_zero(args->context) && ast_strlen_zero(args->extension)) {
241 /* Special case. No exten, context, or priority provided, then move on to the next priority */
242 ipri = snapshot->dialplan->priority + 1;
243 } else {
244 ipri = 1;
245 }
246
247
248 if (stasis_app_control_continue(control, context, exten, ipri)) {
250 return;
251 }
252
254}
255
258 struct ast_ari_response *response)
259{
260 RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
261
262 control = find_control(response, args->channel_id);
263 if (!control) {
264 return;
265 }
266
267 if (stasis_app_control_move(control, args->app, args->app_args)) {
268 ast_ari_response_error(response, 500, "Internal Server Error",
269 "Failed to switch Stasis applications");
270 return;
271 }
272
274}
275
278 struct ast_ari_response *response)
279{
280 RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
281 RAII_VAR(struct ast_channel_snapshot *, chan_snapshot, NULL, ao2_cleanup);
282 char *tech;
283 char *resource;
284 int tech_len;
285
286 control = find_control(response, args->channel_id);
287 if (!control) {
288 return;
289 }
290
291 if (channel_state_invalid(control, response)) {
292 return;
293 }
294
295 if (ast_strlen_zero(args->endpoint)) {
296 ast_ari_response_error(response, 400, "Not Found",
297 "Required parameter 'endpoint' not provided.");
298 return;
299 }
300
301 tech = ast_strdupa(args->endpoint);
302 if (!(resource = strchr(tech, '/')) || !(tech_len = resource - tech)) {
303 ast_ari_response_error(response, 422, "Unprocessable Entity",
304 "Endpoint parameter '%s' does not contain tech/resource", args->endpoint);
305 return;
306 }
307
308 *resource++ = '\0';
309 if (ast_strlen_zero(resource)) {
310 ast_ari_response_error(response, 422, "Unprocessable Entity",
311 "No resource provided in endpoint parameter '%s'", args->endpoint);
312 return;
313 }
314
315 chan_snapshot = ast_channel_snapshot_get_latest(args->channel_id);
316 if (!chan_snapshot) {
317 ast_ari_response_error(response, 500, "Internal Server Error",
318 "Unable to find channel snapshot for '%s'", args->channel_id);
319 return;
320 }
321
322 if (strncasecmp(chan_snapshot->base->type, tech, tech_len)) {
323 ast_ari_response_error(response, 422, "Unprocessable Entity",
324 "Endpoint technology '%s' does not match channel technology '%s'",
325 tech, chan_snapshot->base->type);
326 return;
327 }
328
329 if (stasis_app_control_redirect(control, resource)) {
330 ast_ari_response_error(response, 500, "Internal Server Error",
331 "Failed to redirect channel");
332 return;
333 }
334
336}
337
340 struct ast_ari_response *response)
341{
342 RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
343
344 control = find_control(response, args->channel_id);
345 if (control == NULL) {
346 return;
347 }
348
349 if (channel_state_invalid(control, response)) {
350 return;
351 }
352
353 if (stasis_app_control_answer(control) != 0) {
355 response, 500, "Internal Server Error",
356 "Failed to answer channel");
357 return;
358 }
359
361}
362
365 struct ast_ari_response *response)
366{
367 RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
368
369 control = find_control(response, args->channel_id);
370 if (control == NULL) {
371 return;
372 }
373
374 if (channel_state_invalid(control, response)) {
375 return;
376 }
377
379
381}
382
385 struct ast_ari_response *response)
386{
387 RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
388
389 control = find_control(response, args->channel_id);
390 if (control == NULL) {
391 return;
392 }
393
394 if (channel_state_invalid(control, response)) {
395 return;
396 }
397
399
401}
402
405 struct ast_ari_response *response)
406{
407 RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
408 unsigned int direction = 0;
409 enum ast_frame_type frametype = AST_FRAME_VOICE;
410
411 control = find_control(response, args->channel_id);
412 if (control == NULL) {
413 return;
414 }
415
416 if (channel_state_invalid(control, response)) {
417 return;
418 }
419
420 if (ast_strlen_zero(args->direction)) {
422 response, 400, "Bad Request",
423 "Direction is required");
424 return;
425 }
426
427 if (!strcmp(args->direction, "in")) {
429 } else if (!strcmp(args->direction, "out")) {
431 } else if (!strcmp(args->direction, "both")) {
433 } else {
435 response, 400, "Bad Request",
436 "Invalid direction specified");
437 return;
438 }
439
440 stasis_app_control_mute(control, direction, frametype);
441
443}
444
447 struct ast_ari_response *response)
448{
449 RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
450 unsigned int direction = 0;
451 enum ast_frame_type frametype = AST_FRAME_VOICE;
452
453 control = find_control(response, args->channel_id);
454 if (control == NULL) {
455 return;
456 }
457
458 if (channel_state_invalid(control, response)) {
459 return;
460 }
461
462 if (ast_strlen_zero(args->direction)) {
464 response, 400, "Bad Request",
465 "Direction is required");
466 return;
467 }
468
469 if (!strcmp(args->direction, "in")) {
471 } else if (!strcmp(args->direction, "out")) {
473 } else if (!strcmp(args->direction, "both")) {
475 } else {
477 response, 400, "Bad Request",
478 "Invalid direction specified");
479 return;
480 }
481
482 stasis_app_control_unmute(control, direction, frametype);
483
485}
486
489 struct ast_ari_response *response)
490{
491 RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
492
493 control = find_control(response, args->channel_id);
494 if (control == NULL) {
495 return;
496 }
497
498 if (channel_state_invalid(control, response)) {
499 return;
500 }
501
502 if (ast_strlen_zero(args->dtmf)) {
504 response, 400, "Bad Request",
505 "DTMF is required");
506 return;
507 }
508
509 stasis_app_control_dtmf(control, args->dtmf, args->before, args->between, args->duration, args->after);
510
512}
513
516 struct ast_ari_response *response)
517{
518 RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
519
520 control = find_control(response, args->channel_id);
521 if (control == NULL) {
522 /* Response filled in by find_control */
523 return;
524 }
525
526 if (channel_state_invalid(control, response)) {
527 return;
528 }
529
531
533}
534
537 struct ast_ari_response *response)
538{
539 RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
540
541 control = find_control(response, args->channel_id);
542 if (control == NULL) {
543 /* Response filled in by find_control */
544 return;
545 }
546
547 if (channel_state_invalid(control, response)) {
548 return;
549 }
550
552
554}
555
558 struct ast_ari_response *response)
559{
560 RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
561
562 control = find_control(response, args->channel_id);
563 if (control == NULL) {
564 /* Response filled in by find_control */
565 return;
566 }
567
568 if (channel_state_invalid(control, response)) {
569 return;
570 }
571
572 stasis_app_control_moh_start(control, args->moh_class);
574}
575
578 struct ast_ari_response *response)
579{
580 RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
581
582 control = find_control(response, args->channel_id);
583 if (control == NULL) {
584 /* Response filled in by find_control */
585 return;
586 }
587
588 if (channel_state_invalid(control, response)) {
589 return;
590 }
591
594}
595
598 struct ast_ari_response *response)
599{
600 RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
601
602 control = find_control(response, args->channel_id);
603 if (control == NULL) {
604 /* Response filled in by find_control */
605 return;
606 }
607
608 if (channel_state_invalid(control, response)) {
609 return;
610 }
611
614}
615
618 struct ast_ari_response *response)
619{
620 RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
621
622 control = find_control(response, args->channel_id);
623 if (control == NULL) {
624 /* Response filled in by find_control */
625 return;
626 }
627
628 if (channel_state_invalid(control, response)) {
629 return;
630 }
631
634}
635
637 const char *args_channel_id,
638 const char **args_media,
639 size_t args_media_count,
640 const char *args_lang,
641 int args_offsetms,
642 int args_skipms,
643 const char *args_playback_id,
644 struct ast_ari_response *response)
645{
646 RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
647 RAII_VAR(struct ast_channel_snapshot *, snapshot, NULL, ao2_cleanup);
648 RAII_VAR(struct stasis_app_playback *, playback, NULL, ao2_cleanup);
649 RAII_VAR(char *, playback_url, NULL, ast_free);
650 struct ast_json *json;
651 const char *language;
652
653 ast_assert(response != NULL);
654
655 control = find_control(response, args_channel_id);
656 if (control == NULL) {
657 /* Response filled in by find_control */
658 return;
659 }
660
661 if (channel_state_invalid(control, response)) {
662 return;
663 }
664
665 snapshot = stasis_app_control_get_snapshot(control);
666 if (!snapshot) {
668 response, 404, "Not Found",
669 "Channel not found");
670 return;
671 }
672
673 if (args_skipms < 0) {
675 response, 400, "Bad Request",
676 "skipms cannot be negative");
677 return;
678 }
679
680 if (args_offsetms < 0) {
682 response, 400, "Bad Request",
683 "offsetms cannot be negative");
684 return;
685 }
686
687 language = S_OR(args_lang, snapshot->base->language);
688
689 playback = stasis_app_control_play_uri(control, args_media, args_media_count, language,
690 args_channel_id, STASIS_PLAYBACK_TARGET_CHANNEL, args_skipms, args_offsetms, args_playback_id);
691 if (!playback) {
693 response, 500, "Internal Server Error",
694 "Failed to queue media for playback");
695 return;
696 }
697
698 if (ast_asprintf(&playback_url, "/playbacks/%s",
699 stasis_app_playback_get_id(playback)) == -1) {
700 playback_url = NULL;
702 response, 500, "Internal Server Error",
703 "Out of memory");
704 return;
705 }
706
707 json = stasis_app_playback_to_json(playback);
708 if (!json) {
710 response, 500, "Internal Server Error",
711 "Out of memory");
712 return;
713 }
714
715 ast_ari_response_created(response, playback_url, json);
716}
717
720 struct ast_ari_response *response)
721{
723 args->channel_id,
724 args->media,
725 args->media_count,
726 args->lang,
727 args->offsetms,
728 args->skipms,
729 args->playback_id,
730 response);
731}
732
735 struct ast_ari_response *response)
736{
738 args->channel_id,
739 args->media,
740 args->media_count,
741 args->lang,
742 args->offsetms,
743 args->skipms,
744 args->playback_id,
745 response);
746}
747
750 struct ast_ari_response *response)
751{
752 RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
753 RAII_VAR(struct stasis_app_recording *, recording, NULL, ao2_cleanup);
754 RAII_VAR(char *, recording_url, NULL, ast_free);
755 struct ast_json *json;
758 RAII_VAR(char *, uri_encoded_name, NULL, ast_free);
759 size_t uri_name_maxlen;
760
761 ast_assert(response != NULL);
762
763 if (args->max_duration_seconds < 0) {
765 response, 400, "Bad Request",
766 "max_duration_seconds cannot be negative");
767 return;
768 }
769
770 if (args->max_silence_seconds < 0) {
772 response, 400, "Bad Request",
773 "max_silence_seconds cannot be negative");
774 return;
775 }
776
777 control = find_control(response, args->channel_id);
778 if (control == NULL) {
779 /* Response filled in by find_control */
780 return;
781 }
782
784 if (options == NULL) {
786 response, 500, "Internal Server Error",
787 "Out of memory");
788 }
789 ast_string_field_build(options, target, "channel:%s", args->channel_id);
790 options->max_silence_seconds = args->max_silence_seconds;
791 options->max_duration_seconds = args->max_duration_seconds;
792 options->terminate_on =
794 options->if_exists =
796 options->beep = args->beep;
797
798 if (options->terminate_on == STASIS_APP_RECORDING_TERMINATE_INVALID) {
800 response, 400, "Bad Request",
801 "terminateOn invalid");
802 return;
803 }
804
805 if (options->if_exists == AST_RECORD_IF_EXISTS_ERROR) {
807 response, 400, "Bad Request",
808 "ifExists invalid");
809 return;
810 }
811
812 if (!ast_get_format_for_file_ext(options->format)) {
814 response, 422, "Unprocessable Entity",
815 "specified format is unknown on this system");
816 return;
817 }
818
819 recording = stasis_app_control_record(control, options);
820 if (recording == NULL) {
821 switch(errno) {
822 case EINVAL:
823 /* While the arguments are invalid, we should have
824 * caught them prior to calling record.
825 */
827 response, 500, "Internal Server Error",
828 "Error parsing request");
829 break;
830 case EEXIST:
831 ast_ari_response_error(response, 409, "Conflict",
832 "Recording '%s' already exists and can not be overwritten",
833 args->name);
834 break;
835 case ENOMEM:
837 response, 500, "Internal Server Error",
838 "Out of memory");
839 break;
840 case EPERM:
842 response, 400, "Bad Request",
843 "Recording name invalid");
844 break;
845 default:
847 "Unrecognized recording error: %s\n",
848 strerror(errno));
850 response, 500, "Internal Server Error",
851 "Internal Server Error");
852 break;
853 }
854 return;
855 }
856
857 uri_name_maxlen = strlen(args->name) * 3;
858 uri_encoded_name = ast_malloc(uri_name_maxlen);
859 if (!uri_encoded_name) {
861 response, 500, "Internal Server Error",
862 "Out of memory");
863 return;
864 }
865 ast_uri_encode(args->name, uri_encoded_name, uri_name_maxlen,
867
868 if (ast_asprintf(&recording_url, "/recordings/live/%s",
869 uri_encoded_name) == -1) {
870 recording_url = NULL;
872 response, 500, "Internal Server Error",
873 "Out of memory");
874 return;
875 }
876
877 json = stasis_app_recording_to_json(recording);
878 if (!json) {
880 response, 500, "Internal Server Error",
881 "Out of memory");
882 return;
883 }
884
885 ast_ari_response_created(response, recording_url, json);
886}
887
890 struct ast_ari_response *response)
891{
892 struct ast_channel_snapshot *snapshot;
893
894 snapshot = ast_channel_snapshot_get_latest(args->channel_id);
895 if (!snapshot) {
897 response, 404, "Not Found",
898 "Channel not found");
899 return;
900 }
901
902 ast_ari_response_ok(response,
904 ao2_ref(snapshot, -1);
905}
906
909 struct ast_ari_response *response)
910{
911 RAII_VAR(struct ast_channel *, chan, NULL, ao2_cleanup);
912 int cause;
913
914 chan = ast_channel_get_by_name(args->channel_id);
915 if (chan == NULL) {
917 response, 404, "Not Found",
918 "Channel not found");
919 return;
920 }
921
922 if (!ast_strlen_zero(args->reason) && !ast_strlen_zero(args->reason_code)) {
923 ast_ari_response_error(response, 400, "Bad Request",
924 "The reason and reason_code can't both be specified");
925 return;
926 }
927
928 if (!ast_strlen_zero(args->reason_code)) {
929 /* reason_code allows any hangup code */
930 if (sscanf(args->reason_code, "%30d", &cause) != 1) {
932 response, 400, "Invalid Reason Code",
933 "Invalid reason for hangup reason code provided");
934 return;
935 }
936 } else if (!ast_strlen_zero(args->reason)) {
937 /* reason allows only listed hangup reason */
938 cause = convert_reason_to_hangup_code(args->reason);
939 if (cause == -1) {
941 response, 400, "Invalid Reason",
942 "Invalid reason for hangup reason provided");
943 return;
944 }
945 } else {
946 /* not specified. set default hangup */
947 cause = AST_CAUSE_NORMAL;
948 }
949
950 ast_channel_hangupcause_set(chan, cause);
952
954}
955
958 struct ast_ari_response *response)
959{
960 RAII_VAR(struct ao2_container *, snapshots, NULL, ao2_cleanup);
961 RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
962 struct ao2_iterator i;
963 void *obj;
965
966 snapshots = ast_channel_cache_all();
967
968 json = ast_json_array_create();
969 if (!json) {
971 return;
972 }
973
974 i = ao2_iterator_init(snapshots, 0);
975 while ((obj = ao2_iterator_next(&i))) {
976 struct ast_channel_snapshot *snapshot = obj;
977 int r;
978
979 if (sanitize && sanitize->channel_snapshot
980 && sanitize->channel_snapshot(snapshot)) {
981 ao2_ref(snapshot, -1);
982 continue;
983 }
984
986 json, ast_channel_snapshot_to_json(snapshot, NULL));
987 if (r != 0) {
990 ao2_ref(snapshot, -1);
991 return;
992 }
993 ao2_ref(snapshot, -1);
994 }
996
997 ast_ari_response_ok(response, ast_json_ref(json));
998}
999
1000/*! \brief Structure used for origination */
1002 /*! \brief Dialplan context */
1004 /*! \brief Dialplan extension */
1006 /*! \brief Dialplan priority */
1008 /*! \brief Application data to pass to Stasis application */
1009 char appdata[0];
1010};
1011
1012/*! \brief Thread which dials and executes upon answer */
1013static void *ari_originate_dial(void *data)
1014{
1015 struct ast_dial *dial = data;
1016 struct ari_origination *origination = ast_dial_get_user_data(dial);
1017 enum ast_dial_result res;
1018
1019 res = ast_dial_run(dial, NULL, 0);
1020 if (res != AST_DIAL_RESULT_ANSWERED) {
1021 goto end;
1022 }
1023
1024 if (!ast_strlen_zero(origination->appdata)) {
1025 struct ast_app *app = pbx_findapp("Stasis");
1026
1027 if (app) {
1028 ast_verb(4, "Launching Stasis(%s) on %s\n", origination->appdata,
1030 pbx_exec(ast_dial_answered(dial), app, origination->appdata);
1031 } else {
1032 ast_log(LOG_WARNING, "No such application 'Stasis'\n");
1033 }
1034 } else {
1035 struct ast_channel *answered = ast_dial_answered(dial);
1036
1037 if (!ast_strlen_zero(origination->context)) {
1038 ast_channel_context_set(answered, origination->context);
1039 }
1040
1041 if (!ast_strlen_zero(origination->exten)) {
1042 ast_channel_exten_set(answered, origination->exten);
1043 }
1044
1045 if (origination->priority > 0) {
1046 ast_channel_priority_set(answered, origination->priority);
1047 }
1048
1049 if (ast_pbx_run(answered)) {
1050 ast_log(LOG_ERROR, "Failed to start PBX on %s\n", ast_channel_name(answered));
1051 } else {
1052 /* PBX will have taken care of hanging up, so we steal the answered channel so dial doesn't do it */
1054 }
1055 }
1056
1057end:
1058 ast_dial_destroy(dial);
1059 ast_free(origination);
1060 return NULL;
1061}
1062
1063static struct ast_channel *ari_channels_handle_originate_with_id(const char *args_endpoint,
1064 const char *args_extension,
1065 const char *args_context,
1066 long args_priority,
1067 const char *args_label,
1068 const char *args_app,
1069 const char *args_app_args,
1070 const char *args_caller_id,
1071 int args_timeout,
1072 struct ast_variable *variables,
1073 const char *args_channel_id,
1074 const char *args_other_channel_id,
1075 const char *args_originator,
1076 const char *args_formats,
1077 struct ast_ari_response *response)
1078{
1079 char *dialtech;
1080 char *dialdevice = NULL;
1081 struct ast_dial *dial;
1082 char *caller_id = NULL;
1083 char *cid_num = NULL;
1084 char *cid_name = NULL;
1085 char *stuff;
1086 struct ast_channel *other = NULL;
1087 struct ast_channel *chan = NULL;
1089 struct ast_assigned_ids assignedids = {
1090 .uniqueid = args_channel_id,
1091 .uniqueid2 = args_other_channel_id,
1092 };
1093 struct ari_origination *origination;
1094 pthread_t thread;
1095 struct ast_format_cap *format_cap = NULL;
1096
1097 if ((assignedids.uniqueid && AST_MAX_PUBLIC_UNIQUEID < strlen(assignedids.uniqueid))
1098 || (assignedids.uniqueid2 && AST_MAX_PUBLIC_UNIQUEID < strlen(assignedids.uniqueid2))) {
1099 ast_ari_response_error(response, 400, "Bad Request",
1100 "Uniqueid length exceeds maximum of %d", AST_MAX_PUBLIC_UNIQUEID);
1101 return NULL;
1102 }
1103
1104 if (ast_strlen_zero(args_endpoint)) {
1105 ast_ari_response_error(response, 400, "Bad Request",
1106 "Endpoint must be specified");
1107 return NULL;
1108 }
1109
1110 if (!ast_strlen_zero(args_originator) && !ast_strlen_zero(args_formats)) {
1111 ast_ari_response_error(response, 400, "Bad Request",
1112 "Originator and formats can't both be specified");
1113 return NULL;
1114 }
1115
1116 dialtech = ast_strdupa(args_endpoint);
1117 if ((stuff = strchr(dialtech, '/'))) {
1118 *stuff++ = '\0';
1119 dialdevice = stuff;
1120 }
1121
1122 if (ast_strlen_zero(dialtech) || ast_strlen_zero(dialdevice)) {
1123 ast_ari_response_error(response, 400, "Bad Request",
1124 "Invalid endpoint specified");
1125 return NULL;
1126 }
1127
1128 if (!ast_strlen_zero(args_app)) {
1129 RAII_VAR(struct ast_str *, appdata, ast_str_create(64), ast_free);
1130
1131 if (!appdata) {
1133 return NULL;
1134 }
1135
1136 ast_str_set(&appdata, 0, "%s", args_app);
1137 if (!ast_strlen_zero(args_app_args)) {
1138 ast_str_append(&appdata, 0, ",%s", args_app_args);
1139 }
1140
1141 origination = ast_calloc(1, sizeof(*origination) + ast_str_size(appdata) + 1);
1142 if (!origination) {
1144 return NULL;
1145 }
1146
1147 strcpy(origination->appdata, ast_str_buffer(appdata));
1148 } else if (!ast_strlen_zero(args_extension)) {
1149 origination = ast_calloc(1, sizeof(*origination) + 1);
1150 if (!origination) {
1152 return NULL;
1153 }
1154
1155 ast_copy_string(origination->context, S_OR(args_context, "default"), sizeof(origination->context));
1156 ast_copy_string(origination->exten, args_extension, sizeof(origination->exten));
1157
1158 if (!ast_strlen_zero(args_label)) {
1159 /* A label was provided in the request, use that */
1160 int ipri = 1;
1161 if (sscanf(args_label, "%30d", &ipri) != 1) {
1162 ipri = ast_findlabel_extension(chan, origination->context, origination->exten, args_label, args_caller_id);
1163
1164 if (ipri == -1) {
1165 ast_log(AST_LOG_ERROR, "Requested label: %s can not be found in context: %s\n", args_label, args_context);
1166 ast_ari_response_error(response, 404, "Not Found", "Requested label can not be found");
1167 return NULL;
1168 }
1169 } else {
1170 ast_debug(3, "Numeric value provided for label, jumping to that priority\n");
1171 }
1172
1173 if (ipri == 0) {
1174 ast_log(AST_LOG_ERROR, "Invalid priority label '%s' specified for extension %s in context: %s\n",
1175 args_label, args_extension, args_context);
1176 ast_ari_response_error(response, 400, "Bad Request", "Requested priority is illegal");
1177 return NULL;
1178 }
1179
1180 /* Our priority was provided by a label */
1181 origination->priority = ipri;
1182 } else {
1183 /* No label provided, use provided priority */
1184 origination->priority = args_priority ? args_priority : 1;
1185 }
1186
1187 origination->appdata[0] = '\0';
1188 } else {
1189 ast_ari_response_error(response, 400, "Bad Request",
1190 "Application or extension must be specified");
1191 return NULL;
1192 }
1193
1194 dial = ast_dial_create();
1195 if (!dial) {
1197 ast_free(origination);
1198 return NULL;
1199 }
1200 ast_dial_set_user_data(dial, origination);
1201
1202 if (ast_dial_append(dial, dialtech, dialdevice, &assignedids)) {
1204 ast_dial_destroy(dial);
1205 ast_free(origination);
1206 return NULL;
1207 }
1208
1209 if (args_timeout > 0) {
1210 ast_dial_set_global_timeout(dial, args_timeout * 1000);
1211 } else if (args_timeout == -1) {
1213 } else {
1214 ast_dial_set_global_timeout(dial, 30000);
1215 }
1216
1217 if (!ast_strlen_zero(args_caller_id)) {
1218 caller_id = ast_strdupa(args_caller_id);
1219 ast_callerid_parse(caller_id, &cid_name, &cid_num);
1220
1221 if (ast_is_shrinkable_phonenumber(cid_num)) {
1222 ast_shrink_phone_number(cid_num);
1223 }
1224 }
1225
1226 if (!ast_strlen_zero(args_originator)) {
1227 other = ast_channel_get_by_name(args_originator);
1228 if (!other) {
1230 response, 400, "Bad Request",
1231 "Provided originator channel was not found");
1232 ast_dial_destroy(dial);
1233 ast_free(origination);
1234 return NULL;
1235 }
1236 }
1237
1238 if (!ast_strlen_zero(args_formats)) {
1239 char *format_name;
1240 char *formats_copy = ast_strdupa(args_formats);
1241
1244 ast_dial_destroy(dial);
1245 ast_free(origination);
1246 ast_channel_cleanup(other);
1247 return NULL;
1248 }
1249
1250 while ((format_name = ast_strip(strsep(&formats_copy, ",")))) {
1251 struct ast_format *fmt = ast_format_cache_get(format_name);
1252
1253 if (!fmt || ast_format_cap_append(format_cap, fmt, 0)) {
1254 if (!fmt) {
1256 response, 400, "Bad Request",
1257 "Provided format (%s) was not found", format_name);
1258 } else {
1260 }
1261 ast_dial_destroy(dial);
1262 ast_free(origination);
1263 ast_channel_cleanup(other);
1264 ao2_ref(format_cap, -1);
1265 ao2_cleanup(fmt);
1266 return NULL;
1267 }
1268 ao2_ref(fmt, -1);
1269 }
1270 }
1271
1272 if (ast_dial_prerun(dial, other, format_cap)) {
1274 ast_ari_response_error(response, 409, "Conflict",
1275 "Channel with given unique ID already exists");
1276 } else {
1278 }
1279 ast_dial_destroy(dial);
1280 ast_free(origination);
1281 ast_channel_cleanup(other);
1282 return NULL;
1283 }
1284
1285 ast_channel_cleanup(other);
1286 ao2_cleanup(format_cap);
1287
1288 chan = ast_dial_get_channel(dial, 0);
1289 if (!chan) {
1291 ast_dial_destroy(dial);
1292 ast_free(origination);
1293 return NULL;
1294 }
1295
1296 if (!ast_strlen_zero(cid_num) || !ast_strlen_zero(cid_name)) {
1298
1299 /*
1300 * It seems strange to set the CallerID on an outgoing call leg
1301 * to whom we are calling, but this function's callers are doing
1302 * various Originate methods. This call leg goes to the local
1303 * user. Once the called party answers, the dialplan needs to
1304 * be able to access the CallerID from the CALLERID function as
1305 * if the called party had placed this call.
1306 */
1307 ast_set_callerid(chan, cid_num, cid_name, cid_num);
1308
1310 if (!ast_strlen_zero(cid_num)) {
1311 connected.id.number.valid = 1;
1312 connected.id.number.str = (char *) cid_num;
1314 }
1315 if (!ast_strlen_zero(cid_name)) {
1316 connected.id.name.valid = 1;
1317 connected.id.name.str = (char *) cid_name;
1319 }
1321 }
1322
1323 ast_channel_lock(chan);
1324 if (variables) {
1325 ast_set_variables(chan, variables);
1326 }
1328
1329 if (!ast_strlen_zero(args_app)) {
1330 struct ast_channel *local_peer;
1331
1332 stasis_app_subscribe_channel(args_app, chan);
1333
1334 /* Subscribe to the Local channel peer also. */
1335 local_peer = ast_local_get_peer(chan);
1336 if (local_peer) {
1337 stasis_app_subscribe_channel(args_app, local_peer);
1338 ast_channel_unref(local_peer);
1339 }
1340 }
1341
1343 ast_channel_unlock(chan);
1344
1345 /* Before starting the async dial bump the ref in case the dial quickly goes away and takes
1346 * the reference with it
1347 */
1348 ast_channel_ref(chan);
1349
1352 ast_dial_destroy(dial);
1353 ast_free(origination);
1354 } else {
1356 }
1357
1358 return chan;
1359}
1360
1361/*!
1362 * \internal
1363 * \brief Convert a \c ast_json list of key/value pair tuples into a \c ast_variable list
1364 * \since 13.3.0
1365 *
1366 * \param[out] response HTTP response if error
1367 * \param json_variables The JSON blob containing the variable
1368 * \param[out] variables An out reference to the variables to populate.
1369 *
1370 * \retval 0 on success.
1371 * \retval -1 on error.
1372 */
1373static int json_to_ast_variables(struct ast_ari_response *response, struct ast_json *json_variables, struct ast_variable **variables)
1374{
1376
1377 res = ast_json_to_ast_variables(json_variables, variables);
1378 switch (res) {
1380 return 0;
1382 ast_ari_response_error(response, 400, "Bad Request",
1383 "Only string values in the 'variables' object allowed");
1384 break;
1387 break;
1388 }
1389 ast_log(AST_LOG_ERROR, "Unable to convert 'variables' in JSON body to channel variables\n");
1390
1391 return -1;
1392}
1393
1396 struct ast_ari_response *response)
1397{
1398 struct ast_variable *variables = NULL;
1399 struct ast_channel *chan;
1400
1401 /* Parse any query parameters out of the body parameter */
1402 if (args->variables) {
1403 struct ast_json *json_variables;
1404
1406 json_variables = ast_json_object_get(args->variables, "variables");
1407 if (json_variables
1408 && json_to_ast_variables(response, json_variables, &variables)) {
1409 return;
1410 }
1411 }
1412
1414 args->endpoint,
1415 args->extension,
1416 args->context,
1417 args->priority,
1418 args->label,
1419 args->app,
1420 args->app_args,
1421 args->caller_id,
1422 args->timeout,
1423 variables,
1424 args->channel_id,
1425 args->other_channel_id,
1426 args->originator,
1427 args->formats,
1428 response);
1429 ast_channel_cleanup(chan);
1430 ast_variables_destroy(variables);
1431}
1432
1435 struct ast_ari_response *response)
1436{
1437 struct ast_variable *variables = NULL;
1438 struct ast_channel *chan;
1439
1440 /* Parse any query parameters out of the body parameter */
1441 if (args->variables) {
1442 struct ast_json *json_variables;
1443
1445 json_variables = ast_json_object_get(args->variables, "variables");
1446 if (json_variables
1447 && json_to_ast_variables(response, json_variables, &variables)) {
1448 return;
1449 }
1450 }
1451
1453 args->endpoint,
1454 args->extension,
1455 args->context,
1456 args->priority,
1457 args->label,
1458 args->app,
1459 args->app_args,
1460 args->caller_id,
1461 args->timeout,
1462 variables,
1463 args->channel_id,
1464 args->other_channel_id,
1465 args->originator,
1466 args->formats,
1467 response);
1468 ast_channel_cleanup(chan);
1469 ast_variables_destroy(variables);
1470}
1471
1474 struct ast_ari_response *response)
1475{
1476 RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
1477 RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
1478 RAII_VAR(struct ast_str *, value, ast_str_create(32), ast_free);
1479 RAII_VAR(struct ast_channel *, channel, NULL, ast_channel_cleanup);
1480
1481 ast_assert(response != NULL);
1482
1483 if (!value) {
1485 return;
1486 }
1487
1488 if (ast_strlen_zero(args->variable)) {
1490 response, 400, "Bad Request",
1491 "Variable name is required");
1492 return;
1493 }
1494
1495 if (ast_strlen_zero(args->channel_id)) {
1497 response, 400, "Bad Request",
1498 "Channel ID is required");
1499 return;
1500 }
1501
1502 channel = ast_channel_get_by_name(args->channel_id);
1503 if (!channel) {
1505 response, 404, "Channel Not Found",
1506 "Provided channel was not found");
1507 return;
1508 }
1509
1510 /* You may be tempted to lock the channel you're about to read from. You
1511 * would be wrong. Some dialplan functions put the channel into
1512 * autoservice, which deadlocks if the channel is already locked.
1513 * ast_str_retrieve_variable() does its own locking, and the dialplan
1514 * functions need to as well. We should be fine without the lock.
1515 */
1516
1517 if (args->variable[strlen(args->variable) - 1] == ')') {
1518 if (ast_func_read2(channel, args->variable, &value, 0)) {
1520 response, 500, "Error With Function",
1521 "Unable to read provided function");
1522 return;
1523 }
1524 } else {
1525 if (!ast_str_retrieve_variable(&value, 0, channel, NULL, args->variable)) {
1527 response, 404, "Variable Not Found",
1528 "Provided variable was not found");
1529 return;
1530 }
1531 }
1532
1533 if (!(json = ast_json_pack("{s: s}", "value", S_OR(ast_str_buffer(value), "")))) {
1535 return;
1536 }
1537
1538 ast_ari_response_ok(response, ast_json_ref(json));
1539}
1540
1543 struct ast_ari_response *response)
1544{
1545 RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
1546
1547 ast_assert(response != NULL);
1548
1549 if (ast_strlen_zero(args->variable)) {
1551 response, 400, "Bad Request",
1552 "Variable name is required");
1553 return;
1554 }
1555
1556 control = find_control(response, args->channel_id);
1557 if (control == NULL) {
1558 /* response filled in by find_control */
1559 return;
1560 }
1561
1562 if (stasis_app_control_set_channel_var(control, args->variable, args->value)) {
1564 response, 400, "Bad Request",
1565 "Failed to execute function");
1566 return;
1567 }
1568
1570}
1571
1573 const char *args_channel_id,
1574 const char *args_spy,
1575 const char *args_whisper,
1576 const char *args_app,
1577 const char *args_app_args,
1578 const char *args_snoop_id,
1579 struct ast_ari_response *response)
1580{
1581 enum stasis_app_snoop_direction spy, whisper;
1582 RAII_VAR(struct ast_channel *, chan, NULL, ast_channel_cleanup);
1583 RAII_VAR(struct ast_channel *, snoop, NULL, ast_channel_cleanup);
1584 RAII_VAR(struct ast_channel_snapshot *, snapshot, NULL, ao2_cleanup);
1585
1586 ast_assert(response != NULL);
1587
1588 if (ast_strlen_zero(args_spy) || !strcmp(args_spy, "none")) {
1590 } else if (!strcmp(args_spy, "both")) {
1592 } else if (!strcmp(args_spy, "out")) {
1594 } else if (!strcmp(args_spy, "in")) {
1596 } else {
1598 response, 400, "Bad Request",
1599 "Invalid direction specified for spy");
1600 return;
1601 }
1602
1603 if (ast_strlen_zero(args_whisper) || !strcmp(args_whisper, "none")) {
1605 } else if (!strcmp(args_whisper, "both")) {
1607 } else if (!strcmp(args_whisper, "out")) {
1609 } else if (!strcmp(args_whisper, "in")) {
1610 whisper = STASIS_SNOOP_DIRECTION_IN;
1611 } else {
1613 response, 400, "Bad Request",
1614 "Invalid direction specified for whisper");
1615 return;
1616 }
1617
1620 response, 400, "Bad Request",
1621 "Direction must be specified for at least spy or whisper");
1622 return;
1623 } else if (ast_strlen_zero(args_app)) {
1625 response, 400, "Bad Request",
1626 "Application name is required");
1627 return;
1628 }
1629
1630 chan = ast_channel_get_by_name(args_channel_id);
1631 if (chan == NULL) {
1633 response, 404, "Channel Not Found",
1634 "Provided channel was not found");
1635 return;
1636 }
1637
1638 snoop = stasis_app_control_snoop(chan, spy, whisper, args_app, args_app_args,
1639 args_snoop_id);
1640 if (snoop == NULL) {
1642 response, 500, "Internal error",
1643 "Snoop channel could not be created");
1644 return;
1645 }
1646
1649}
1650
1653 struct ast_ari_response *response)
1654{
1656 args->channel_id,
1657 args->spy,
1658 args->whisper,
1659 args->app,
1660 args->app_args,
1661 args->snoop_id,
1662 response);
1663}
1664
1667 struct ast_ari_response *response)
1668{
1670 args->channel_id,
1671 args->spy,
1672 args->whisper,
1673 args->app,
1674 args->app_args,
1675 args->snoop_id,
1676 response);
1677}
1678
1682};
1683
1684static void chan_data_destroy(struct ari_channel_thread_data *chan_data)
1685{
1686 ast_free(chan_data->stasis_stuff);
1687 ast_hangup(chan_data->chan);
1688 ast_free(chan_data);
1689}
1690
1691/*!
1692 * \brief Thread that owns stasis-created channel.
1693 *
1694 * The channel enters into a Stasis application immediately upon creation. In this
1695 * way, the channel can be manipulated by the Stasis application. Once the channel
1696 * exits the Stasis application, it is hung up.
1697 */
1698static void *ari_channel_thread(void *data)
1699{
1700 struct ari_channel_thread_data *chan_data = data;
1701 struct ast_app *stasis_app;
1702
1703 stasis_app = pbx_findapp("Stasis");
1704 if (!stasis_app) {
1705 ast_log(LOG_ERROR, "Stasis dialplan application is not registered");
1706 chan_data_destroy(chan_data);
1707 return NULL;
1708 }
1709
1710 pbx_exec(chan_data->chan, stasis_app, ast_str_buffer(chan_data->stasis_stuff));
1711
1712 chan_data_destroy(chan_data);
1713
1714 return NULL;
1715}
1716
1718 .type = "ARI Dialstring",
1719 .destroy = ast_free_ptr,
1720};
1721
1722/*!
1723 * \brief Save dialstring onto a channel datastore
1724 *
1725 * This will later be retrieved when it comes time to actually dial the channel
1726 *
1727 * \param chan The channel on which to save the dialstring
1728 * \param dialstring The dialstring to save
1729 * \retval 0 on success.
1730 * \retval -1 on error.
1731 */
1732static int save_dialstring(struct ast_channel *chan, const char *dialstring)
1733{
1734 struct ast_datastore *datastore;
1735
1737 if (!datastore) {
1738 return -1;
1739 }
1740
1741 datastore->data = ast_strdup(dialstring);
1742 if (!datastore->data) {
1743 ast_datastore_free(datastore);
1744 return -1;
1745 }
1746
1747 ast_channel_lock(chan);
1748 if (ast_channel_datastore_add(chan, datastore)) {
1749 ast_channel_unlock(chan);
1750 ast_datastore_free(datastore);
1751 return -1;
1752 }
1753 ast_channel_unlock(chan);
1754
1755 return 0;
1756}
1757
1758/*!
1759 * \brief Retrieve the dialstring from the channel datastore
1760 *
1761 * \pre chan is locked
1762 * \param chan Channel that was previously created in ARI
1763 * \retval NULL Failed to find datastore
1764 * \retval non-NULL The dialstring
1765 */
1766static char *restore_dialstring(struct ast_channel *chan)
1767{
1768 struct ast_datastore *datastore;
1769
1770 datastore = ast_channel_datastore_find(chan, &dialstring_info, NULL);
1771 if (!datastore) {
1772 return NULL;
1773 }
1774
1775 return datastore->data;
1776}
1777
1780 struct ast_ari_response *response)
1781{
1782 RAII_VAR(struct ast_variable *, variables, NULL, ast_variables_destroy);
1783 struct ast_assigned_ids assignedids;
1784 struct ari_channel_thread_data *chan_data;
1785 struct ast_channel_snapshot *snapshot;
1786 pthread_t thread;
1787 char *dialtech;
1788 char *dialdevice = NULL;
1789 char *stuff;
1790 int cause;
1791 struct ast_format_cap *request_cap;
1792 struct ast_channel *originator;
1793
1794 /* Parse any query parameters out of the body parameter */
1795 if (args->variables) {
1796 struct ast_json *json_variables;
1797
1799 json_variables = ast_json_object_get(args->variables, "variables");
1800 if (json_variables
1801 && json_to_ast_variables(response, json_variables, &variables)) {
1802 return;
1803 }
1804 }
1805
1806 assignedids.uniqueid = args->channel_id;
1807 assignedids.uniqueid2 = args->other_channel_id;
1808
1809 if (!ast_strlen_zero(args->originator) && !ast_strlen_zero(args->formats)) {
1810 ast_ari_response_error(response, 400, "Bad Request",
1811 "Originator and formats can't both be specified");
1812 return;
1813 }
1814
1815 if (ast_strlen_zero(args->endpoint)) {
1816 ast_ari_response_error(response, 400, "Bad Request",
1817 "Endpoint must be specified");
1818 return;
1819 }
1820
1821 chan_data = ast_calloc(1, sizeof(*chan_data));
1822 if (!chan_data) {
1824 return;
1825 }
1826
1827 chan_data->stasis_stuff = ast_str_create(32);
1828 if (!chan_data->stasis_stuff) {
1830 chan_data_destroy(chan_data);
1831 return;
1832 }
1833
1834 ast_str_append(&chan_data->stasis_stuff, 0, "%s", args->app);
1835 if (!ast_strlen_zero(args->app_args)) {
1836 ast_str_append(&chan_data->stasis_stuff, 0, ",%s", args->app_args);
1837 }
1838
1839 dialtech = ast_strdupa(args->endpoint);
1840 if ((stuff = strchr(dialtech, '/'))) {
1841 *stuff++ = '\0';
1842 dialdevice = stuff;
1843 }
1844
1845 if (ast_strlen_zero(dialtech) || ast_strlen_zero(dialdevice)) {
1846 ast_ari_response_error(response, 400, "Bad Request",
1847 "Invalid endpoint specified");
1848 chan_data_destroy(chan_data);
1849 return;
1850 }
1851
1852 originator = ast_channel_get_by_name(args->originator);
1853 if (originator) {
1854 request_cap = ao2_bump(ast_channel_nativeformats(originator));
1855 if (!ast_strlen_zero(args->app)) {
1856 stasis_app_subscribe_channel(args->app, originator);
1857 }
1858 } else if (!ast_strlen_zero(args->formats)) {
1859 char *format_name;
1860 char *formats_copy = ast_strdupa(args->formats);
1861
1862 if (!(request_cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
1864 chan_data_destroy(chan_data);
1865 return;
1866 }
1867
1868 while ((format_name = ast_strip(strsep(&formats_copy, ",")))) {
1869 struct ast_format *fmt = ast_format_cache_get(format_name);
1870
1871 if (!fmt || ast_format_cap_append(request_cap, fmt, 0)) {
1872 if (!fmt) {
1874 response, 400, "Bad Request",
1875 "Provided format (%s) was not found", format_name);
1876 } else {
1878 }
1879 ao2_ref(request_cap, -1);
1880 ao2_cleanup(fmt);
1881 chan_data_destroy(chan_data);
1882 return;
1883 }
1884 ao2_ref(fmt, -1);
1885 }
1886 } else {
1887 if (!(request_cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
1889 chan_data_destroy(chan_data);
1890 return;
1891 }
1892
1894 }
1895
1896 chan_data->chan = ast_request(dialtech, request_cap, &assignedids, originator, dialdevice, &cause);
1897 ao2_cleanup(request_cap);
1898
1899 if (!chan_data->chan) {
1901 ast_ari_response_error(response, 409, "Conflict",
1902 "Channel with given unique ID already exists");
1903 } else {
1905 }
1906 ast_channel_cleanup(originator);
1907 chan_data_destroy(chan_data);
1908 return;
1909 }
1910
1911 if (!ast_strlen_zero(args->app)) {
1912 stasis_app_subscribe_channel(args->app, chan_data->chan);
1913 }
1914
1915 if (variables) {
1916 ast_set_variables(chan_data->chan, variables);
1917 }
1918
1919 ast_channel_cleanup(originator);
1920
1921 if (save_dialstring(chan_data->chan, stuff)) {
1923 chan_data_destroy(chan_data);
1924 return;
1925 }
1926
1928
1931 chan_data_destroy(chan_data);
1932 } else {
1934 }
1935
1936 ao2_ref(snapshot, -1);
1937}
1938
1941 struct ast_ari_response *response)
1942{
1943 RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
1944 RAII_VAR(struct ast_channel *, caller, NULL, ast_channel_cleanup);
1945 RAII_VAR(struct ast_channel *, callee, NULL, ast_channel_cleanup);
1946 char *dialstring;
1947
1948 control = find_control(response, args->channel_id);
1949 if (control == NULL) {
1950 /* Response filled in by find_control */
1951 return;
1952 }
1953
1954 caller = ast_channel_get_by_name(args->caller);
1955
1956 callee = ast_channel_get_by_name(args->channel_id);
1957 if (!callee) {
1958 ast_ari_response_error(response, 404, "Not Found",
1959 "Callee not found");
1960 return;
1961 }
1962
1963 if (ast_channel_state(callee) != AST_STATE_DOWN
1964 && ast_channel_state(callee) != AST_STATE_RESERVED) {
1965 ast_ari_response_error(response, 409, "Conflict",
1966 "Channel is not in the 'Down' state");
1967 return;
1968 }
1969
1970 /* XXX This is straight up copied from main/dial.c. It's probably good
1971 * to separate this to some common method.
1972 */
1973 if (caller) {
1974 ast_channel_lock_both(caller, callee);
1975 } else {
1976 ast_channel_lock(callee);
1977 }
1978
1979 dialstring = restore_dialstring(callee);
1980 if (!dialstring) {
1981 ast_channel_unlock(callee);
1982 if (caller) {
1983 ast_channel_unlock(caller);
1984 }
1985 ast_ari_response_error(response, 409, "Conflict",
1986 "Dialing a channel not created by ARI");
1987 return;
1988 }
1989 /* Make a copy of the dialstring just in case some jerk tries to hang up the
1990 * channel before we can actually dial
1991 */
1992 dialstring = ast_strdupa(dialstring);
1993
1995 if (caller) {
1996 ast_channel_inherit_variables(caller, callee);
1997 ast_channel_datastore_inherit(caller, callee);
1999
2000 /* Copy over callerid information */
2002
2004
2006
2007 ast_channel_language_set(callee, ast_channel_language(caller));
2010 ast_channel_musicclass_set(callee, ast_channel_musicclass(caller));
2011
2014 ast_channel_unlock(caller);
2015 }
2016
2018 ast_channel_unlock(callee);
2019
2020 if (stasis_app_control_dial(control, dialstring, args->timeout)) {
2022 return;
2023 }
2024
2026}
2027
2030 struct ast_ari_response *response)
2031{
2032 RAII_VAR(struct ast_channel *, chan, NULL, ast_channel_cleanup);
2033 RAII_VAR(struct ast_rtp_instance *, rtp, NULL, ao2_cleanup);
2034 struct ast_json *j_res;
2035 const struct ast_channel_tech *tech;
2036 struct ast_rtp_glue *glue;
2037
2038 chan = ast_channel_get_by_name(args->channel_id);
2039 if (!chan) {
2040 ast_ari_response_error(response, 404, "Not Found",
2041 "Channel not found");
2042 return;
2043 }
2044
2045 ast_channel_lock(chan);
2046 tech = ast_channel_tech(chan);
2047 if (!tech) {
2048 ast_channel_unlock(chan);
2049 ast_ari_response_error(response, 404, "Not Found",
2050 "Channel's tech not found");
2051 return;
2052 }
2053
2054 glue = ast_rtp_instance_get_glue(tech->type);
2055 if (!glue) {
2056 ast_channel_unlock(chan);
2057 ast_ari_response_error(response, 403, "Forbidden",
2058 "Unsupported channel type");
2059 return;
2060 }
2061
2062 glue->get_rtp_info(chan, &rtp);
2063 if (!rtp) {
2064 ast_channel_unlock(chan);
2065 ast_ari_response_error(response, 404, "Not Found",
2066 "RTP info not found");
2067 return;
2068 }
2069
2071 if (!j_res) {
2072 ast_channel_unlock(chan);
2073 ast_ari_response_error(response, 404, "Not Found",
2074 "Statistics not found");
2075 return;
2076 }
2077
2078 ast_channel_unlock(chan);
2079 ast_ari_response_ok(response, j_res);
2080
2081 return;
2082}
2083
2085 struct ast_variable *variables,
2086 struct ast_ari_response *response)
2087{
2088 char *endpoint;
2089 struct ast_channel *chan;
2090 struct varshead *vars;
2091
2092 if (ast_asprintf(&endpoint, "UnicastRTP/%s/c(%s)",
2093 args->external_host,
2094 args->format) == -1) {
2095 return 1;
2096 }
2097
2099 endpoint,
2100 NULL,
2101 NULL,
2102 0,
2103 NULL,
2104 args->app,
2105 args->data,
2106 NULL,
2107 0,
2108 variables,
2109 args->channel_id,
2110 NULL,
2111 NULL,
2112 args->format,
2113 response);
2114 ast_variables_destroy(variables);
2115
2116 ast_free(endpoint);
2117
2118 if (!chan) {
2119 return 1;
2120 }
2121
2122 ast_channel_lock(chan);
2123 vars = ast_channel_varshead(chan);
2124 if (vars && !AST_LIST_EMPTY(vars)) {
2125 ast_json_object_set(response->message, "channelvars", ast_json_channel_vars(vars));
2126 }
2127 ast_channel_unlock(chan);
2128 ast_channel_unref(chan);
2129 return 0;
2130}
2131
2133 struct ast_variable *variables,
2134 struct ast_ari_response *response)
2135{
2136 size_t endpoint_len;
2137 char *endpoint;
2138 struct ast_channel *chan;
2139 struct varshead *vars;
2140
2141 if (ast_strlen_zero(args->data)) {
2142 ast_ari_response_error(response, 400, "Bad Request", "data can not be empty");
2143 return;
2144 }
2145
2146 endpoint_len = strlen("AudioSocket/") + strlen(args->external_host) + 1 + strlen(args->data) + 1;
2147 endpoint = ast_alloca(endpoint_len);
2148 /* The UUID is stored in the arbitrary data field */
2149 snprintf(endpoint, endpoint_len, "AudioSocket/%s/%s", args->external_host, args->data);
2150
2152 endpoint,
2153 NULL,
2154 NULL,
2155 0,
2156 NULL,
2157 args->app,
2158 args->data,
2159 NULL,
2160 0,
2161 variables,
2162 args->channel_id,
2163 NULL,
2164 NULL,
2165 args->format,
2166 response);
2167 ast_variables_destroy(variables);
2168
2169 if (!chan) {
2170 return;
2171 }
2172
2173 ast_channel_lock(chan);
2174 vars = ast_channel_varshead(chan);
2175 if (vars && !AST_LIST_EMPTY(vars)) {
2176 ast_json_object_set(response->message, "channelvars", ast_json_channel_vars(vars));
2177 }
2178 ast_channel_unlock(chan);
2179 ast_channel_unref(chan);
2180}
2181
2182#include "asterisk/config.h"
2183#include "asterisk/netsock2.h"
2184
2187{
2188 struct ast_variable *variables = NULL;
2189 char *external_host;
2190 char *host = NULL;
2191 char *port = NULL;
2192
2193 ast_assert(response != NULL);
2194
2195 /* Parse any query parameters out of the body parameter */
2196 if (args->variables) {
2197 struct ast_json *json_variables;
2198
2200 json_variables = ast_json_object_get(args->variables, "variables");
2201 if (json_variables
2202 && json_to_ast_variables(response, json_variables, &variables)) {
2203 return;
2204 }
2205 }
2206
2207 if (ast_strlen_zero(args->app)) {
2208 ast_ari_response_error(response, 400, "Bad Request", "app cannot be empty");
2209 return;
2210 }
2211
2212 if (ast_strlen_zero(args->external_host)) {
2213 ast_ari_response_error(response, 400, "Bad Request", "external_host cannot be empty");
2214 return;
2215 }
2216
2217 external_host = ast_strdupa(args->external_host);
2218 if (!ast_sockaddr_split_hostport(external_host, &host, &port, PARSE_PORT_REQUIRE)) {
2219 ast_ari_response_error(response, 400, "Bad Request", "external_host must be <host>:<port>");
2220 return;
2221 }
2222
2223 if (ast_strlen_zero(args->format)) {
2224 ast_ari_response_error(response, 400, "Bad Request", "format cannot be empty");
2225 return;
2226 }
2227
2228 if (ast_strlen_zero(args->encapsulation)) {
2229 args->encapsulation = "rtp";
2230 }
2231 if (ast_strlen_zero(args->transport)) {
2232 args->transport = "udp";
2233 }
2234 if (ast_strlen_zero(args->connection_type)) {
2235 args->connection_type = "client";
2236 }
2237 if (ast_strlen_zero(args->direction)) {
2238 args->direction = "both";
2239 }
2240
2241 if (strcasecmp(args->encapsulation, "rtp") == 0 && strcasecmp(args->transport, "udp") == 0) {
2242 if (external_media_rtp_udp(args, variables, response)) {
2244 response, 500, "Internal Server Error",
2245 "An internal error prevented this request from being handled");
2246 }
2247 } else if (strcasecmp(args->encapsulation, "audiosocket") == 0 && strcasecmp(args->transport, "tcp") == 0) {
2248 external_media_audiosocket_tcp(args, variables, response);
2249 } else {
2251 response, 501, "Not Implemented",
2252 "The encapsulation and/or transport is not supported");
2253 }
2254}
static const char app[]
Definition: app_adsiprog.c:56
pthread_t thread
Definition: app_sla.c:329
void ast_ari_response_created(struct ast_ari_response *response, const char *url, struct ast_json *message)
Fill in a Created (201) ast_ari_response.
Definition: res_ari.c:305
void ast_ari_response_error(struct ast_ari_response *response, int response_code, const char *response_text, const char *message_fmt,...)
Fill in an error ast_ari_response.
Definition: res_ari.c:259
void ast_ari_response_ok(struct ast_ari_response *response, struct ast_json *message)
Fill in an OK (200) ast_ari_response.
Definition: res_ari.c:276
void ast_ari_response_alloc_failed(struct ast_ari_response *response)
Fill in response with a 500 message for allocation failures.
Definition: res_ari.c:298
void ast_ari_response_no_content(struct ast_ari_response *response)
Fill in a No Content (204) ast_ari_response.
Definition: res_ari.c:284
Asterisk main include file. File version handling, generic pbx functions.
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: astmm.h:288
#define ast_free(a)
Definition: astmm.h:180
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:241
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:298
void ast_free_ptr(void *ptr)
free() wrapper
Definition: astmm.c:1739
#define ast_asprintf(ret, fmt,...)
A wrapper for asprintf()
Definition: astmm.h:267
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:191
#define ast_log
Definition: astobj2.c:42
#define ao2_iterator_next(iter)
Definition: astobj2.h:1911
#define ao2_cleanup(obj)
Definition: astobj2.h:1934
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
#define ao2_bump(obj)
Bump refcount on an AO2 object by one, returning the object.
Definition: astobj2.h:480
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
Bridging API.
CallerID (and other GR30) management and generation Includes code and algorithms from the Zapata libr...
int ast_callerid_parse(char *instr, char **name, char **location)
Destructively parse inbuf into name and location (or number)
Definition: callerid.c:1063
void ast_shrink_phone_number(char *n)
Shrink a phone number in place to just digits (more accurately it just removes ()'s,...
Definition: callerid.c:1002
int ast_is_shrinkable_phonenumber(const char *exten)
Check if a string consists only of digits and + # ( ) - . (meaning it can be cleaned with ast_shrink_...
Definition: callerid.c:1058
#define AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED
Definition: callerid.h:423
Internal Asterisk hangup causes.
#define AST_CAUSE_CONGESTION
Definition: causes.h:153
#define AST_CAUSE_UNALLOCATED
Definition: causes.h:98
#define AST_CAUSE_INTERWORKING
Definition: causes.h:146
#define AST_CAUSE_BEARERCAPABILITY_NOTAVAIL
Definition: causes.h:130
#define AST_CAUSE_INVALID_NUMBER_FORMAT
Definition: causes.h:116
#define AST_CAUSE_FAILURE
Definition: causes.h:150
#define AST_CAUSE_NO_USER_RESPONSE
Definition: causes.h:108
#define AST_CAUSE_NORMAL
Definition: causes.h:151
#define AST_CAUSE_CALL_REJECTED
Definition: causes.h:111
#define AST_CAUSE_ANSWERED_ELSEWHERE
Definition: causes.h:114
#define AST_CAUSE_NORMAL_UNSPECIFIED
Definition: causes.h:119
#define AST_CAUSE_NOANSWER
Definition: causes.h:152
#define AST_CAUSE_BUSY
Definition: causes.h:149
static char language[MAX_LANGUAGE]
Definition: chan_iax2.c:324
void ast_channel_exten_set(struct ast_channel *chan, const char *value)
const char * ast_channel_name(const struct ast_channel *chan)
#define AST_MAX_PUBLIC_UNIQUEID
Definition: channel.h:147
enum ast_channel_error ast_channel_errno(void)
Get error code for latest channel operation.
Definition: channel.c:10961
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
Definition: channel.c:2385
void ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition: channel.c:2541
struct varshead * ast_channel_varshead(struct ast_channel *chan)
@ AST_CHANNEL_REQUESTOR_BRIDGE_PEER
Definition: channel.h:1477
void ast_channel_set_connected_line(struct ast_channel *chan, const struct ast_party_connected_line *connected, const struct ast_set_party_connected_line *update)
Set the connected line information in the Asterisk channel.
Definition: channel.c:8308
const char * ast_channel_musicclass(const struct ast_channel *chan)
#define ast_channel_lock(chan)
Definition: channel.h:2922
struct ast_format_cap * ast_channel_nativeformats(const struct ast_channel *chan)
struct ast_party_redirecting * ast_channel_redirecting(struct ast_channel *chan)
unsigned short ast_channel_transfercapability(const struct ast_channel *chan)
void ast_set_variables(struct ast_channel *chan, struct ast_variable *vars)
adds a list of channel variables to a channel
Definition: channel.c:8115
struct ast_flags * ast_channel_flags(struct ast_channel *chan)
@ AST_CHANNEL_ERROR_ID_EXISTS
Definition: channel.h:4797
#define ast_channel_ref(c)
Increase channel reference count.
Definition: channel.h:2947
#define ast_channel_lock_both(chan1, chan2)
Lock two channels.
Definition: channel.h:2929
struct ast_party_connected_line * ast_channel_connected(struct ast_channel *chan)
const char * ast_channel_uniqueid(const struct ast_channel *chan)
int ast_channel_datastore_inherit(struct ast_channel *from, struct ast_channel *to)
Inherit datastores from a parent to a child.
Definition: channel.c:2368
void ast_channel_req_accountcodes(struct ast_channel *chan, const struct ast_channel *requestor, enum ast_channel_requestor_relationship relationship)
Setup new channel accountcodes from the requestor channel after ast_request().
Definition: channel.c:6434
#define AST_MUTE_DIRECTION_READ
Definition: channel.h:4712
ast_channel_adsicpe
Definition: channel.h:868
void ast_set_callerid(struct ast_channel *chan, const char *cid_num, const char *cid_name, const char *cid_ani)
Set caller ID number, name and ANI and generate AMI event.
Definition: channel.c:7334
void ast_channel_inherit_variables(const struct ast_channel *parent, struct ast_channel *child)
Inherits channel variable from parent to child channel.
Definition: channel.c:6771
struct ast_party_dialed * ast_channel_dialed(struct ast_channel *chan)
int ast_softhangup(struct ast_channel *chan, int cause)
Softly hangup up a channel.
Definition: channel.c:2471
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2958
@ AST_SOFTHANGUP_EXPLICIT
Definition: channel.h:1148
#define AST_MAX_CONTEXT
Definition: channel.h:135
const char * ast_channel_language(const struct ast_channel *chan)
void ast_channel_context_set(struct ast_channel *chan, const char *value)
void ast_connected_line_copy_from_caller(struct ast_party_connected_line *dest, const struct ast_party_caller *src)
Copy the caller information to the connected line information.
Definition: channel.c:8293
#define AST_MUTE_DIRECTION_WRITE
Definition: channel.h:4713
@ AST_FLAG_ORIGINATED
Definition: channel.h:1039
const struct ast_channel_tech * ast_channel_tech(const struct ast_channel *chan)
struct ast_party_caller * ast_channel_caller(struct ast_channel *chan)
void ast_party_connected_line_set_init(struct ast_party_connected_line *init, const struct ast_party_connected_line *guide)
Initialize the given connected line structure using the given guide for a set update operation.
Definition: channel.c:2045
void ast_channel_transfercapability_set(struct ast_channel *chan, unsigned short value)
void ast_channel_priority_set(struct ast_channel *chan, int value)
void ast_channel_hangupcause_set(struct ast_channel *chan, int value)
#define ast_channel_cleanup(c)
Cleanup a channel reference.
Definition: channel.h:2969
struct ast_channel * ast_channel_get_by_name(const char *name)
Find a channel by name.
Definition: channel.c:1454
void ast_channel_adsicpe_set(struct ast_channel *chan, enum ast_channel_adsicpe value)
struct ast_channel * ast_request(const char *type, struct ast_format_cap *request_cap, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, const char *addr, int *cause)
Requests a channel.
Definition: channel.c:6354
#define ast_channel_unlock(chan)
Definition: channel.h:2923
#define AST_MAX_EXTENSION
Definition: channel.h:134
void ast_party_redirecting_copy(struct ast_party_redirecting *dest, const struct ast_party_redirecting *src)
Copy the source redirecting information to the destination redirecting.
Definition: channel.c:2135
struct ast_datastore * ast_channel_datastore_find(struct ast_channel *chan, const struct ast_datastore_info *info, const char *uid)
Find a datastore on a channel.
Definition: channel.c:2399
ast_channel_state
ast_channel states
Definition: channelstate.h:35
@ AST_STATE_RINGING
Definition: channelstate.h:41
@ AST_STATE_DOWN
Definition: channelstate.h:36
@ AST_STATE_RESERVED
Definition: channelstate.h:37
@ AST_MEDIA_TYPE_AUDIO
Definition: codec.h:32
Local proxy channel special access.
struct ast_channel * ast_local_get_peer(struct ast_channel *ast)
Get the other local channel in the pair.
Definition: core_local.c:276
#define ast_datastore_alloc(info, uid)
Definition: datastore.h:85
int ast_datastore_free(struct ast_datastore *datastore)
Free a data store object.
Definition: datastore.c:68
Dialing API.
ast_dial_result
List of return codes for dial run API calls.
Definition: dial.h:54
@ AST_DIAL_RESULT_ANSWERED
Definition: dial.h:61
int ast_dial_append(struct ast_dial *dial, const char *tech, const char *device, const struct ast_assigned_ids *assignedids)
Append a channel.
Definition: dial.c:280
struct ast_dial * ast_dial_create(void)
New dialing structure.
Definition: dial.c:223
struct ast_channel * ast_dial_answered(struct ast_dial *dial)
Return channel that answered.
Definition: dial.c:977
void ast_dial_set_user_data(struct ast_dial *dial, void *user_data)
Set user data on a dial structure.
Definition: dial.c:1274
int ast_dial_prerun(struct ast_dial *dial, struct ast_channel *chan, struct ast_format_cap *cap)
Request all appended channels, but do not dial.
Definition: dial.c:431
void ast_dial_set_global_timeout(struct ast_dial *dial, int timeout)
Set the maximum time (globally) allowed for trying to ring phones.
Definition: dial.c:1284
enum ast_dial_result ast_dial_run(struct ast_dial *dial, struct ast_channel *chan, int async)
Execute dialing synchronously or asynchronously.
Definition: dial.c:935
struct ast_channel * ast_dial_answered_steal(struct ast_dial *dial)
Steal the channel that answered.
Definition: dial.c:989
void * ast_dial_get_user_data(struct ast_dial *dial)
Return the user data on a dial structure.
Definition: dial.c:1279
struct ast_channel * ast_dial_get_channel(struct ast_dial *dial, int num)
Get the dialing channel, if prerun has been executed.
Definition: dial.c:1258
int ast_dial_destroy(struct ast_dial *dial)
Destroys a dialing structure.
Definition: dial.c:1091
char connected
Definition: eagi_proxy.c:82
char * end
Definition: eagi_proxy.c:73
Generic File Format Support. Should be included by clients of the file handling routines....
struct ast_format * ast_get_format_for_file_ext(const char *file_ext)
Get the ast_format associated with the given file extension.
Definition: file.c:2006
Media Format Cache API.
#define ast_format_cache_get(name)
Retrieve a named format from the cache.
Definition: format_cache.h:278
int ast_format_cap_append_by_type(struct ast_format_cap *cap, enum ast_media_type type)
Add all codecs Asterisk knows about for a specific type to the capabilities structure.
Definition: format_cap.c:216
@ AST_FORMAT_CAP_FLAG_DEFAULT
Definition: format_cap.h:38
#define ast_format_cap_append(cap, format, framing)
Add format capability to capabilities structure.
Definition: format_cap.h:99
#define ast_format_cap_alloc(flags)
Allocate a new ast_format_cap structure.
Definition: format_cap.h:49
direction
struct ao2_container * ast_channel_cache_all(void)
struct ast_channel_snapshot * ast_channel_snapshot_get_latest(const char *uniqueid)
Obtain the latest ast_channel_snapshot from the Stasis Message Bus API cache. This is an ao2 object,...
void ast_channel_stage_snapshot_done(struct ast_channel *chan)
Clear flag to indicate channel snapshot is being staged, and publish snapshot.
void ast_channel_stage_snapshot(struct ast_channel *chan)
Set flag to indicate channel snapshot is being staged.
@ AST_RECORD_IF_EXISTS_ERROR
char * strsep(char **str, const char *delims)
Configuration File Parser.
@ PARSE_PORT_REQUIRE
void ast_variables_destroy(struct ast_variable *var)
Free variable list.
Definition: extconf.c:1262
ast_frame_type
Frame types.
@ AST_FRAME_VOICE
#define AST_LOG_ERROR
#define ast_debug(level,...)
Log a DEBUG message.
#define LOG_ERROR
#define ast_verb(level,...)
#define LOG_WARNING
void ast_json_unref(struct ast_json *value)
Decrease refcount on value. If refcount reaches zero, value is freed.
Definition: json.c:73
int ast_json_array_append(struct ast_json *array, struct ast_json *value)
Append to an array.
Definition: json.c:378
struct ast_json * ast_json_pack(char const *format,...)
Helper for creating complex JSON values.
Definition: json.c:612
struct ast_json * ast_json_array_create(void)
Create a empty JSON array.
Definition: json.c:362
struct ast_json * ast_json_ref(struct ast_json *value)
Increase refcount on value.
Definition: json.c:67
int ast_json_object_set(struct ast_json *object, const char *key, struct ast_json *value)
Set a field in a JSON object.
Definition: json.c:414
ast_json_to_ast_vars_code
Definition: json.h:1109
@ AST_JSON_TO_AST_VARS_CODE_INVALID_TYPE
Conversion failed because invalid value type supplied.
Definition: json.h:1116
@ AST_JSON_TO_AST_VARS_CODE_SUCCESS
Conversion successful.
Definition: json.h:1111
@ AST_JSON_TO_AST_VARS_CODE_OOM
Conversion failed because of allocation failure. (Out Of Memory)
Definition: json.h:1118
struct ast_json * ast_json_object_get(struct ast_json *object, const char *key)
Get a field from a JSON object.
Definition: json.c:407
enum ast_json_to_ast_vars_code ast_json_to_ast_variables(struct ast_json *json_variables, struct ast_variable **variables)
Convert a ast_json list of key/value pair tuples into a ast_variable list.
Definition: json.c:818
struct ast_json * ast_json_channel_vars(struct varshead *channelvars)
Construct a JSON object from a ast_var_t list.
Definition: json.c:864
#define AST_LIST_EMPTY(head)
Checks whether the specified list contains any entries.
Definition: linkedlists.h:450
int errno
int ast_max_forwards_decrement(struct ast_channel *chan)
Decrement the max forwards count for a particular channel.
Definition: max_forwards.c:135
Network socket handling.
int ast_sockaddr_split_hostport(char *str, char **host, char **port, int flags)
Splits a string into its host and port components.
Definition: netsock2.c:164
Core PBX routines and definitions.
int ast_findlabel_extension(struct ast_channel *c, const char *context, const char *exten, const char *label, const char *callerid)
Find the priority of an extension that has the specified label.
Definition: pbx.c:4180
enum ast_pbx_result ast_pbx_run(struct ast_channel *c)
Execute the PBX in the current thread.
Definition: pbx.c:4755
int pbx_exec(struct ast_channel *c, struct ast_app *app, const char *data)
Execute an application.
Definition: pbx_app.c:471
int ast_func_read2(struct ast_channel *chan, const char *function, struct ast_str **str, ssize_t maxlen)
executes a read operation on a function
const char * ast_str_retrieve_variable(struct ast_str **buf, ssize_t maxlen, struct ast_channel *chan, struct varshead *headp, const char *var)
struct ast_app * pbx_findapp(const char *app)
Look up an application.
Definition: ael_main.c:165
#define NULL
Definition: resample.c:96
static int save_dialstring(struct ast_channel *chan, const char *dialstring)
Save dialstring onto a channel datastore.
void ast_ari_channels_mute(struct ast_variable *headers, struct ast_ari_channels_mute_args *args, struct ast_ari_response *response)
Mute a channel.
void ast_ari_channels_snoop_channel_with_id(struct ast_variable *headers, struct ast_ari_channels_snoop_channel_with_id_args *args, struct ast_ari_response *response)
Start snooping.
void ast_ari_channels_continue_in_dialplan(struct ast_variable *headers, struct ast_ari_channels_continue_in_dialplan_args *args, struct ast_ari_response *response)
Exit application; continue execution in the dialplan.
void ast_ari_channels_start_moh(struct ast_variable *headers, struct ast_ari_channels_start_moh_args *args, struct ast_ari_response *response)
Play music on hold to a channel.
static int channel_state_invalid(struct stasis_app_control *control, struct ast_ari_response *response)
Ensure channel is in a state that allows operation to be performed.
void ast_ari_channels_stop_moh(struct ast_variable *headers, struct ast_ari_channels_stop_moh_args *args, struct ast_ari_response *response)
Stop playing music on hold to a channel.
void ast_ari_channels_move(struct ast_variable *headers, struct ast_ari_channels_move_args *args, struct ast_ari_response *response)
Move the channel from one Stasis application to another.
static char * restore_dialstring(struct ast_channel *chan)
Retrieve the dialstring from the channel datastore.
void ast_ari_channels_send_dtmf(struct ast_variable *headers, struct ast_ari_channels_send_dtmf_args *args, struct ast_ari_response *response)
Send provided DTMF to a given channel.
void ast_ari_channels_unmute(struct ast_variable *headers, struct ast_ari_channels_unmute_args *args, struct ast_ari_response *response)
Unmute a channel.
void ast_ari_channels_dial(struct ast_variable *headers, struct ast_ari_channels_dial_args *args, struct ast_ari_response *response)
Dial a created channel.
static void * ari_originate_dial(void *data)
Thread which dials and executes upon answer.
void ast_ari_channels_create(struct ast_variable *headers, struct ast_ari_channels_create_args *args, struct ast_ari_response *response)
Create channel.
static int json_to_ast_variables(struct ast_ari_response *response, struct ast_json *json_variables, struct ast_variable **variables)
void ast_ari_channels_list(struct ast_variable *headers, struct ast_ari_channels_list_args *args, struct ast_ari_response *response)
List all active channels in Asterisk.
static void ari_channels_handle_snoop_channel(const char *args_channel_id, const char *args_spy, const char *args_whisper, const char *args_app, const char *args_app_args, const char *args_snoop_id, struct ast_ari_response *response)
void ast_ari_channels_get(struct ast_variable *headers, struct ast_ari_channels_get_args *args, struct ast_ari_response *response)
Channel details.
static void * ari_channel_thread(void *data)
Thread that owns stasis-created channel.
void ast_ari_channels_snoop_channel(struct ast_variable *headers, struct ast_ari_channels_snoop_channel_args *args, struct ast_ari_response *response)
Start snooping.
struct ast_datastore_info dialstring_info
void ast_ari_channels_ring(struct ast_variable *headers, struct ast_ari_channels_ring_args *args, struct ast_ari_response *response)
Indicate ringing to a channel.
void ast_ari_channels_play(struct ast_variable *headers, struct ast_ari_channels_play_args *args, struct ast_ari_response *response)
Start playback of media.
void ast_ari_channels_stop_silence(struct ast_variable *headers, struct ast_ari_channels_stop_silence_args *args, struct ast_ari_response *response)
Stop playing silence to a channel.
void ast_ari_channels_external_media(struct ast_variable *headers, struct ast_ari_channels_external_media_args *args, struct ast_ari_response *response)
Start an External Media session.
static void ari_channels_handle_play(const char *args_channel_id, const char **args_media, size_t args_media_count, const char *args_lang, int args_offsetms, int args_skipms, const char *args_playback_id, struct ast_ari_response *response)
void ast_ari_channels_ring_stop(struct ast_variable *headers, struct ast_ari_channels_ring_stop_args *args, struct ast_ari_response *response)
Stop ringing indication on a channel if locally generated.
void ast_ari_channels_start_silence(struct ast_variable *headers, struct ast_ari_channels_start_silence_args *args, struct ast_ari_response *response)
Play silence to a channel.
static struct ast_channel * ari_channels_handle_originate_with_id(const char *args_endpoint, const char *args_extension, const char *args_context, long args_priority, const char *args_label, const char *args_app, const char *args_app_args, const char *args_caller_id, int args_timeout, struct ast_variable *variables, const char *args_channel_id, const char *args_other_channel_id, const char *args_originator, const char *args_formats, struct ast_ari_response *response)
static void external_media_audiosocket_tcp(struct ast_ari_channels_external_media_args *args, struct ast_variable *variables, struct ast_ari_response *response)
static int convert_reason_to_hangup_code(const char *reason)
Return the corresponded hangup code of the given reason.
void ast_ari_channels_unhold(struct ast_variable *headers, struct ast_ari_channels_unhold_args *args, struct ast_ari_response *response)
Remove a channel from hold.
void ast_ari_channels_originate(struct ast_variable *headers, struct ast_ari_channels_originate_args *args, struct ast_ari_response *response)
Create a new channel (originate).
void ast_ari_channels_redirect(struct ast_variable *headers, struct ast_ari_channels_redirect_args *args, struct ast_ari_response *response)
Redirect the channel to a different location.
void ast_ari_channels_record(struct ast_variable *headers, struct ast_ari_channels_record_args *args, struct ast_ari_response *response)
Start a recording.
static void chan_data_destroy(struct ari_channel_thread_data *chan_data)
void ast_ari_channels_set_channel_var(struct ast_variable *headers, struct ast_ari_channels_set_channel_var_args *args, struct ast_ari_response *response)
Set the value of a channel variable or function.
static int external_media_rtp_udp(struct ast_ari_channels_external_media_args *args, struct ast_variable *variables, struct ast_ari_response *response)
void ast_ari_channels_hold(struct ast_variable *headers, struct ast_ari_channels_hold_args *args, struct ast_ari_response *response)
Hold a channel.
void ast_ari_channels_answer(struct ast_variable *headers, struct ast_ari_channels_answer_args *args, struct ast_ari_response *response)
Answer a channel.
void ast_ari_channels_play_with_id(struct ast_variable *headers, struct ast_ari_channels_play_with_id_args *args, struct ast_ari_response *response)
Start playback of media and specify the playbackId.
void ast_ari_channels_rtpstatistics(struct ast_variable *headers, struct ast_ari_channels_rtpstatistics_args *args, struct ast_ari_response *response)
RTP stats on a channel.
void ast_ari_channels_get_channel_var(struct ast_variable *headers, struct ast_ari_channels_get_channel_var_args *args, struct ast_ari_response *response)
Get the value of a channel variable or function.
static struct stasis_app_control * find_control(struct ast_ari_response *response, const char *channel_id)
Finds the control object for a channel, filling the response with an error, if appropriate.
void ast_ari_channels_originate_with_id(struct ast_variable *headers, struct ast_ari_channels_originate_with_id_args *args, struct ast_ari_response *response)
Create a new channel (originate with id).
void ast_ari_channels_hangup(struct ast_variable *headers, struct ast_ari_channels_hangup_args *args, struct ast_ari_response *response)
Delete (i.e. hangup) a channel.
Generated file - declares stubs to be implemented in res/ari/resource_channels.c.
int ast_ari_channels_originate_with_id_parse_body(struct ast_json *body, struct ast_ari_channels_originate_with_id_args *args)
Body parsing function for /channels/{channelId}.
int ast_ari_channels_create_parse_body(struct ast_json *body, struct ast_ari_channels_create_args *args)
Body parsing function for /channels/create.
int ast_ari_channels_external_media_parse_body(struct ast_json *body, struct ast_ari_channels_external_media_args *args)
Body parsing function for /channels/externalMedia.
int ast_ari_channels_originate_parse_body(struct ast_json *body, struct ast_ari_channels_originate_args *args)
Body parsing function for /channels.
Pluggable RTP Architecture.
struct ast_json * ast_rtp_instance_get_stats_all_json(struct ast_rtp_instance *instance)
Retrieve statistics about an RTP instance in json format.
Definition: rtp_engine.c:4097
struct ast_rtp_glue * ast_rtp_instance_get_glue(const char *type)
Get the RTP glue that binds a channel to the RTP engine.
Definition: rtp_engine.c:2219
Stasis Application API. See Stasis Application API for detailed documentation.
struct stasis_message_sanitizer * stasis_app_get_sanitizer(void)
Get the Stasis message sanitizer for app_stasis applications.
Definition: res_stasis.c:2271
void stasis_app_control_moh_start(struct stasis_app_control *control, const char *moh_class)
Play music on hold to a channel (does not affect hold status)
Definition: control.c:800
int stasis_app_control_unmute(struct stasis_app_control *control, unsigned int direction, enum ast_frame_type frametype)
Unmute the channel associated with this control.
Definition: control.c:679
void stasis_app_control_unhold(struct stasis_app_control *control)
Remove the channel associated with the control from hold.
Definition: control.c:781
void stasis_app_control_silence_start(struct stasis_app_control *control)
Start playing silence to a channel.
Definition: control.c:852
void stasis_app_control_silence_stop(struct stasis_app_control *control)
Stop playing silence to a channel.
Definition: control.c:875
int stasis_app_control_continue(struct stasis_app_control *control, const char *context, const char *extension, int priority)
Exit res_stasis and continue execution in the dialplan.
Definition: control.c:409
int stasis_app_control_redirect(struct stasis_app_control *control, const char *endpoint)
Redirect a channel in res_stasis to a particular endpoint.
Definition: control.c:520
void stasis_app_control_moh_stop(struct stasis_app_control *control)
Stop playing music on hold to a channel (does not affect hold status)
Definition: control.c:818
int stasis_app_control_move(struct stasis_app_control *control, const char *app_name, const char *app_args)
Exit res_stasis and move to another Stasis application.
Definition: control.c:471
int stasis_app_control_mute(struct stasis_app_control *control, unsigned int direction, enum ast_frame_type frametype)
Mute the channel associated with this control.
Definition: control.c:651
enum stasis_app_subscribe_res stasis_app_subscribe_channel(const char *app_name, struct ast_channel *chan)
Directly subscribe an application to a channel.
Definition: res_stasis.c:1991
int stasis_app_control_dtmf(struct stasis_app_control *control, const char *dtmf, int before, int between, unsigned int duration, int after)
Send DTMF to the channel associated with this control.
Definition: control.c:585
void stasis_app_control_hold(struct stasis_app_control *control)
Place the channel associated with the control on hold.
Definition: control.c:768
struct stasis_app_control * stasis_app_control_find_by_channel_id(const char *channel_id)
Returns the handler for the channel with the given id.
Definition: res_stasis.c:349
int stasis_app_control_ring_stop(struct stasis_app_control *control)
Stop locally generated ringing on the channel associated with this control.
Definition: control.c:627
int stasis_app_control_dial(struct stasis_app_control *control, const char *dialstring, unsigned int timeout)
Dial a channel.
Definition: control.c:1686
struct ast_channel_snapshot * stasis_app_control_get_snapshot(const struct stasis_app_control *control)
Returns the most recent snapshot for the associated channel.
Definition: control.c:880
int stasis_app_control_set_channel_var(struct stasis_app_control *control, const char *variable, const char *value)
Set a variable on the channel associated with this control to value.
Definition: control.c:731
int stasis_app_control_ring(struct stasis_app_control *control)
Indicate ringing to the channel associated with this control.
Definition: control.c:612
int stasis_app_control_answer(struct stasis_app_control *control)
Answer the channel associated with this control.
Stasis Application Playback API. See StasisApplication API" for detailed documentation.
@ STASIS_PLAYBACK_TARGET_CHANNEL
struct stasis_app_playback * stasis_app_control_play_uri(struct stasis_app_control *control, const char **media, size_t media_count, const char *language, const char *target_id, enum stasis_app_playback_target_type target_type, int skipms, long offsetms, const char *id)
Play a file to the control's channel.
struct ast_json * stasis_app_playback_to_json(const struct stasis_app_playback *playback)
Convert a playback to its JSON representation.
const char * stasis_app_playback_get_id(struct stasis_app_playback *playback)
Gets the unique id of a playback object.
Stasis Application Recording API. See StasisApplication API" for detailed documentation.
struct stasis_app_recording_options * stasis_app_recording_options_create(const char *name, const char *format)
Allocate a recording options object.
struct ast_json * stasis_app_recording_to_json(const struct stasis_app_recording *recording)
Construct a JSON model of a recording.
struct stasis_app_recording * stasis_app_control_record(struct stasis_app_control *control, struct stasis_app_recording_options *options)
Record media from a channel.
enum ast_record_if_exists stasis_app_recording_if_exists_parse(const char *str)
Parse a string into the if_exists enum.
#define STASIS_APP_RECORDING_TERMINATE_INVALID
char stasis_app_recording_termination_parse(const char *str)
Parse a string into the recording termination enum.
Stasis Application Snoop API. See StasisApplication API" for detailed documentation.
struct ast_channel * stasis_app_control_snoop(struct ast_channel *chan, enum stasis_app_snoop_direction spy, enum stasis_app_snoop_direction whisper, const char *app, const char *app_args, const char *snoop_id)
Create a snoop on the provided channel.
stasis_app_snoop_direction
Directions for audio stream flow.
@ STASIS_SNOOP_DIRECTION_IN
Audio stream in from the channel.
@ STASIS_SNOOP_DIRECTION_OUT
Audio stream out to the channel.
@ STASIS_SNOOP_DIRECTION_NONE
No direction.
@ STASIS_SNOOP_DIRECTION_BOTH
Audio stream to AND from the channel.
struct ast_json * ast_channel_snapshot_to_json(const struct ast_channel_snapshot *snapshot, const struct stasis_message_sanitizer *sanitize)
Build a JSON object from a ast_channel_snapshot.
#define ast_string_field_build(x, field, fmt, args...)
Set a field to a complex (built) value.
Definition: stringfields.h:555
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
Definition: strings.h:1139
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:761
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one.
Definition: strings.h:80
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
Definition: strings.h:659
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
Definition: strings.h:1113
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:425
char * ast_strip(char *s)
Strip leading/trailing whitespace from a string.
Definition: strings.h:223
size_t ast_str_size(const struct ast_str *buf)
Returns the current maximum length (without reallocation) of the current buffer.
Definition: strings.h:742
Generic container type.
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1821
struct ast_str * stasis_stuff
struct ast_channel * chan
Structure used for origination.
char appdata[0]
Application data to pass to Stasis application.
char exten[AST_MAX_EXTENSION]
Dialplan extension.
char context[AST_MAX_CONTEXT]
Dialplan context.
int priority
Dialplan priority.
ast_app: A registered application
Definition: pbx_app.c:45
struct ast_json * message
Definition: ari.h:94
Structure to pass both assignedid values to channel drivers.
Definition: channel.h:604
const char * uniqueid2
Definition: channel.h:606
const char * uniqueid
Definition: channel.h:605
Structure representing a snapshot of channel state.
enum ast_channel_state state
Structure to describe a channel "technology", ie a channel driver See for examples:
Definition: channel.h:628
const char *const type
Definition: channel.h:629
Main Channel structure associated with a channel.
struct ast_channel_snapshot * snapshot
Structure for a data store type.
Definition: datastore.h:31
const char * type
Definition: datastore.h:32
Structure for a data store object.
Definition: datastore.h:64
void * data
Definition: datastore.h:66
Main dialing structure. Contains global options, channels being dialed, and more!
Definition: dial.c:48
Format capabilities structure, holds formats + preference order + etc.
Definition: format_cap.c:54
Definition of a media format.
Definition: format.c:43
Abstract JSON element (object, array, string, int, ...).
Connected Line/Party information.
Definition: channel.h:456
int transit_network_select
Transit Network Select.
Definition: channel.h:397
enum ast_rtp_glue_result(* get_rtp_info)(struct ast_channel *chan, struct ast_rtp_instance **instance)
Callback for retrieving the RTP instance carrying audio.
Definition: rtp_engine.h:775
Support for dynamic strings.
Definition: strings.h:623
Structure for variables, used for configurations and for channel variables.
Structure containing callbacks for Stasis message sanitization.
Definition: stasis.h:200
int(* channel_snapshot)(const struct ast_channel_snapshot *snapshot)
Callback which determines whether a channel should be sanitized from a message based on the channel's...
Definition: stasis.h:221
int value
Definition: syslog.c:37
const char * args
static struct test_options options
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:941
#define ast_assert(a)
Definition: utils.h:739
char * ast_uri_encode(const char *string, char *outbuf, int buflen, struct ast_flags spec)
Turn text string to URI-encoded XX version.
Definition: utils.c:723
const struct ast_flags ast_uri_http
Definition: utils.c:719
#define ast_pthread_create_detached(a, b, c, d)
Definition: utils.h:588
#define ast_set_flag(p, flag)
Definition: utils.h:70