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