Asterisk - The Open Source Telephony Project GIT-master-5963e62
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros Modules Pages
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"
48#include "resource_channels.h"
49
50#include <limits.h>
51
52
53/*! \brief Return the corresponded hangup code of the given reason */
54static int convert_reason_to_hangup_code(const char* reason)
55{
56 if (!strcmp(reason, "normal")) {
57 return AST_CAUSE_NORMAL;
58 } else if (!strcmp(reason, "busy")) {
59 return AST_CAUSE_BUSY;
60 } else if (!strcmp(reason, "congestion")) {
62 } else if (!strcmp(reason, "no_answer")) {
63 return AST_CAUSE_NOANSWER;
64 } else if (!strcmp(reason, "timeout")) {
66 } else if (!strcmp(reason, "rejected")) {
68 } else if (!strcmp(reason, "unallocated")) {
70 } else if (!strcmp(reason, "normal_unspecified")) {
72 } else if (!strcmp(reason, "number_incomplete")) {
74 } else if (!strcmp(reason, "codec_mismatch")) {
76 } else if (!strcmp(reason, "interworking")) {
78 } else if (!strcmp(reason, "failure")) {
79 return AST_CAUSE_FAILURE;
80 } else if(!strcmp(reason, "answered_elsewhere")) {
82 }
83
84 return -1;
85}
86
87/*!
88 * \brief Ensure channel is in a state that allows operation to be performed.
89 *
90 * Since Asterisk 14, it has been possible for down channels, as well as unanswered
91 * outbound channels to enter Stasis. While some operations are fine to perform on
92 * such channels, operations that
93 *
94 * - Attempt to manipulate channel state
95 * - Attempt to play media
96 * - Attempt to control the channel's location in the dialplan
97 *
98 * are invalid. This function can be used to determine if the channel is in an
99 * appropriate state.
100 *
101 * \note When this function returns an error, the HTTP response is taken care of.
102 *
103 * \param control The app control
104 * \param response Response to fill in if there is an error
105 *
106 * \retval 0 Channel is in a valid state. Continue on!
107 * \retval non-zero Channel is in an invalid state. Bail!
108 */
109static int channel_state_invalid(struct stasis_app_control *control,
110 struct ast_ari_response *response)
111{
112 struct ast_channel_snapshot *snapshot;
113
114 snapshot = stasis_app_control_get_snapshot(control);
115 if (!snapshot) {
116 ast_ari_response_error(response, 404, "Not Found", "Channel not found");
117 return -1;
118 }
119
120 /* These channel states apply only to outbound channels:
121 * - Down: Channel has been created, and nothing else has been done
122 * - Reserved: For a PRI, an underlying B-channel is reserved,
123 * but the channel is not yet dialed
124 * - Ringing: The channel has been dialed.
125 *
126 * This does not affect inbound channels. Inbound channels, when they
127 * enter the dialplan, are in the "Ring" state. If they have already
128 * been answered, then they are in the "Up" state.
129 */
130 if (snapshot->state == AST_STATE_DOWN
131 || snapshot->state == AST_STATE_RESERVED
132 || snapshot->state == AST_STATE_RINGING) {
133 ast_ari_response_error(response, 412, "Precondition Failed",
134 "Channel in invalid state");
135 ao2_ref(snapshot, -1);
136
137 return -1;
138 }
139
140 ao2_ref(snapshot, -1);
141
142 return 0;
143}
144
145/*!
146 * \brief Finds the control object for a channel, filling the response with an
147 * error, if appropriate.
148 * \param[out] response Response to fill with an error if control is not found.
149 * \param channel_id ID of the channel to lookup.
150 * \return Channel control object.
151 * \retval NULL if control object does not exist.
152 */
154 struct ast_ari_response *response,
155 const char *channel_id)
156{
157 RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
158
159 ast_assert(response != NULL);
160
161 control = stasis_app_control_find_by_channel_id(channel_id);
162 if (control == NULL) {
163 /* Distinguish between 404 and 409 errors */
164 RAII_VAR(struct ast_channel *, chan, NULL, ao2_cleanup);
165 chan = ast_channel_get_by_name(channel_id);
166 if (chan == NULL) {
167 ast_ari_response_error(response, 404, "Not Found",
168 "Channel not found");
169 return NULL;
170 }
171
172 ast_ari_response_error(response, 409, "Conflict",
173 "Channel not in Stasis application");
174 return NULL;
175 }
176
177 ao2_ref(control, +1);
178 return control;
179}
180
182 struct ast_variable *headers,
184 struct ast_ari_response *response)
185{
186 RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
187 RAII_VAR(struct ast_channel_snapshot *, snapshot, NULL, ao2_cleanup);
188 int ipri;
189 const char *context;
190 const char *exten;
191
192 ast_assert(response != NULL);
193
194 control = find_control(response, args->channel_id);
195 if (control == NULL) {
196 return;
197 }
198
199 if (channel_state_invalid(control, response)) {
200 return;
201 }
202
203 snapshot = stasis_app_control_get_snapshot(control);
204 if (!snapshot) {
205 ast_ari_response_error(response, 404, "Not Found", "Channel not found");
206 return;
207 }
208
209 if (ast_strlen_zero(args->context)) {
210 context = snapshot->dialplan->context;
211 exten = S_OR(args->extension, snapshot->dialplan->exten);
212 } else {
213 context = args->context;
214 exten = S_OR(args->extension, "s");
215 }
216
217 if (!ast_strlen_zero(args->label)) {
218 /* A label was provided in the request, use that */
219
220 if (sscanf(args->label, "%30d", &ipri) != 1) {
221 ipri = ast_findlabel_extension(NULL, context, exten, args->label, NULL);
222 if (ipri == -1) {
223 ast_log(AST_LOG_ERROR, "Requested label: %s can not be found in context: %s\n", args->label, context);
224 ast_ari_response_error(response, 404, "Not Found", "Requested label can not be found");
225 return;
226 }
227 } else {
228 ast_debug(3, "Numeric value provided for label, jumping to that priority\n");
229 }
230
231 if (ipri == 0) {
232 ast_log(AST_LOG_ERROR, "Invalid priority label '%s' specified for extension %s in context: %s\n",
233 args->label, exten, context);
234 ast_ari_response_error(response, 400, "Bad Request", "Requested priority is illegal");
235 return;
236 }
237
238 } else if (args->priority) {
239 /* No label provided, use provided priority */
240 ipri = args->priority;
241 } else if (ast_strlen_zero(args->context) && ast_strlen_zero(args->extension)) {
242 /* Special case. No exten, context, or priority provided, then move on to the next priority */
243 ipri = snapshot->dialplan->priority + 1;
244 } else {
245 ipri = 1;
246 }
247
248
249 if (stasis_app_control_continue(control, context, exten, ipri)) {
251 return;
252 }
253
255}
256
259 struct ast_ari_response *response)
260{
261 RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
262
263 control = find_control(response, args->channel_id);
264 if (!control) {
265 return;
266 }
267
268 if (stasis_app_control_move(control, args->app, args->app_args)) {
269 ast_ari_response_error(response, 500, "Internal Server Error",
270 "Failed to switch Stasis applications");
271 return;
272 }
273
275}
276
279 struct ast_ari_response *response)
280{
281 RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
282 RAII_VAR(struct ast_channel_snapshot *, chan_snapshot, NULL, ao2_cleanup);
283 char *tech;
284 char *resource;
285 int tech_len;
286
287 control = find_control(response, args->channel_id);
288 if (!control) {
289 return;
290 }
291
292 if (channel_state_invalid(control, response)) {
293 return;
294 }
295
296 if (ast_strlen_zero(args->endpoint)) {
297 ast_ari_response_error(response, 400, "Not Found",
298 "Required parameter 'endpoint' not provided.");
299 return;
300 }
301
302 tech = ast_strdupa(args->endpoint);
303 if (!(resource = strchr(tech, '/')) || !(tech_len = resource - tech)) {
304 ast_ari_response_error(response, 422, "Unprocessable Entity",
305 "Endpoint parameter '%s' does not contain tech/resource", args->endpoint);
306 return;
307 }
308
309 *resource++ = '\0';
310 if (ast_strlen_zero(resource)) {
311 ast_ari_response_error(response, 422, "Unprocessable Entity",
312 "No resource provided in endpoint parameter '%s'", args->endpoint);
313 return;
314 }
315
316 chan_snapshot = ast_channel_snapshot_get_latest(args->channel_id);
317 if (!chan_snapshot) {
318 ast_ari_response_error(response, 500, "Internal Server Error",
319 "Unable to find channel snapshot for '%s'", args->channel_id);
320 return;
321 }
322
323 if (strncasecmp(chan_snapshot->base->type, tech, tech_len)) {
324 ast_ari_response_error(response, 422, "Unprocessable Entity",
325 "Endpoint technology '%s' does not match channel technology '%s'",
326 tech, chan_snapshot->base->type);
327 return;
328 }
329
330 if (stasis_app_control_redirect(control, resource)) {
331 ast_ari_response_error(response, 500, "Internal Server Error",
332 "Failed to redirect channel");
333 return;
334 }
335
337}
338
341 struct ast_ari_response *response)
342{
343 RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
344
345 control = find_control(response, args->channel_id);
346 if (control == NULL) {
347 return;
348 }
349
350 if (channel_state_invalid(control, response)) {
351 return;
352 }
353
354 if (stasis_app_control_answer(control) != 0) {
356 response, 500, "Internal Server Error",
357 "Failed to answer channel");
358 return;
359 }
360
362}
363
366 struct ast_ari_response *response)
367{
368 RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
369
370 control = find_control(response, args->channel_id);
371 if (control == NULL) {
372 return;
373 }
374
375 if (channel_state_invalid(control, response)) {
376 return;
377 }
378
380
382}
383
386 struct ast_ari_response *response)
387{
388 RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
389
390 control = find_control(response, args->channel_id);
391 if (control == NULL) {
392 return;
393 }
394
395 if (channel_state_invalid(control, response)) {
396 return;
397 }
398
400
402}
403
406 struct ast_ari_response *response)
407{
408 RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
409 unsigned int direction = 0;
410 enum ast_frame_type frametype = AST_FRAME_VOICE;
411
412 control = find_control(response, args->channel_id);
413 if (control == NULL) {
414 return;
415 }
416
417 if (channel_state_invalid(control, response)) {
418 return;
419 }
420
421 if (ast_strlen_zero(args->direction)) {
423 response, 400, "Bad Request",
424 "Direction is required");
425 return;
426 }
427
428 if (!strcmp(args->direction, "in")) {
430 } else if (!strcmp(args->direction, "out")) {
432 } else if (!strcmp(args->direction, "both")) {
434 } else {
436 response, 400, "Bad Request",
437 "Invalid direction specified");
438 return;
439 }
440
441 stasis_app_control_mute(control, direction, frametype);
442
444}
445
448 struct ast_ari_response *response)
449{
450 RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
451 unsigned int direction = 0;
452 enum ast_frame_type frametype = AST_FRAME_VOICE;
453
454 control = find_control(response, args->channel_id);
455 if (control == NULL) {
456 return;
457 }
458
459 if (channel_state_invalid(control, response)) {
460 return;
461 }
462
463 if (ast_strlen_zero(args->direction)) {
465 response, 400, "Bad Request",
466 "Direction is required");
467 return;
468 }
469
470 if (!strcmp(args->direction, "in")) {
472 } else if (!strcmp(args->direction, "out")) {
474 } else if (!strcmp(args->direction, "both")) {
476 } else {
478 response, 400, "Bad Request",
479 "Invalid direction specified");
480 return;
481 }
482
483 stasis_app_control_unmute(control, direction, frametype);
484
486}
487
490 struct ast_ari_response *response)
491{
492 RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
493
494 control = find_control(response, args->channel_id);
495 if (control == NULL) {
496 return;
497 }
498
499 if (channel_state_invalid(control, response)) {
500 return;
501 }
502
503 if (ast_strlen_zero(args->dtmf)) {
505 response, 400, "Bad Request",
506 "DTMF is required");
507 return;
508 }
509
510 stasis_app_control_dtmf(control, args->dtmf, args->before, args->between, args->duration, args->after);
511
513}
514
517 struct ast_ari_response *response)
518{
519 RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
520
521 control = find_control(response, args->channel_id);
522 if (control == NULL) {
523 /* Response filled in by find_control */
524 return;
525 }
526
527 if (channel_state_invalid(control, response)) {
528 return;
529 }
530
532
534}
535
538 struct ast_ari_response *response)
539{
540 RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
541
542 control = find_control(response, args->channel_id);
543 if (control == NULL) {
544 /* Response filled in by find_control */
545 return;
546 }
547
548 if (channel_state_invalid(control, response)) {
549 return;
550 }
551
553
555}
556
559 struct ast_ari_response *response)
560{
561 RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
562
563 control = find_control(response, args->channel_id);
564 if (control == NULL) {
565 /* Response filled in by find_control */
566 return;
567 }
568
569 if (channel_state_invalid(control, response)) {
570 return;
571 }
572
573 stasis_app_control_moh_start(control, args->moh_class);
575}
576
579 struct ast_ari_response *response)
580{
581 RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
582
583 control = find_control(response, args->channel_id);
584 if (control == NULL) {
585 /* Response filled in by find_control */
586 return;
587 }
588
589 if (channel_state_invalid(control, response)) {
590 return;
591 }
592
595}
596
599 struct ast_ari_response *response)
600{
601 RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
602
603 control = find_control(response, args->channel_id);
604 if (control == NULL) {
605 /* Response filled in by find_control */
606 return;
607 }
608
609 if (channel_state_invalid(control, response)) {
610 return;
611 }
612
615}
616
619 struct ast_ari_response *response)
620{
621 RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
622
623 control = find_control(response, args->channel_id);
624 if (control == NULL) {
625 /* Response filled in by find_control */
626 return;
627 }
628
629 if (channel_state_invalid(control, response)) {
630 return;
631 }
632
635}
636
638 const char *args_channel_id,
639 const char **args_media,
640 size_t args_media_count,
641 const char *args_lang,
642 int args_offsetms,
643 int args_skipms,
644 const char *args_playback_id,
645 struct ast_ari_response *response)
646{
647 RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
648 RAII_VAR(struct ast_channel_snapshot *, snapshot, NULL, ao2_cleanup);
649 RAII_VAR(struct stasis_app_playback *, playback, NULL, ao2_cleanup);
650 RAII_VAR(char *, playback_url, NULL, ast_free);
651 struct ast_json *json;
652 const char *language;
653
654 ast_assert(response != NULL);
655
656 control = find_control(response, args_channel_id);
657 if (control == NULL) {
658 /* Response filled in by find_control */
659 return;
660 }
661
662 if (channel_state_invalid(control, response)) {
663 return;
664 }
665
666 snapshot = stasis_app_control_get_snapshot(control);
667 if (!snapshot) {
669 response, 404, "Not Found",
670 "Channel not found");
671 return;
672 }
673
674 if (args_skipms < 0) {
676 response, 400, "Bad Request",
677 "skipms cannot be negative");
678 return;
679 }
680
681 if (args_offsetms < 0) {
683 response, 400, "Bad Request",
684 "offsetms cannot be negative");
685 return;
686 }
687
688 language = S_OR(args_lang, snapshot->base->language);
689
690 playback = stasis_app_control_play_uri(control, args_media, args_media_count, language,
691 args_channel_id, STASIS_PLAYBACK_TARGET_CHANNEL, args_skipms, args_offsetms, args_playback_id);
692 if (!playback) {
694 response, 500, "Internal Server Error",
695 "Failed to queue media for playback");
696 return;
697 }
698
699 if (ast_asprintf(&playback_url, "/playbacks/%s",
700 stasis_app_playback_get_id(playback)) == -1) {
701 playback_url = NULL;
703 response, 500, "Internal Server Error",
704 "Out of memory");
705 return;
706 }
707
708 json = stasis_app_playback_to_json(playback);
709 if (!json) {
711 response, 500, "Internal Server Error",
712 "Out of memory");
713 return;
714 }
715
716 ast_ari_response_created(response, playback_url, json);
717}
718
721 struct ast_ari_response *response)
722{
724 args->channel_id,
725 args->media,
726 args->media_count,
727 args->lang,
728 args->offsetms,
729 args->skipms,
730 args->playback_id,
731 response);
732}
733
736 struct ast_ari_response *response)
737{
739 args->channel_id,
740 args->media,
741 args->media_count,
742 args->lang,
743 args->offsetms,
744 args->skipms,
745 args->playback_id,
746 response);
747}
748
751 struct ast_ari_response *response)
752{
753 RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
754 RAII_VAR(struct stasis_app_recording *, recording, NULL, ao2_cleanup);
755 RAII_VAR(char *, recording_url, NULL, ast_free);
756 struct ast_json *json;
759 RAII_VAR(char *, uri_encoded_name, NULL, ast_free);
760 size_t uri_name_maxlen;
761
762 ast_assert(response != NULL);
763
764 if (args->max_duration_seconds < 0) {
766 response, 400, "Bad Request",
767 "max_duration_seconds cannot be negative");
768 return;
769 }
770
771 if (args->max_silence_seconds < 0) {
773 response, 400, "Bad Request",
774 "max_silence_seconds cannot be negative");
775 return;
776 }
777
778 control = find_control(response, args->channel_id);
779 if (control == NULL) {
780 /* Response filled in by find_control */
781 return;
782 }
783
785 if (options == NULL) {
787 response, 500, "Internal Server Error",
788 "Out of memory");
789 }
790 ast_string_field_build(options, target, "channel:%s", args->channel_id);
791 options->max_silence_seconds = args->max_silence_seconds;
792 options->max_duration_seconds = args->max_duration_seconds;
793 options->terminate_on =
795 options->if_exists =
797 options->beep = args->beep;
798
799 if (options->terminate_on == STASIS_APP_RECORDING_TERMINATE_INVALID) {
801 response, 400, "Bad Request",
802 "terminateOn invalid");
803 return;
804 }
805
806 if (options->if_exists == AST_RECORD_IF_EXISTS_ERROR) {
808 response, 400, "Bad Request",
809 "ifExists invalid");
810 return;
811 }
812
813 if (!ast_get_format_for_file_ext(options->format)) {
815 response, 422, "Unprocessable Entity",
816 "specified format is unknown on this system");
817 return;
818 }
819
820 recording = stasis_app_control_record(control, options);
821 if (recording == NULL) {
822 switch(errno) {
823 case EINVAL:
824 /* While the arguments are invalid, we should have
825 * caught them prior to calling record.
826 */
828 response, 500, "Internal Server Error",
829 "Error parsing request");
830 break;
831 case EEXIST:
832 ast_ari_response_error(response, 409, "Conflict",
833 "Recording '%s' already exists and can not be overwritten",
834 args->name);
835 break;
836 case ENOMEM:
838 response, 500, "Internal Server Error",
839 "Out of memory");
840 break;
841 case EPERM:
843 response, 400, "Bad Request",
844 "Recording name invalid");
845 break;
846 default:
848 "Unrecognized recording error: %s\n",
849 strerror(errno));
851 response, 500, "Internal Server Error",
852 "Internal Server Error");
853 break;
854 }
855 return;
856 }
857
858 uri_name_maxlen = strlen(args->name) * 3;
859 uri_encoded_name = ast_malloc(uri_name_maxlen);
860 if (!uri_encoded_name) {
862 response, 500, "Internal Server Error",
863 "Out of memory");
864 return;
865 }
866 ast_uri_encode(args->name, uri_encoded_name, uri_name_maxlen,
868
869 if (ast_asprintf(&recording_url, "/recordings/live/%s",
870 uri_encoded_name) == -1) {
871 recording_url = NULL;
873 response, 500, "Internal Server Error",
874 "Out of memory");
875 return;
876 }
877
878 json = stasis_app_recording_to_json(recording);
879 if (!json) {
881 response, 500, "Internal Server Error",
882 "Out of memory");
883 return;
884 }
885
886 ast_ari_response_created(response, recording_url, json);
887}
888
891 struct ast_ari_response *response)
892{
893 struct ast_channel_snapshot *snapshot;
894
895 snapshot = ast_channel_snapshot_get_latest(args->channel_id);
896 if (!snapshot) {
898 response, 404, "Not Found",
899 "Channel not found");
900 return;
901 }
902
903 ast_ari_response_ok(response,
905 ao2_ref(snapshot, -1);
906}
907
910 struct ast_ari_response *response)
911{
912 RAII_VAR(struct ast_channel *, chan, NULL, ao2_cleanup);
913 int cause;
914
915 chan = ast_channel_get_by_name(args->channel_id);
916 if (chan == NULL) {
918 response, 404, "Not Found",
919 "Channel not found");
920 return;
921 }
922
923 if (!ast_strlen_zero(args->reason) && !ast_strlen_zero(args->reason_code)) {
924 ast_ari_response_error(response, 400, "Bad Request",
925 "The reason and reason_code can't both be specified");
926 return;
927 }
928
929 if (!ast_strlen_zero(args->reason_code)) {
930 /* reason_code allows any hangup code */
931 if (sscanf(args->reason_code, "%30d", &cause) != 1) {
933 response, 400, "Invalid Reason Code",
934 "Invalid reason for hangup reason code provided");
935 return;
936 }
937 } else if (!ast_strlen_zero(args->reason)) {
938 /* reason allows only listed hangup reason */
939 cause = convert_reason_to_hangup_code(args->reason);
940 if (cause == -1) {
942 response, 400, "Invalid Reason",
943 "Invalid reason for hangup reason provided");
944 return;
945 }
946 } else {
947 /* not specified. set default hangup */
948 cause = AST_CAUSE_NORMAL;
949 }
950
951 ast_channel_hangupcause_set(chan, cause);
953
955}
956
959 struct ast_ari_response *response)
960{
961 RAII_VAR(struct ao2_container *, snapshots, NULL, ao2_cleanup);
962 RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
963 struct ao2_iterator i;
964 void *obj;
966
967 snapshots = ast_channel_cache_all();
968
969 json = ast_json_array_create();
970 if (!json) {
972 return;
973 }
974
975 i = ao2_iterator_init(snapshots, 0);
976 while ((obj = ao2_iterator_next(&i))) {
977 struct ast_channel_snapshot *snapshot = obj;
978 int r;
979
980 if (sanitize && sanitize->channel_snapshot
981 && sanitize->channel_snapshot(snapshot)) {
982 ao2_ref(snapshot, -1);
983 continue;
984 }
985
987 json, ast_channel_snapshot_to_json(snapshot, NULL));
988 if (r != 0) {
991 ao2_ref(snapshot, -1);
992 return;
993 }
994 ao2_ref(snapshot, -1);
995 }
997
998 ast_ari_response_ok(response, ast_json_ref(json));
999}
1000
1001/*! \brief Structure used for origination */
1003 /*! \brief Dialplan context */
1005 /*! \brief Dialplan extension */
1007 /*! \brief Dialplan priority */
1009 /*! \brief Application data to pass to Stasis application */
1010 char appdata[0];
1011};
1012
1013/*! \brief Thread which dials and executes upon answer */
1014static void *ari_originate_dial(void *data)
1015{
1016 struct ast_dial *dial = data;
1017 struct ari_origination *origination = ast_dial_get_user_data(dial);
1018 enum ast_dial_result res;
1019
1020 res = ast_dial_run(dial, NULL, 0);
1021 if (res != AST_DIAL_RESULT_ANSWERED) {
1022 goto end;
1023 }
1024
1025 if (!ast_strlen_zero(origination->appdata)) {
1026 struct ast_app *app = pbx_findapp("Stasis");
1027
1028 if (app) {
1029 ast_verb(4, "Launching Stasis(%s) on %s\n", origination->appdata,
1031 pbx_exec(ast_dial_answered(dial), app, origination->appdata);
1032 } else {
1033 ast_log(LOG_WARNING, "No such application 'Stasis'\n");
1034 }
1035 } else {
1036 struct ast_channel *answered = ast_dial_answered(dial);
1037
1038 if (!ast_strlen_zero(origination->context)) {
1039 ast_channel_context_set(answered, origination->context);
1040 }
1041
1042 if (!ast_strlen_zero(origination->exten)) {
1043 ast_channel_exten_set(answered, origination->exten);
1044 }
1045
1046 if (origination->priority > 0) {
1047 ast_channel_priority_set(answered, origination->priority);
1048 }
1049
1050 if (ast_pbx_run(answered)) {
1051 ast_log(LOG_ERROR, "Failed to start PBX on %s\n", ast_channel_name(answered));
1052 } else {
1053 /* PBX will have taken care of hanging up, so we steal the answered channel so dial doesn't do it */
1055 }
1056 }
1057
1058end:
1059 ast_dial_destroy(dial);
1060 ast_free(origination);
1061 return NULL;
1062}
1063
1064static struct ast_channel *ari_channels_handle_originate_with_id(const char *args_endpoint,
1065 const char *args_extension,
1066 const char *args_context,
1067 long args_priority,
1068 const char *args_label,
1069 const char *args_app,
1070 const char *args_app_args,
1071 const char *args_caller_id,
1072 int args_timeout,
1073 struct ast_variable *variables,
1074 const char *args_channel_id,
1075 const char *args_other_channel_id,
1076 const char *args_originator,
1077 const char *args_formats,
1078 struct ast_ari_response *response)
1079{
1080 char *dialtech;
1081 char *dialdevice = NULL;
1082 struct ast_dial *dial;
1083 char *caller_id = NULL;
1084 char *cid_num = NULL;
1085 char *cid_name = NULL;
1086 char *stuff;
1087 struct ast_channel *other = NULL;
1088 struct ast_channel *chan = NULL;
1090 struct ast_assigned_ids assignedids = {
1091 .uniqueid = args_channel_id,
1092 .uniqueid2 = args_other_channel_id,
1093 };
1094 struct ari_origination *origination;
1095 pthread_t thread;
1096 struct ast_format_cap *format_cap = NULL;
1097
1098 if ((assignedids.uniqueid && AST_MAX_PUBLIC_UNIQUEID < strlen(assignedids.uniqueid))
1099 || (assignedids.uniqueid2 && AST_MAX_PUBLIC_UNIQUEID < strlen(assignedids.uniqueid2))) {
1100 ast_ari_response_error(response, 400, "Bad Request",
1101 "Uniqueid length exceeds maximum of %d", AST_MAX_PUBLIC_UNIQUEID);
1102 return NULL;
1103 }
1104
1105 if (ast_strlen_zero(args_endpoint)) {
1106 ast_ari_response_error(response, 400, "Bad Request",
1107 "Endpoint must be specified");
1108 return NULL;
1109 }
1110
1111 if (!ast_strlen_zero(args_originator) && !ast_strlen_zero(args_formats)) {
1112 ast_ari_response_error(response, 400, "Bad Request",
1113 "Originator and formats can't both be specified");
1114 return NULL;
1115 }
1116
1117 dialtech = ast_strdupa(args_endpoint);
1118 if ((stuff = strchr(dialtech, '/'))) {
1119 *stuff++ = '\0';
1120 dialdevice = stuff;
1121 }
1122
1123 if (ast_strlen_zero(dialtech) || ast_strlen_zero(dialdevice)) {
1124 ast_ari_response_error(response, 400, "Bad Request",
1125 "Invalid endpoint specified");
1126 return NULL;
1127 }
1128
1129 if (!ast_strlen_zero(args_app)) {
1130 RAII_VAR(struct ast_str *, appdata, ast_str_create(64), ast_free);
1131
1132 if (!appdata) {
1134 return NULL;
1135 }
1136
1137 ast_str_set(&appdata, 0, "%s", args_app);
1138 if (!ast_strlen_zero(args_app_args)) {
1139 ast_str_append(&appdata, 0, ",%s", args_app_args);
1140 }
1141
1142 origination = ast_calloc(1, sizeof(*origination) + ast_str_size(appdata) + 1);
1143 if (!origination) {
1145 return NULL;
1146 }
1147
1148 strcpy(origination->appdata, ast_str_buffer(appdata));
1149 } else if (!ast_strlen_zero(args_extension)) {
1150 origination = ast_calloc(1, sizeof(*origination) + 1);
1151 if (!origination) {
1153 return NULL;
1154 }
1155
1156 ast_copy_string(origination->context, S_OR(args_context, "default"), sizeof(origination->context));
1157 ast_copy_string(origination->exten, args_extension, sizeof(origination->exten));
1158
1159 if (!ast_strlen_zero(args_label)) {
1160 /* A label was provided in the request, use that */
1161 int ipri = 1;
1162 if (sscanf(args_label, "%30d", &ipri) != 1) {
1163 ipri = ast_findlabel_extension(chan, origination->context, origination->exten, args_label, args_caller_id);
1164
1165 if (ipri == -1) {
1166 ast_log(AST_LOG_ERROR, "Requested label: %s can not be found in context: %s\n", args_label, args_context);
1167 ast_ari_response_error(response, 404, "Not Found", "Requested label can not be found");
1168 return NULL;
1169 }
1170 } else {
1171 ast_debug(3, "Numeric value provided for label, jumping to that priority\n");
1172 }
1173
1174 if (ipri == 0) {
1175 ast_log(AST_LOG_ERROR, "Invalid priority label '%s' specified for extension %s in context: %s\n",
1176 args_label, args_extension, args_context);
1177 ast_ari_response_error(response, 400, "Bad Request", "Requested priority is illegal");
1178 return NULL;
1179 }
1180
1181 /* Our priority was provided by a label */
1182 origination->priority = ipri;
1183 } else {
1184 /* No label provided, use provided priority */
1185 origination->priority = args_priority ? args_priority : 1;
1186 }
1187
1188 origination->appdata[0] = '\0';
1189 } else {
1190 ast_ari_response_error(response, 400, "Bad Request",
1191 "Application or extension must be specified");
1192 return NULL;
1193 }
1194
1195 dial = ast_dial_create();
1196 if (!dial) {
1198 ast_free(origination);
1199 return NULL;
1200 }
1201 ast_dial_set_user_data(dial, origination);
1202
1203 if (ast_dial_append(dial, dialtech, dialdevice, &assignedids)) {
1205 ast_dial_destroy(dial);
1206 ast_free(origination);
1207 return NULL;
1208 }
1209
1210 if (args_timeout > 0) {
1211 ast_dial_set_global_timeout(dial, args_timeout * 1000);
1212 } else if (args_timeout == -1) {
1214 } else {
1215 ast_dial_set_global_timeout(dial, 30000);
1216 }
1217
1218 if (!ast_strlen_zero(args_caller_id)) {
1219 caller_id = ast_strdupa(args_caller_id);
1220 ast_callerid_parse(caller_id, &cid_name, &cid_num);
1221
1222 if (ast_is_shrinkable_phonenumber(cid_num)) {
1223 ast_shrink_phone_number(cid_num);
1224 }
1225 }
1226
1227 if (!ast_strlen_zero(args_originator)) {
1228 other = ast_channel_get_by_name(args_originator);
1229 if (!other) {
1231 response, 400, "Bad Request",
1232 "Provided originator channel was not found");
1233 ast_dial_destroy(dial);
1234 ast_free(origination);
1235 return NULL;
1236 }
1237 }
1238
1239 if (!ast_strlen_zero(args_formats)) {
1240 char *format_name;
1241 char *formats_copy = ast_strdupa(args_formats);
1242
1245 ast_dial_destroy(dial);
1246 ast_free(origination);
1247 ast_channel_cleanup(other);
1248 return NULL;
1249 }
1250
1251 while ((format_name = ast_strip(strsep(&formats_copy, ",")))) {
1252 struct ast_format *fmt = ast_format_cache_get(format_name);
1253
1254 if (!fmt || ast_format_cap_append(format_cap, fmt, 0)) {
1255 if (!fmt) {
1257 response, 400, "Bad Request",
1258 "Provided format (%s) was not found", format_name);
1259 } else {
1261 }
1262 ast_dial_destroy(dial);
1263 ast_free(origination);
1264 ast_channel_cleanup(other);
1265 ao2_ref(format_cap, -1);
1266 ao2_cleanup(fmt);
1267 return NULL;
1268 }
1269 ao2_ref(fmt, -1);
1270 }
1271 }
1272
1273 if (ast_dial_prerun(dial, other, format_cap)) {
1275 ast_ari_response_error(response, 409, "Conflict",
1276 "Channel with given unique ID already exists");
1277 } else {
1279 }
1280 ast_dial_destroy(dial);
1281 ast_free(origination);
1282 ast_channel_cleanup(other);
1283 return NULL;
1284 }
1285
1286 ast_channel_cleanup(other);
1287 ao2_cleanup(format_cap);
1288
1289 chan = ast_dial_get_channel(dial, 0);
1290 if (!chan) {
1292 ast_dial_destroy(dial);
1293 ast_free(origination);
1294 return NULL;
1295 }
1296
1297 if (!ast_strlen_zero(cid_num) || !ast_strlen_zero(cid_name)) {
1299
1300 /*
1301 * It seems strange to set the CallerID on an outgoing call leg
1302 * to whom we are calling, but this function's callers are doing
1303 * various Originate methods. This call leg goes to the local
1304 * user. Once the called party answers, the dialplan needs to
1305 * be able to access the CallerID from the CALLERID function as
1306 * if the called party had placed this call.
1307 */
1308 ast_set_callerid(chan, cid_num, cid_name, cid_num);
1309
1311 if (!ast_strlen_zero(cid_num)) {
1312 connected.id.number.valid = 1;
1313 connected.id.number.str = (char *) cid_num;
1315 }
1316 if (!ast_strlen_zero(cid_name)) {
1317 connected.id.name.valid = 1;
1318 connected.id.name.str = (char *) cid_name;
1320 }
1322 }
1323
1324 ast_channel_lock(chan);
1325 if (variables) {
1326 ast_set_variables(chan, variables);
1327 }
1329
1330 if (!ast_strlen_zero(args_app)) {
1331 struct ast_channel *local_peer;
1332
1333 stasis_app_subscribe_channel(args_app, chan);
1334
1335 /* Subscribe to the Local channel peer also. */
1336 local_peer = ast_local_get_peer(chan);
1337 if (local_peer) {
1338 stasis_app_subscribe_channel(args_app, local_peer);
1339 ast_channel_unref(local_peer);
1340 }
1341 }
1342
1344 ast_channel_unlock(chan);
1345
1346 /* Before starting the async dial bump the ref in case the dial quickly goes away and takes
1347 * the reference with it
1348 */
1349 ast_channel_ref(chan);
1350
1353 ast_dial_destroy(dial);
1354 ast_free(origination);
1355 } else {
1357 }
1358
1359 return chan;
1360}
1361
1362/*!
1363 * \internal
1364 * \brief Convert a \c ast_json list of key/value pair tuples into a \c ast_variable list
1365 * \since 13.3.0
1366 *
1367 * \param[out] response HTTP response if error
1368 * \param json_variables The JSON blob containing the variable
1369 * \param[out] variables An out reference to the variables to populate.
1370 *
1371 * \retval 0 on success.
1372 * \retval -1 on error.
1373 */
1374static int json_to_ast_variables(struct ast_ari_response *response, struct ast_json *json_variables, struct ast_variable **variables)
1375{
1377
1378 res = ast_json_to_ast_variables(json_variables, variables);
1379 switch (res) {
1381 return 0;
1383 ast_ari_response_error(response, 400, "Bad Request",
1384 "Only string values in the 'variables' object allowed");
1385 break;
1388 break;
1389 }
1390 ast_log(AST_LOG_ERROR, "Unable to convert 'variables' in JSON body to channel variables\n");
1391
1392 return -1;
1393}
1394
1397 struct ast_ari_response *response)
1398{
1399 struct ast_variable *variables = NULL;
1400 struct ast_channel *chan;
1401
1402 /* Parse any query parameters out of the body parameter */
1403 if (args->variables) {
1404 struct ast_json *json_variables;
1405
1407 json_variables = ast_json_object_get(args->variables, "variables");
1408 if (json_variables
1409 && json_to_ast_variables(response, json_variables, &variables)) {
1410 return;
1411 }
1412 }
1413
1415 args->endpoint,
1416 args->extension,
1417 args->context,
1418 args->priority,
1419 args->label,
1420 args->app,
1421 args->app_args,
1422 args->caller_id,
1423 args->timeout,
1424 variables,
1425 args->channel_id,
1426 args->other_channel_id,
1427 args->originator,
1428 args->formats,
1429 response);
1430 ast_channel_cleanup(chan);
1431 ast_variables_destroy(variables);
1432}
1433
1436 struct ast_ari_response *response)
1437{
1438 struct ast_variable *variables = NULL;
1439 struct ast_channel *chan;
1440
1441 /* Parse any query parameters out of the body parameter */
1442 if (args->variables) {
1443 struct ast_json *json_variables;
1444
1446 json_variables = ast_json_object_get(args->variables, "variables");
1447 if (json_variables
1448 && json_to_ast_variables(response, json_variables, &variables)) {
1449 return;
1450 }
1451 }
1452
1454 args->endpoint,
1455 args->extension,
1456 args->context,
1457 args->priority,
1458 args->label,
1459 args->app,
1460 args->app_args,
1461 args->caller_id,
1462 args->timeout,
1463 variables,
1464 args->channel_id,
1465 args->other_channel_id,
1466 args->originator,
1467 args->formats,
1468 response);
1469 ast_channel_cleanup(chan);
1470 ast_variables_destroy(variables);
1471}
1472
1475 struct ast_ari_response *response)
1476{
1477 RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
1478 RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
1479 RAII_VAR(struct ast_str *, value, ast_str_create(32), ast_free);
1480 RAII_VAR(struct ast_channel *, channel, NULL, ast_channel_cleanup);
1481
1482 ast_assert(response != NULL);
1483
1484 if (!value) {
1486 return;
1487 }
1488
1489 if (ast_strlen_zero(args->variable)) {
1491 response, 400, "Bad Request",
1492 "Variable name is required");
1493 return;
1494 }
1495
1496 if (ast_strlen_zero(args->channel_id)) {
1498 response, 400, "Bad Request",
1499 "Channel ID is required");
1500 return;
1501 }
1502
1503 channel = ast_channel_get_by_name(args->channel_id);
1504 if (!channel) {
1506 response, 404, "Channel Not Found",
1507 "Provided channel was not found");
1508 return;
1509 }
1510
1511 /* You may be tempted to lock the channel you're about to read from. You
1512 * would be wrong. Some dialplan functions put the channel into
1513 * autoservice, which deadlocks if the channel is already locked.
1514 * ast_str_retrieve_variable() does its own locking, and the dialplan
1515 * functions need to as well. We should be fine without the lock.
1516 */
1517
1518 if (args->variable[strlen(args->variable) - 1] == ')') {
1519 if (ast_func_read2(channel, args->variable, &value, 0)) {
1521 response, 500, "Error With Function",
1522 "Unable to read provided function");
1523 return;
1524 }
1525 } else {
1526 if (!ast_str_retrieve_variable(&value, 0, channel, NULL, args->variable)) {
1528 response, 404, "Variable Not Found",
1529 "Provided variable was not found");
1530 return;
1531 }
1532 }
1533
1534 if (!(json = ast_json_pack("{s: s}", "value", S_OR(ast_str_buffer(value), "")))) {
1536 return;
1537 }
1538
1539 ast_ari_response_ok(response, ast_json_ref(json));
1540}
1541
1544 struct ast_ari_response *response)
1545{
1546 RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
1547
1548 ast_assert(response != NULL);
1549
1550 if (ast_strlen_zero(args->variable)) {
1552 response, 400, "Bad Request",
1553 "Variable name is required");
1554 return;
1555 }
1556
1557 control = find_control(response, args->channel_id);
1558 if (control == NULL) {
1559 /* response filled in by find_control */
1560 return;
1561 }
1562
1563 if (stasis_app_control_set_channel_var(control, args->variable, args->value)) {
1565 response, 400, "Bad Request",
1566 "Failed to execute function");
1567 return;
1568 }
1569
1571}
1572
1574 const char *args_channel_id,
1575 const char *args_spy,
1576 const char *args_whisper,
1577 const char *args_app,
1578 const char *args_app_args,
1579 const char *args_snoop_id,
1580 struct ast_ari_response *response)
1581{
1582 enum stasis_app_snoop_direction spy, whisper;
1583 RAII_VAR(struct ast_channel *, chan, NULL, ast_channel_cleanup);
1584 RAII_VAR(struct ast_channel *, snoop, NULL, ast_channel_cleanup);
1585 RAII_VAR(struct ast_channel_snapshot *, snapshot, NULL, ao2_cleanup);
1586
1587 ast_assert(response != NULL);
1588
1589 if (ast_strlen_zero(args_spy) || !strcmp(args_spy, "none")) {
1591 } else if (!strcmp(args_spy, "both")) {
1593 } else if (!strcmp(args_spy, "out")) {
1595 } else if (!strcmp(args_spy, "in")) {
1597 } else {
1599 response, 400, "Bad Request",
1600 "Invalid direction specified for spy");
1601 return;
1602 }
1603
1604 if (ast_strlen_zero(args_whisper) || !strcmp(args_whisper, "none")) {
1606 } else if (!strcmp(args_whisper, "both")) {
1608 } else if (!strcmp(args_whisper, "out")) {
1610 } else if (!strcmp(args_whisper, "in")) {
1611 whisper = STASIS_SNOOP_DIRECTION_IN;
1612 } else {
1614 response, 400, "Bad Request",
1615 "Invalid direction specified for whisper");
1616 return;
1617 }
1618
1621 response, 400, "Bad Request",
1622 "Direction must be specified for at least spy or whisper");
1623 return;
1624 } else if (ast_strlen_zero(args_app)) {
1626 response, 400, "Bad Request",
1627 "Application name is required");
1628 return;
1629 }
1630
1631 chan = ast_channel_get_by_name(args_channel_id);
1632 if (chan == NULL) {
1634 response, 404, "Channel Not Found",
1635 "Provided channel was not found");
1636 return;
1637 }
1638
1639 snoop = stasis_app_control_snoop(chan, spy, whisper, args_app, args_app_args,
1640 args_snoop_id);
1641 if (snoop == NULL) {
1643 response, 500, "Internal error",
1644 "Snoop channel could not be created");
1645 return;
1646 }
1647
1650}
1651
1654 struct ast_ari_response *response)
1655{
1657 args->channel_id,
1658 args->spy,
1659 args->whisper,
1660 args->app,
1661 args->app_args,
1662 args->snoop_id,
1663 response);
1664}
1665
1668 struct ast_ari_response *response)
1669{
1671 args->channel_id,
1672 args->spy,
1673 args->whisper,
1674 args->app,
1675 args->app_args,
1676 args->snoop_id,
1677 response);
1678}
1679
1683};
1684
1685static void chan_data_destroy(struct ari_channel_thread_data *chan_data)
1686{
1687 ast_free(chan_data->stasis_stuff);
1688 ast_hangup(chan_data->chan);
1689 ast_free(chan_data);
1690}
1691
1692/*!
1693 * \brief Thread that owns stasis-created channel.
1694 *
1695 * The channel enters into a Stasis application immediately upon creation. In this
1696 * way, the channel can be manipulated by the Stasis application. Once the channel
1697 * exits the Stasis application, it is hung up.
1698 */
1699static void *ari_channel_thread(void *data)
1700{
1701 struct ari_channel_thread_data *chan_data = data;
1702 struct ast_app *stasis_app;
1703
1704 stasis_app = pbx_findapp("Stasis");
1705 if (!stasis_app) {
1706 ast_log(LOG_ERROR, "Stasis dialplan application is not registered");
1707 chan_data_destroy(chan_data);
1708 return NULL;
1709 }
1710
1711 pbx_exec(chan_data->chan, stasis_app, ast_str_buffer(chan_data->stasis_stuff));
1712
1713 chan_data_destroy(chan_data);
1714
1715 return NULL;
1716}
1717
1719 .type = "ARI Dialstring",
1720 .destroy = ast_free_ptr,
1721};
1722
1723/*!
1724 * \brief Save dialstring onto a channel datastore
1725 *
1726 * This will later be retrieved when it comes time to actually dial the channel
1727 *
1728 * \param chan The channel on which to save the dialstring
1729 * \param dialstring The dialstring to save
1730 * \retval 0 on success.
1731 * \retval -1 on error.
1732 */
1733static int save_dialstring(struct ast_channel *chan, const char *dialstring)
1734{
1735 struct ast_datastore *datastore;
1736
1738 if (!datastore) {
1739 return -1;
1740 }
1741
1742 datastore->data = ast_strdup(dialstring);
1743 if (!datastore->data) {
1744 ast_datastore_free(datastore);
1745 return -1;
1746 }
1747
1748 ast_channel_lock(chan);
1749 if (ast_channel_datastore_add(chan, datastore)) {
1750 ast_channel_unlock(chan);
1751 ast_datastore_free(datastore);
1752 return -1;
1753 }
1754 ast_channel_unlock(chan);
1755
1756 return 0;
1757}
1758
1759/*!
1760 * \brief Retrieve the dialstring from the channel datastore
1761 *
1762 * \pre chan is locked
1763 * \param chan Channel that was previously created in ARI
1764 * \retval NULL Failed to find datastore
1765 * \retval non-NULL The dialstring
1766 */
1767static char *restore_dialstring(struct ast_channel *chan)
1768{
1769 struct ast_datastore *datastore;
1770
1771 datastore = ast_channel_datastore_find(chan, &dialstring_info, NULL);
1772 if (!datastore) {
1773 return NULL;
1774 }
1775
1776 return datastore->data;
1777}
1778
1781 struct ast_ari_response *response)
1782{
1783 RAII_VAR(struct ast_variable *, variables, NULL, ast_variables_destroy);
1784 struct ast_assigned_ids assignedids;
1785 struct ari_channel_thread_data *chan_data;
1786 struct ast_channel_snapshot *snapshot;
1787 pthread_t thread;
1788 char *dialtech;
1789 char *dialdevice = NULL;
1790 char *stuff;
1791 int cause;
1792 struct ast_format_cap *request_cap;
1793 struct ast_channel *originator;
1794
1795 /* Parse any query parameters out of the body parameter */
1796 if (args->variables) {
1797 struct ast_json *json_variables;
1798
1800 json_variables = ast_json_object_get(args->variables, "variables");
1801 if (json_variables
1802 && json_to_ast_variables(response, json_variables, &variables)) {
1803 return;
1804 }
1805 }
1806
1807 assignedids.uniqueid = args->channel_id;
1808 assignedids.uniqueid2 = args->other_channel_id;
1809
1810 if (!ast_strlen_zero(args->originator) && !ast_strlen_zero(args->formats)) {
1811 ast_ari_response_error(response, 400, "Bad Request",
1812 "Originator and formats can't both be specified");
1813 return;
1814 }
1815
1816 if (ast_strlen_zero(args->endpoint)) {
1817 ast_ari_response_error(response, 400, "Bad Request",
1818 "Endpoint must be specified");
1819 return;
1820 }
1821
1822 chan_data = ast_calloc(1, sizeof(*chan_data));
1823 if (!chan_data) {
1825 return;
1826 }
1827
1828 chan_data->stasis_stuff = ast_str_create(32);
1829 if (!chan_data->stasis_stuff) {
1831 chan_data_destroy(chan_data);
1832 return;
1833 }
1834
1835 ast_str_append(&chan_data->stasis_stuff, 0, "%s", args->app);
1836 if (!ast_strlen_zero(args->app_args)) {
1837 ast_str_append(&chan_data->stasis_stuff, 0, ",%s", args->app_args);
1838 }
1839
1840 dialtech = ast_strdupa(args->endpoint);
1841 if ((stuff = strchr(dialtech, '/'))) {
1842 *stuff++ = '\0';
1843 dialdevice = stuff;
1844 }
1845
1846 if (ast_strlen_zero(dialtech) || ast_strlen_zero(dialdevice)) {
1847 ast_ari_response_error(response, 400, "Bad Request",
1848 "Invalid endpoint specified");
1849 chan_data_destroy(chan_data);
1850 return;
1851 }
1852
1853 originator = ast_channel_get_by_name(args->originator);
1854 if (originator) {
1855 request_cap = ao2_bump(ast_channel_nativeformats(originator));
1856 if (!ast_strlen_zero(args->app)) {
1857 stasis_app_subscribe_channel(args->app, originator);
1858 }
1859 } else if (!ast_strlen_zero(args->formats)) {
1860 char *format_name;
1861 char *formats_copy = ast_strdupa(args->formats);
1862
1863 if (!(request_cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
1865 chan_data_destroy(chan_data);
1866 return;
1867 }
1868
1869 while ((format_name = ast_strip(strsep(&formats_copy, ",")))) {
1870 struct ast_format *fmt = ast_format_cache_get(format_name);
1871
1872 if (!fmt || ast_format_cap_append(request_cap, fmt, 0)) {
1873 if (!fmt) {
1875 response, 400, "Bad Request",
1876 "Provided format (%s) was not found", format_name);
1877 } else {
1879 }
1880 ao2_ref(request_cap, -1);
1881 ao2_cleanup(fmt);
1882 chan_data_destroy(chan_data);
1883 return;
1884 }
1885 ao2_ref(fmt, -1);
1886 }
1887 } else {
1888 if (!(request_cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
1890 chan_data_destroy(chan_data);
1891 return;
1892 }
1893
1895 }
1896
1897 chan_data->chan = ast_request(dialtech, request_cap, &assignedids, originator, dialdevice, &cause);
1898 ao2_cleanup(request_cap);
1899
1900 if (!chan_data->chan) {
1902 ast_ari_response_error(response, 409, "Conflict",
1903 "Channel with given unique ID already exists");
1904 } else {
1906 }
1907 ast_channel_cleanup(originator);
1908 chan_data_destroy(chan_data);
1909 return;
1910 }
1911
1912 if (!ast_strlen_zero(args->app)) {
1913 stasis_app_subscribe_channel(args->app, chan_data->chan);
1914 }
1915
1916 if (variables) {
1917 ast_set_variables(chan_data->chan, variables);
1918 }
1919
1920 ast_channel_cleanup(originator);
1921
1922 if (save_dialstring(chan_data->chan, stuff)) {
1924 chan_data_destroy(chan_data);
1925 return;
1926 }
1927
1929
1932 chan_data_destroy(chan_data);
1933 } else {
1935 }
1936
1937 ao2_ref(snapshot, -1);
1938}
1939
1942 struct ast_ari_response *response)
1943{
1944 RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
1945 RAII_VAR(struct ast_channel *, caller, NULL, ast_channel_cleanup);
1946 RAII_VAR(struct ast_channel *, callee, NULL, ast_channel_cleanup);
1947 char *dialstring;
1948
1949 control = find_control(response, args->channel_id);
1950 if (control == NULL) {
1951 /* Response filled in by find_control */
1952 return;
1953 }
1954
1955 caller = ast_channel_get_by_name(args->caller);
1956
1957 callee = ast_channel_get_by_name(args->channel_id);
1958 if (!callee) {
1959 ast_ari_response_error(response, 404, "Not Found",
1960 "Callee not found");
1961 return;
1962 }
1963
1964 if (ast_channel_state(callee) != AST_STATE_DOWN
1965 && ast_channel_state(callee) != AST_STATE_RESERVED) {
1966 ast_ari_response_error(response, 409, "Conflict",
1967 "Channel is not in the 'Down' state");
1968 return;
1969 }
1970
1971 /* XXX This is straight up copied from main/dial.c. It's probably good
1972 * to separate this to some common method.
1973 */
1974 if (caller) {
1975 ast_channel_lock_both(caller, callee);
1976 } else {
1977 ast_channel_lock(callee);
1978 }
1979
1980 dialstring = restore_dialstring(callee);
1981 if (!dialstring) {
1982 ast_channel_unlock(callee);
1983 if (caller) {
1984 ast_channel_unlock(caller);
1985 }
1986 ast_ari_response_error(response, 409, "Conflict",
1987 "Dialing a channel not created by ARI");
1988 return;
1989 }
1990 /* Make a copy of the dialstring just in case some jerk tries to hang up the
1991 * channel before we can actually dial
1992 */
1993 dialstring = ast_strdupa(dialstring);
1994
1996 if (caller) {
1997 ast_channel_inherit_variables(caller, callee);
1998 ast_channel_datastore_inherit(caller, callee);
2000
2001 /* Copy over callerid information */
2003
2005
2007
2008 ast_channel_language_set(callee, ast_channel_language(caller));
2011 ast_channel_musicclass_set(callee, ast_channel_musicclass(caller));
2012
2015 ast_channel_unlock(caller);
2016 }
2017
2019 ast_channel_unlock(callee);
2020
2021 if (stasis_app_control_dial(control, dialstring, args->timeout)) {
2023 return;
2024 }
2025
2027}
2028
2031 struct ast_ari_response *response)
2032{
2033 RAII_VAR(struct ast_channel *, chan, NULL, ast_channel_cleanup);
2034 RAII_VAR(struct ast_rtp_instance *, rtp, NULL, ao2_cleanup);
2035 struct ast_json *j_res;
2036 const struct ast_channel_tech *tech;
2037 struct ast_rtp_glue *glue;
2038
2039 chan = ast_channel_get_by_name(args->channel_id);
2040 if (!chan) {
2041 ast_ari_response_error(response, 404, "Not Found",
2042 "Channel not found");
2043 return;
2044 }
2045
2046 ast_channel_lock(chan);
2047 tech = ast_channel_tech(chan);
2048 if (!tech) {
2049 ast_channel_unlock(chan);
2050 ast_ari_response_error(response, 404, "Not Found",
2051 "Channel's tech not found");
2052 return;
2053 }
2054
2055 glue = ast_rtp_instance_get_glue(tech->type);
2056 if (!glue) {
2057 ast_channel_unlock(chan);
2058 ast_ari_response_error(response, 403, "Forbidden",
2059 "Unsupported channel type");
2060 return;
2061 }
2062
2063 glue->get_rtp_info(chan, &rtp);
2064 if (!rtp) {
2065 ast_channel_unlock(chan);
2066 ast_ari_response_error(response, 404, "Not Found",
2067 "RTP info not found");
2068 return;
2069 }
2070
2072 if (!j_res) {
2073 ast_channel_unlock(chan);
2074 ast_ari_response_error(response, 404, "Not Found",
2075 "Statistics not found");
2076 return;
2077 }
2078
2079 ast_channel_unlock(chan);
2080 ast_ari_response_ok(response, j_res);
2081
2082 return;
2083}
2084
2086 struct ast_variable *variables,
2087 struct ast_ari_response *response)
2088{
2089 char *endpoint;
2090 struct ast_channel *chan;
2091 struct varshead *vars;
2092
2093 if (ast_asprintf(&endpoint, "UnicastRTP/%s/c(%s)",
2094 args->external_host,
2095 args->format) == -1) {
2096 return 1;
2097 }
2098
2100 endpoint,
2101 NULL,
2102 NULL,
2103 0,
2104 NULL,
2105 args->app,
2106 args->data,
2107 NULL,
2108 0,
2109 variables,
2110 args->channel_id,
2111 NULL,
2112 NULL,
2113 args->format,
2114 response);
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 char *endpoint;
2137 struct ast_channel *chan;
2138 struct varshead *vars;
2139
2140 if (ast_strlen_zero(args->data)) {
2141 ast_ari_response_error(response, 400, "Bad Request", "data can not be empty");
2142 return 1;
2143 }
2144
2145 if (ast_asprintf(&endpoint, "AudioSocket/%s/%s",
2146 args->external_host, args->data) == -1) {
2147 return 1;
2148 }
2149
2151 endpoint,
2152 NULL,
2153 NULL,
2154 0,
2155 NULL,
2156 args->app,
2157 args->data,
2158 NULL,
2159 0,
2160 variables,
2161 args->channel_id,
2162 NULL,
2163 NULL,
2164 args->format,
2165 response);
2166
2167 ast_free(endpoint);
2168
2169 if (!chan) {
2170 return 1;
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 return 0;
2181}
2182
2184 struct ast_variable *variables,
2185 struct ast_ari_response *response)
2186{
2187 char *endpoint;
2188 struct ast_channel *chan;
2189 struct varshead *vars;
2190
2191 if (ast_asprintf(&endpoint, "WebSocket/%s/c(%s)",
2192 args->external_host,
2193 args->format) == -1) {
2194 return 1;
2195 }
2196
2198 endpoint,
2199 NULL,
2200 NULL,
2201 0,
2202 NULL,
2203 args->app,
2204 args->data,
2205 NULL,
2206 0,
2207 variables,
2208 args->channel_id,
2209 NULL,
2210 NULL,
2211 args->format,
2212 response);
2213
2214 ast_free(endpoint);
2215
2216 if (!chan) {
2217 return 1;
2218 }
2219
2220 ast_channel_lock(chan);
2221 vars = ast_channel_varshead(chan);
2222 if (vars && !AST_LIST_EMPTY(vars)) {
2223 ast_json_object_set(response->message, "channelvars", ast_json_channel_vars(vars));
2224 }
2225 ast_channel_unlock(chan);
2226 ast_channel_unref(chan);
2227 return 0;
2228}
2229
2230#include "asterisk/config.h"
2231#include "asterisk/netsock2.h"
2232
2235{
2236 RAII_VAR(struct ast_variable *, variables, NULL, ast_variables_destroy);
2237 char *external_host;
2238 char *host = NULL;
2239 char *port = NULL;
2240
2241 ast_assert(response != NULL);
2242
2243 /* Parse any query parameters out of the body parameter */
2244 if (args->variables) {
2245 struct ast_json *json_variables;
2246
2248 json_variables = ast_json_object_get(args->variables, "variables");
2249 if (json_variables
2250 && json_to_ast_variables(response, json_variables, &variables)) {
2251 return;
2252 }
2253 }
2254
2255 if (ast_strlen_zero(args->app)) {
2256 ast_ari_response_error(response, 400, "Bad Request", "app cannot be empty");
2257 return;
2258 }
2259
2260 if (ast_strlen_zero(args->transport)) {
2261 args->transport = "udp";
2262 }
2263
2264 if (ast_strlen_zero(args->encapsulation)) {
2265 args->encapsulation = "rtp";
2266 }
2267 if (ast_strings_equal(args->transport, "websocket")) {
2268 if (!ast_strings_equal(args->encapsulation, "none")) {
2269 ast_ari_response_error(response, 400, "Bad Request", "encapsulation must be 'none' for websocket transport");
2270 return;
2271 }
2272 }
2273
2274 if (ast_strings_equal(args->encapsulation, "rtp")) {
2275 if (!ast_strings_equal(args->transport, "udp")) {
2276 ast_ari_response_error(response, 400, "Bad Request", "transport must be 'udp' for rtp encapsulation");
2277 return;
2278 }
2279 }
2280
2281 if (ast_strings_equal(args->encapsulation, "audiosocket")) {
2282 if (!ast_strings_equal(args->transport, "tcp")) {
2283 ast_ari_response_error(response, 400, "Bad Request", "transport must be 'tcp' for audiosocket encapsulation");
2284 return;
2285 }
2286 }
2287
2288 if (ast_strlen_zero(args->connection_type)) {
2289 args->connection_type = "client";
2290 }
2291 if (!ast_strings_equal(args->transport, "websocket")) {
2292 if (ast_strings_equal(args->connection_type, "server")) {
2293 ast_ari_response_error(response, 400, "Bad Request", "'server' connection_type can only be used with the websocket transport");
2294 return;
2295 }
2296 }
2297
2298 if (ast_strlen_zero(args->external_host)) {
2299 if (ast_strings_equal(args->connection_type, "client")) {
2300 ast_ari_response_error(response, 400, "Bad Request", "external_host is required for all but websocket server connections");
2301 return;
2302 } else {
2303 /* server is only valid for websocket, enforced above */
2304 args->external_host = "INCOMING";
2305 }
2306 }
2307
2308 if (ast_strings_equal(args->transport, "websocket")) {
2309 if (ast_strings_equal(args->connection_type, "client")) {
2310 struct ast_websocket_client *ws_client =
2312 ao2_cleanup(ws_client);
2313 if (!ws_client) {
2314 ast_ari_response_error(response, 400, "Bad Request", "external_host must be a valid websocket_client connection id.");
2315 return;
2316 }
2317 }
2318 } else {
2319 external_host = ast_strdupa(args->external_host);
2320 if (!ast_sockaddr_split_hostport(external_host, &host, &port, PARSE_PORT_REQUIRE)) {
2321 ast_ari_response_error(response, 400, "Bad Request", "external_host must be <host>:<port> for all transports other than websocket");
2322 return;
2323 }
2324 }
2325
2326 if (ast_strlen_zero(args->format)) {
2327 ast_ari_response_error(response, 400, "Bad Request", "format cannot be empty");
2328 return;
2329 }
2330
2331 if (ast_strlen_zero(args->direction)) {
2332 args->direction = "both";
2333 }
2334
2335 if (strcasecmp(args->encapsulation, "rtp") == 0 && strcasecmp(args->transport, "udp") == 0) {
2336 if (external_media_rtp_udp(args, variables, response)) {
2338 response, 500, "Internal Server Error",
2339 "An internal error prevented this request from being handled");
2340 }
2341 } else if (strcasecmp(args->encapsulation, "audiosocket") == 0 && strcasecmp(args->transport, "tcp") == 0) {
2342 if (external_media_audiosocket_tcp(args, variables, response)) {
2344 response, 500, "Internal Server Error",
2345 "An internal error prevented this request from being handled");
2346 }
2347 } else if (strcasecmp(args->encapsulation, "none") == 0 && strcasecmp(args->transport, "websocket") == 0) {
2348 if (external_media_websocket(args, variables, response)) {
2350 response, 500, "Internal Server Error",
2351 "An internal error prevented this request from being handled");
2352 }
2353 } else {
2355 response, 501, "Not Implemented",
2356 "The encapsulation and/or transport is not supported");
2357 }
2358}
2359
2361{
2363 RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
2364 RAII_VAR(struct ast_channel *, chan, NULL, ast_channel_cleanup);
2365
2366 control = find_control(response, args->channel_id);
2367 if (control == NULL) {
2368 /* Response filled in by find_control */
2369 return;
2370 }
2371
2372 chan = ast_channel_get_by_name(args->channel_id);
2373 if (!chan) {
2374 ast_ari_response_error(response, 404, "Not Found",
2375 "Callee not found");
2376 return;
2377 }
2378
2379 if (ast_strlen_zero(args->states)) {
2380 ast_ari_response_error(response, 400, "Bad Request", "states must not be empty");
2381 return;
2382 }
2383
2384 if (strcasecmp(args->states, "channel_progress") == 0) {
2386 } else if (strcasecmp(args->states, "channel_answered") == 0) {
2388 } else if (strcasecmp(args->states, "channel_unavailable") == 0) {
2390 } else if (strcasecmp(args->states, "channel_declined") == 0) {
2392 } else {
2393 ast_ari_response_error(response, 400, "Bad Request", "Invalid states value");
2394 return;
2395 }
2396
2399}
static const char app[]
Definition: app_adsiprog.c:56
pthread_t thread
Definition: app_sla.c:335
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:258
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:212
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:229
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:251
void ast_ari_response_no_content(struct ast_ari_response *response)
Fill in a No Content (204) ast_ari_response.
Definition: res_ari.c:237
char * strsep(char **str, const char *delims)
Asterisk main include file. File version handling, generic pbx functions.
#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:1162
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:1101
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:1157
#define AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED
Definition: callerid.h:437
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:348
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:10962
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
Definition: channel.c:2354
void ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition: channel.c:2510
struct varshead * ast_channel_varshead(struct ast_channel *chan)
@ AST_CHANNEL_REQUESTOR_BRIDGE_PEER
Definition: channel.h:1525
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:8309
const char * ast_channel_musicclass(const struct ast_channel *chan)
#define ast_channel_lock(chan)
Definition: channel.h:2972
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:8116
struct ast_flags * ast_channel_flags(struct ast_channel *chan)
@ AST_CHANNEL_ERROR_ID_EXISTS
Definition: channel.h:4875
#define ast_channel_ref(c)
Increase channel reference count.
Definition: channel.h:2997
#define ast_channel_lock_both(chan1, chan2)
Lock two channels.
Definition: channel.h:2979
struct ast_party_connected_line * ast_channel_connected(struct ast_channel *chan)
@ AST_FLAG_ORIGINATED
Definition: channel.h:1059
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:2337
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:6389
#define AST_MUTE_DIRECTION_READ
Definition: channel.h:4790
ast_channel_adsicpe
Definition: channel.h:888
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:7303
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:6731
struct ast_channel * ast_channel_get_by_name(const char *search)
Find a channel by name or uniqueid.
Definition: channel.c:1397
@ AST_SOFTHANGUP_EXPLICIT
Definition: channel.h:1168
struct ast_party_dialed * ast_channel_dialed(struct ast_channel *chan)
int ast_indicate_data(struct ast_channel *chan, int condition, const void *data, size_t datalen)
Indicates condition of channel, with payload.
Definition: channel.c:4608
int ast_softhangup(struct ast_channel *chan, int cause)
Softly hangup up a channel.
Definition: channel.c:2440
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:3008
#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:8294
#define AST_MUTE_DIRECTION_WRITE
Definition: channel.h:4791
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:2012
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:3019
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:6309
#define ast_channel_unlock(chan)
Definition: channel.h:2973
#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:2102
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:2368
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:288
#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:2014
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
Configuration File Parser.
@ PARSE_PORT_REQUIRE
void ast_variables_destroy(struct ast_variable *var)
Free variable list.
Definition: extconf.c:1262
ast_control_transfer
@ AST_TRANSFER_FAILED
@ AST_TRANSFER_UNAVAILABLE
@ AST_TRANSFER_SUCCESS
@ AST_TRANSFER_PROGRESS
ast_frame_type
Frame types.
@ AST_FRAME_VOICE
@ AST_CONTROL_TRANSFER
#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:941
#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:4195
enum ast_pbx_result ast_pbx_run(struct ast_channel *c)
Execute the PBX in the current thread.
Definition: pbx.c:4770
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 external_media_audiosocket_tcp(struct ast_ari_channels_external_media_args *args, struct ast_variable *variables, struct ast_ari_response *response)
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_transfer_progress(struct ast_variable *headers, struct ast_ari_channels_transfer_progress_args *args, struct ast_ari_response *response)
Inform the channel about the progress of the attended/blind transfer.
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 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.
static int external_media_websocket(struct ast_ari_channels_external_media_args *args, struct ast_variable *variables, struct ast_ari_response *response)
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:4271
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:2388
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:2343
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:806
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:685
void stasis_app_control_unhold(struct stasis_app_control *control)
Remove the channel associated with the control from hold.
Definition: control.c:787
void stasis_app_control_silence_start(struct stasis_app_control *control)
Start playing silence to a channel.
Definition: control.c:858
void stasis_app_control_silence_stop(struct stasis_app_control *control)
Stop playing silence to a channel.
Definition: control.c:881
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:415
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:526
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:824
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:477
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:657
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:2063
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:591
void stasis_app_control_hold(struct stasis_app_control *control)
Place the channel associated with the control on hold.
Definition: control.c:774
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:633
int stasis_app_control_dial(struct stasis_app_control *control, const char *dialstring, unsigned int timeout)
Dial a channel.
Definition: control.c:1696
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:886
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:737
int stasis_app_control_ring(struct stasis_app_control *control)
Indicate ringing to the channel associated with this control.
Definition: control.c:618
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
int ast_strings_equal(const char *str1, const char *str2)
Compare strings for equality checking for NULL.
Definition: strings.c:238
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:103
Structure to pass both assignedid values to channel drivers.
Definition: channel.h:606
const char * uniqueid2
Definition: channel.h:608
const char * uniqueid
Definition: channel.h:607
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:648
const char *const type
Definition: channel.h:649
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:458
int transit_network_select
Transit Network Select.
Definition: channel.h:399
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:787
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:947
#define ast_assert(a)
Definition: utils.h:745
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:594
#define ast_set_flag(p, flag)
Definition: utils.h:70
struct ast_websocket_client * ast_websocket_client_retrieve_by_id(const char *id)
Retrieve a websocket client object by ID.