Asterisk - The Open Source Telephony Project  GIT-master-a24979a
Data Structures | Functions | Variables
resource_channels.c File Reference

Implementation for ARI stubs. More...

#include "asterisk.h"
#include "asterisk/file.h"
#include "asterisk/pbx.h"
#include "asterisk/bridge.h"
#include "asterisk/callerid.h"
#include "asterisk/stasis_app.h"
#include "asterisk/stasis_app_playback.h"
#include "asterisk/stasis_app_recording.h"
#include "asterisk/stasis_app_snoop.h"
#include "asterisk/stasis_channels.h"
#include "asterisk/causes.h"
#include "asterisk/format_cache.h"
#include "asterisk/core_local.h"
#include "asterisk/dial.h"
#include "asterisk/max_forwards.h"
#include "asterisk/rtp_engine.h"
#include "resource_channels.h"
#include <limits.h>
#include "asterisk/config.h"
#include "asterisk/netsock2.h"
Include dependency graph for resource_channels.c:

Go to the source code of this file.

Data Structures

struct  ari_channel_thread_data
 
struct  ari_origination
 Structure used for origination. More...
 

Functions

static void * ari_channel_thread (void *data)
 Thread that owns stasis-created channel. More...
 
static struct ast_channelari_channels_handle_originate_with_id (const char *args_endpoint, const char *args_extension, const char *args_context, long args_priority, const char *args_label, const char *args_app, const char *args_app_args, const char *args_caller_id, int args_timeout, struct ast_variable *variables, const char *args_channel_id, const char *args_other_channel_id, const char *args_originator, const char *args_formats, struct ast_ari_response *response)
 
static void 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)
 
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)
 
static void * ari_originate_dial (void *data)
 Thread which dials and executes upon answer. More...
 
void ast_ari_channels_answer (struct ast_variable *headers, struct ast_ari_channels_answer_args *args, struct ast_ari_response *response)
 Answer a channel. More...
 
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. More...
 
void ast_ari_channels_create (struct ast_variable *headers, struct ast_ari_channels_create_args *args, struct ast_ari_response *response)
 Create channel. More...
 
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. More...
 
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. More...
 
void ast_ari_channels_get (struct ast_variable *headers, struct ast_ari_channels_get_args *args, struct ast_ari_response *response)
 Channel details. More...
 
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. More...
 
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. More...
 
void ast_ari_channels_hold (struct ast_variable *headers, struct ast_ari_channels_hold_args *args, struct ast_ari_response *response)
 Hold a channel. More...
 
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. More...
 
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. More...
 
void ast_ari_channels_mute (struct ast_variable *headers, struct ast_ari_channels_mute_args *args, struct ast_ari_response *response)
 Mute a channel. More...
 
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). More...
 
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). More...
 
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. More...
 
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. More...
 
void ast_ari_channels_record (struct ast_variable *headers, struct ast_ari_channels_record_args *args, struct ast_ari_response *response)
 Start a recording. More...
 
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. More...
 
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. More...
 
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. More...
 
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. More...
 
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. More...
 
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. More...
 
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. More...
 
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. More...
 
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. More...
 
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. More...
 
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. More...
 
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. More...
 
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. More...
 
void ast_ari_channels_unmute (struct ast_variable *headers, struct ast_ari_channels_unmute_args *args, struct ast_ari_response *response)
 Unmute a channel. More...
 
static void chan_data_destroy (struct ari_channel_thread_data *chan_data)
 
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. More...
 
static int convert_reason_to_hangup_code (const char *reason)
 Return the corresponded hangup code of the given reason. More...
 
static void external_media_audiosocket_tcp (struct ast_ari_channels_external_media_args *args, struct ast_variable *variables, struct ast_ari_response *response)
 
static void external_media_rtp_udp (struct ast_ari_channels_external_media_args *args, struct ast_variable *variables, struct ast_ari_response *response)
 
static struct stasis_app_controlfind_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. More...
 
static int json_to_ast_variables (struct ast_ari_response *response, struct ast_json *json_variables, struct ast_variable **variables)
 
static char * restore_dialstring (struct ast_channel *chan)
 Retrieve the dialstring from the channel datastore. More...
 
static int save_dialstring (struct ast_channel *chan, const char *dialstring)
 Save dialstring onto a channel datastore. More...
 

Variables

struct ast_datastore_info dialstring_info
 

Detailed Description

Implementation for ARI stubs.

Author
David M. Lee, II dlee@.nosp@m.digi.nosp@m.um.co.nosp@m.m

Definition in file resource_channels.c.

Function Documentation

◆ ari_channel_thread()

static void* ari_channel_thread ( void *  data)
static

Thread that owns stasis-created channel.

The channel enters into a Stasis application immediately upon creation. In this way, the channel can be manipulated by the Stasis application. Once the channel exits the Stasis application, it is hung up.

Definition at line 1698 of file resource_channels.c.

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 }
#define ast_log
Definition: astobj2.c:42
#define LOG_ERROR
int pbx_exec(struct ast_channel *c, struct ast_app *app, const char *data)
Execute an application.
Definition: pbx_app.c:471
struct ast_app * pbx_findapp(const char *app)
Look up an application.
Definition: ael_main.c:165
#define NULL
Definition: resample.c:96
static void chan_data_destroy(struct ari_channel_thread_data *chan_data)
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:739
struct ast_str * stasis_stuff
struct ast_channel * chan
ast_app: A registered application
Definition: pbx_app.c:45

References ast_log, ast_str_buffer(), ari_channel_thread_data::chan, chan_data_destroy(), LOG_ERROR, NULL, pbx_exec(), pbx_findapp(), and ari_channel_thread_data::stasis_stuff.

Referenced by ast_ari_channels_create().

◆ ari_channels_handle_originate_with_id()

static struct ast_channel* ari_channels_handle_originate_with_id ( const char *  args_endpoint,
const char *  args_extension,
const char *  args_context,
long  args_priority,
const char *  args_label,
const char *  args_app,
const char *  args_app_args,
const char *  args_caller_id,
int  args_timeout,
struct ast_variable variables,
const char *  args_channel_id,
const char *  args_other_channel_id,
const char *  args_originator,
const char *  args_formats,
struct ast_ari_response response 
)
static

Definition at line 1063 of file resource_channels.c.

1078 {
1079  char *dialtech;
1080  char *dialdevice = NULL;
1081  struct ast_dial *dial;
1082  char *caller_id = NULL;
1083  char *cid_num = NULL;
1084  char *cid_name = NULL;
1085  char *stuff;
1086  struct ast_channel *other = NULL;
1087  struct ast_channel *chan = NULL;
1089  struct ast_assigned_ids assignedids = {
1090  .uniqueid = args_channel_id,
1091  .uniqueid2 = args_other_channel_id,
1092  };
1093  struct ari_origination *origination;
1094  pthread_t thread;
1095  struct ast_format_cap *format_cap = NULL;
1096 
1097  if ((assignedids.uniqueid && AST_MAX_PUBLIC_UNIQUEID < strlen(assignedids.uniqueid))
1098  || (assignedids.uniqueid2 && AST_MAX_PUBLIC_UNIQUEID < strlen(assignedids.uniqueid2))) {
1099  ast_ari_response_error(response, 400, "Bad Request",
1100  "Uniqueid length exceeds maximum of %d", AST_MAX_PUBLIC_UNIQUEID);
1101  return NULL;
1102  }
1103 
1104  if (ast_strlen_zero(args_endpoint)) {
1105  ast_ari_response_error(response, 400, "Bad Request",
1106  "Endpoint must be specified");
1107  return NULL;
1108  }
1109 
1110  if (!ast_strlen_zero(args_originator) && !ast_strlen_zero(args_formats)) {
1111  ast_ari_response_error(response, 400, "Bad Request",
1112  "Originator and formats can't both be specified");
1113  return NULL;
1114  }
1115 
1116  dialtech = ast_strdupa(args_endpoint);
1117  if ((stuff = strchr(dialtech, '/'))) {
1118  *stuff++ = '\0';
1119  dialdevice = stuff;
1120  }
1121 
1122  if (ast_strlen_zero(dialtech) || ast_strlen_zero(dialdevice)) {
1123  ast_ari_response_error(response, 400, "Bad Request",
1124  "Invalid endpoint specified");
1125  return NULL;
1126  }
1127 
1128  if (!ast_strlen_zero(args_app)) {
1129  RAII_VAR(struct ast_str *, appdata, ast_str_create(64), ast_free);
1130 
1131  if (!appdata) {
1133  return NULL;
1134  }
1135 
1136  ast_str_set(&appdata, 0, "%s", args_app);
1137  if (!ast_strlen_zero(args_app_args)) {
1138  ast_str_append(&appdata, 0, ",%s", args_app_args);
1139  }
1140 
1141  origination = ast_calloc(1, sizeof(*origination) + ast_str_size(appdata) + 1);
1142  if (!origination) {
1144  return NULL;
1145  }
1146 
1147  strcpy(origination->appdata, ast_str_buffer(appdata));
1148  } else if (!ast_strlen_zero(args_extension)) {
1149  origination = ast_calloc(1, sizeof(*origination) + 1);
1150  if (!origination) {
1152  return NULL;
1153  }
1154 
1155  ast_copy_string(origination->context, S_OR(args_context, "default"), sizeof(origination->context));
1156  ast_copy_string(origination->exten, args_extension, sizeof(origination->exten));
1157 
1158  if (!ast_strlen_zero(args_label)) {
1159  /* A label was provided in the request, use that */
1160  int ipri = 1;
1161  if (sscanf(args_label, "%30d", &ipri) != 1) {
1162  ipri = ast_findlabel_extension(chan, origination->context, origination->exten, args_label, args_caller_id);
1163 
1164  if (ipri == -1) {
1165  ast_log(AST_LOG_ERROR, "Requested label: %s can not be found in context: %s\n", args_label, args_context);
1166  ast_ari_response_error(response, 404, "Not Found", "Requested label can not be found");
1167  return NULL;
1168  }
1169  } else {
1170  ast_debug(3, "Numeric value provided for label, jumping to that priority\n");
1171  }
1172 
1173  if (ipri == 0) {
1174  ast_log(AST_LOG_ERROR, "Invalid priority label '%s' specified for extension %s in context: %s\n",
1175  args_label, args_extension, args_context);
1176  ast_ari_response_error(response, 400, "Bad Request", "Requested priority is illegal");
1177  return NULL;
1178  }
1179 
1180  /* Our priority was provided by a label */
1181  origination->priority = ipri;
1182  } else {
1183  /* No label provided, use provided priority */
1184  origination->priority = args_priority ? args_priority : 1;
1185  }
1186 
1187  origination->appdata[0] = '\0';
1188  } else {
1189  ast_ari_response_error(response, 400, "Bad Request",
1190  "Application or extension must be specified");
1191  return NULL;
1192  }
1193 
1194  dial = ast_dial_create();
1195  if (!dial) {
1197  ast_free(origination);
1198  return NULL;
1199  }
1200  ast_dial_set_user_data(dial, origination);
1201 
1202  if (ast_dial_append(dial, dialtech, dialdevice, &assignedids)) {
1204  ast_dial_destroy(dial);
1205  ast_free(origination);
1206  return NULL;
1207  }
1208 
1209  if (args_timeout > 0) {
1210  ast_dial_set_global_timeout(dial, args_timeout * 1000);
1211  } else if (args_timeout == -1) {
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 
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 
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  */
1308 
1310  if (!ast_strlen_zero(cid_num)) {
1311  connected.id.number.valid = 1;
1312  connected.id.number.str = (char *) cid_num;
1313  connected.id.number.presentation = AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED;
1314  }
1315  if (!ast_strlen_zero(cid_name)) {
1316  connected.id.name.valid = 1;
1317  connected.id.name.str = (char *) cid_name;
1319  }
1321  }
1322 
1323  ast_channel_lock(chan);
1324  if (variables) {
1325  ast_set_variables(chan, variables);
1326  }
1328 
1329  if (!ast_strlen_zero(args_app)) {
1330  struct ast_channel *local_peer;
1331 
1332  stasis_app_subscribe_channel(args_app, chan);
1333 
1334  /* Subscribe to the Local channel peer also. */
1335  local_peer = ast_local_get_peer(chan);
1336  if (local_peer) {
1337  stasis_app_subscribe_channel(args_app, local_peer);
1338  ast_channel_unref(local_peer);
1339  }
1340  }
1341 
1343  ast_channel_unlock(chan);
1344 
1345  /* Before starting the async dial bump the ref in case the dial quickly goes away and takes
1346  * the reference with it
1347  */
1348  ast_channel_ref(chan);
1349 
1352  ast_dial_destroy(dial);
1353  ast_free(origination);
1354  } else {
1356  }
1357 
1358  return chan;
1359 }
pthread_t thread
Definition: app_meetme.c:1091
void ast_ari_response_error(struct ast_ari_response *response, int response_code, const char *response_text, const char *message_fmt,...)
Fill in an error ast_ari_response.
Definition: res_ari.c:259
void ast_ari_response_ok(struct ast_ari_response *response, struct ast_json *message)
Fill in an OK (200) ast_ari_response.
Definition: res_ari.c:276
void ast_ari_response_alloc_failed(struct ast_ari_response *response)
Fill in response with a 500 message for allocation failures.
Definition: res_ari.c:298
#define ast_free(a)
Definition: astmm.h:180
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:298
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
#define ao2_cleanup(obj)
Definition: astobj2.h:1934
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
int ast_callerid_parse(char *instr, char **name, char **location)
Destructively parse inbuf into name and location (or number)
Definition: callerid.c:1008
void ast_shrink_phone_number(char *n)
Shrink a phone number in place to just digits (more accurately it just removes ()'s,...
Definition: callerid.c:947
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
#define AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED
Definition: callerid.h:329
static char cid_num[AST_MAX_EXTENSION]
Definition: chan_mgcp.c:167
static char cid_name[AST_MAX_EXTENSION]
Definition: chan_mgcp.c:168
#define AST_MAX_PUBLIC_UNIQUEID
Definition: channel.h:147
struct ast_party_connected_line * ast_channel_connected(struct ast_channel *chan)
enum ast_channel_error ast_channel_errno(void)
Get error code for latest channel operation.
Definition: channel.c:11147
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:8391
const char * ast_channel_uniqueid(const struct ast_channel *chan)
#define ast_channel_lock(chan)
Definition: channel.h:2922
void ast_set_variables(struct ast_channel *chan, struct ast_variable *vars)
adds a list of channel variables to a channel
Definition: channel.c:8198
@ AST_CHANNEL_ERROR_ID_EXISTS
Definition: channel.h:4885
#define ast_channel_ref(c)
Increase channel reference count.
Definition: channel.h:2947
@ AST_FLAG_ORIGINATED
Definition: channel.h:1039
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:7417
struct ast_flags * ast_channel_flags(struct ast_channel *chan)
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2958
struct ast_channel * ast_channel_get_by_name(const char *name)
Find a channel by name.
Definition: channel.c:1448
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:2039
#define ast_channel_cleanup(c)
Cleanup a channel reference.
Definition: channel.h:2969
#define ast_channel_unlock(chan)
Definition: channel.h:2923
struct ast_channel * ast_local_get_peer(struct ast_channel *ast)
Get the other local channel in the pair.
Definition: core_local.c:276
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
void ast_dial_set_user_data(struct ast_dial *dial, void *user_data)
Set user data on a dial structure.
Definition: dial.c:1269
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
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:1253
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:1279
int ast_dial_destroy(struct ast_dial *dial)
Destroys a dialing structure.
Definition: dial.c:1086
struct ast_dial * ast_dial_create(void)
New dialing structure.
Definition: dial.c:225
char connected
Definition: eagi_proxy.c:82
#define ast_format_cache_get(name)
Retrieve a named format from the cache.
Definition: format_cache.h:278
@ AST_FORMAT_CAP_FLAG_DEFAULT
Definition: format_cap.h:38
#define ast_format_cap_append(cap, format, framing)
Add format capability to capabilities structure.
Definition: format_cap.h:99
#define ast_format_cap_alloc(flags)
Allocate a new ast_format_cap structure.
Definition: format_cap.h:49
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,...
char * strsep(char **str, const char *delims)
#define AST_LOG_ERROR
#define ast_debug(level,...)
Log a DEBUG message.
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:4187
static void * ari_originate_dial(void *data)
Thread which dials and executes upon answer.
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
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.
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:1117
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one.
Definition: strings.h:80
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
Definition: strings.h:640
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:1091
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:406
char * ast_strip(char *s)
Strip leading/trailing whitespace from a string.
Definition: strings.h:223
size_t ast_str_size(const struct ast_str *buf)
Returns the current maximum length (without reallocation) of the current buffer.
Definition: strings.h:723
Structure used for origination.
char appdata[0]
Application data to pass to Stasis application.
char exten[AST_MAX_EXTENSION]
Dialplan extension.
char context[AST_MAX_CONTEXT]
Dialplan context.
int priority
Dialplan priority.
Structure to pass both assignedid values to channel drivers.
Definition: channel.h:604
const char * uniqueid2
Definition: channel.h:606
const char * uniqueid
Definition: channel.h:605
Structure representing a snapshot of channel state.
Main Channel structure associated with a channel.
struct ast_channel_snapshot * snapshot
Main dialing structure. Contains global options, channels being dialed, and more!
Definition: dial.c:48
Format capabilities structure, holds formats + preference order + etc.
Definition: format_cap.c:54
Definition of a media format.
Definition: format.c:43
Connected Line/Party information.
Definition: channel.h:456
Support for dynamic strings.
Definition: strings.h:604
#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:936
#define ast_pthread_create_detached(a, b, c, d)
Definition: utils.h:583
#define ast_set_flag(p, flag)
Definition: utils.h:70

References ao2_cleanup, ao2_ref, ari_origination::appdata, ari_originate_dial(), ast_ari_response_alloc_failed(), ast_ari_response_error(), ast_ari_response_ok(), ast_callerid_parse(), ast_calloc, ast_channel_cleanup, ast_channel_connected(), ast_channel_errno(), AST_CHANNEL_ERROR_ID_EXISTS, ast_channel_flags(), ast_channel_get_by_name(), ast_channel_lock, ast_channel_ref, ast_channel_set_connected_line(), ast_channel_snapshot_get_latest(), ast_channel_snapshot_to_json(), ast_channel_uniqueid(), ast_channel_unlock, ast_channel_unref, ast_copy_string(), ast_debug, ast_dial_append(), ast_dial_create(), ast_dial_destroy(), ast_dial_get_channel(), ast_dial_prerun(), ast_dial_set_global_timeout(), ast_dial_set_user_data(), ast_findlabel_extension(), AST_FLAG_ORIGINATED, ast_format_cache_get, ast_format_cap_alloc, ast_format_cap_append, AST_FORMAT_CAP_FLAG_DEFAULT, ast_free, ast_is_shrinkable_phonenumber(), ast_local_get_peer(), ast_log, AST_LOG_ERROR, AST_MAX_PUBLIC_UNIQUEID, ast_party_connected_line_set_init(), AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED, ast_pthread_create_detached, ast_set_callerid(), ast_set_flag, ast_set_variables(), ast_shrink_phone_number(), ast_str_append(), ast_str_buffer(), ast_str_create, ast_str_set(), ast_str_size(), ast_strdupa, ast_strip(), ast_strlen_zero(), cid_name, cid_num, connected, ari_origination::context, ari_origination::exten, NULL, ari_origination::priority, RAII_VAR, S_OR, ast_channel::snapshot, stasis_app_subscribe_channel(), strsep(), thread, ast_assigned_ids::uniqueid, and ast_assigned_ids::uniqueid2.

Referenced by ast_ari_channels_originate(), ast_ari_channels_originate_with_id(), external_media_audiosocket_tcp(), and external_media_rtp_udp().

◆ ari_channels_handle_play()

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 
)
static

Definition at line 636 of file resource_channels.c.

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 }
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_asprintf(ret, fmt,...)
A wrapper for asprintf()
Definition: astmm.h:267
static char language[MAX_LANGUAGE]
Definition: chan_alsa.c:121
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.
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.
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
@ STASIS_PLAYBACK_TARGET_CHANNEL
const char * stasis_app_playback_get_id(struct stasis_app_playback *playback)
Gets the unique id of a playback object.
struct stasis_app_playback * stasis_app_control_play_uri(struct stasis_app_control *control, const char **media, size_t media_count, const char *language, const char *target_id, enum stasis_app_playback_target_type target_type, int skipms, long offsetms, const char *id)
Play a file to the control's channel.
struct ast_json * stasis_app_playback_to_json(const struct stasis_app_playback *playback)
Convert a playback to its JSON representation.
Abstract JSON element (object, array, string, int, ...).
#define ast_assert(a)
Definition: utils.h:734

References ao2_cleanup, ast_ari_response_created(), ast_ari_response_error(), ast_asprintf, ast_assert, ast_free, channel_state_invalid(), find_control(), language, NULL, RAII_VAR, S_OR, stasis_app_control_get_snapshot(), stasis_app_control_play_uri(), stasis_app_playback_get_id(), stasis_app_playback_to_json(), and STASIS_PLAYBACK_TARGET_CHANNEL.

Referenced by ast_ari_channels_play(), and ast_ari_channels_play_with_id().

◆ ari_channels_handle_snoop_channel()

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 
)
static

Definition at line 1572 of file resource_channels.c.

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 }
stasis_app_snoop_direction
Directions for audio stream flow.
@ STASIS_SNOOP_DIRECTION_IN
Audio stream in from the channel.
@ STASIS_SNOOP_DIRECTION_OUT
Audio stream out to the channel.
@ STASIS_SNOOP_DIRECTION_NONE
No direction.
@ STASIS_SNOOP_DIRECTION_BOTH
Audio stream to AND from the channel.
struct ast_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.

References ao2_cleanup, ast_ari_response_error(), ast_ari_response_ok(), ast_assert, ast_channel_cleanup, ast_channel_get_by_name(), ast_channel_snapshot_get_latest(), ast_channel_snapshot_to_json(), ast_channel_uniqueid(), ast_strlen_zero(), NULL, RAII_VAR, stasis_app_control_snoop(), STASIS_SNOOP_DIRECTION_BOTH, STASIS_SNOOP_DIRECTION_IN, STASIS_SNOOP_DIRECTION_NONE, and STASIS_SNOOP_DIRECTION_OUT.

Referenced by ast_ari_channels_snoop_channel(), and ast_ari_channels_snoop_channel_with_id().

◆ ari_originate_dial()

static void* ari_originate_dial ( void *  data)
static

Thread which dials and executes upon answer.

Definition at line 1013 of file resource_channels.c.

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 }
static const char app[]
Definition: app_adsiprog.c:56
void ast_channel_exten_set(struct ast_channel *chan, const char *value)
const char * ast_channel_name(const struct ast_channel *chan)
void ast_channel_context_set(struct ast_channel *chan, const char *value)
void ast_channel_priority_set(struct ast_channel *chan, int value)
ast_dial_result
List of return codes for dial run API calls.
Definition: dial.h:54
@ AST_DIAL_RESULT_ANSWERED
Definition: dial.h:61
void * ast_dial_get_user_data(struct ast_dial *dial)
Return the user data on a dial structure.
Definition: dial.c:1274
struct ast_channel * ast_dial_answered_steal(struct ast_dial *dial)
Steal the channel that answered.
Definition: dial.c:993
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
struct ast_channel * ast_dial_answered(struct ast_dial *dial)
Return channel that answered.
Definition: dial.c:981
char * end
Definition: eagi_proxy.c:73
#define ast_verb(level,...)
#define LOG_WARNING
enum ast_pbx_result ast_pbx_run(struct ast_channel *c)
Execute the PBX in the current thread.
Definition: pbx.c:4762

References app, ari_origination::appdata, ast_channel_context_set(), ast_channel_exten_set(), ast_channel_name(), ast_channel_priority_set(), ast_dial_answered(), ast_dial_answered_steal(), ast_dial_destroy(), ast_dial_get_user_data(), AST_DIAL_RESULT_ANSWERED, ast_dial_run(), ast_free, ast_log, ast_pbx_run(), ast_strlen_zero(), ast_verb, ari_origination::context, end, ari_origination::exten, LOG_ERROR, LOG_WARNING, NULL, pbx_exec(), pbx_findapp(), and ari_origination::priority.

Referenced by ari_channels_handle_originate_with_id().

◆ ast_ari_channels_answer()

void ast_ari_channels_answer ( struct ast_variable headers,
struct ast_ari_channels_answer_args args,
struct ast_ari_response response 
)

Answer a channel.

Parameters
headersHTTP headers
argsSwagger parameters
[out]responseHTTP response

Definition at line 338 of file resource_channels.c.

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 }
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
int stasis_app_control_answer(struct stasis_app_control *control)
Answer the channel associated with this control.
const char * args

References ao2_cleanup, args, ast_ari_response_error(), ast_ari_response_no_content(), channel_state_invalid(), find_control(), NULL, RAII_VAR, and stasis_app_control_answer().

Referenced by ast_ari_channels_answer_cb().

◆ ast_ari_channels_continue_in_dialplan()

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.

Parameters
headersHTTP headers
argsSwagger parameters
[out]responseHTTP response

Definition at line 180 of file resource_channels.c.

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 }
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:122
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:120
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

References ao2_cleanup, args, ast_ari_response_alloc_failed(), ast_ari_response_error(), ast_ari_response_no_content(), ast_assert, ast_debug, ast_findlabel_extension(), ast_log, AST_LOG_ERROR, ast_strlen_zero(), channel_state_invalid(), context, exten, find_control(), NULL, RAII_VAR, S_OR, stasis_app_control_continue(), and stasis_app_control_get_snapshot().

Referenced by ast_ari_channels_continue_in_dialplan_cb().

◆ ast_ari_channels_create()

void ast_ari_channels_create ( struct ast_variable headers,
struct ast_ari_channels_create_args args,
struct ast_ari_response response 
)

Create channel.

Parameters
headersHTTP headers
argsSwagger parameters
[out]responseHTTP response

Definition at line 1778 of file resource_channels.c.

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 
1931  chan_data_destroy(chan_data);
1932  } else {
1934  }
1935 
1936  ao2_ref(snapshot, -1);
1937 }
#define ao2_bump(obj)
Bump refcount on an AO2 object by one, returning the object.
Definition: astobj2.h:480
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:6432
struct ast_format_cap * ast_channel_nativeformats(const struct ast_channel *chan)
@ AST_MEDIA_TYPE_AUDIO
Definition: codec.h:32
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
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
static int save_dialstring(struct ast_channel *chan, const char *dialstring)
Save dialstring onto a channel datastore.
static void * ari_channel_thread(void *data)
Thread that owns stasis-created channel.
static int json_to_ast_variables(struct ast_ari_response *response, struct ast_json *json_variables, struct ast_variable **variables)
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.

References ao2_bump, ao2_cleanup, ao2_ref, args, ari_channel_thread(), ast_ari_channels_create_parse_body(), ast_ari_response_alloc_failed(), ast_ari_response_error(), ast_ari_response_ok(), ast_calloc, ast_channel_cleanup, ast_channel_errno(), AST_CHANNEL_ERROR_ID_EXISTS, ast_channel_get_by_name(), ast_channel_nativeformats(), ast_channel_snapshot_get_latest(), ast_channel_snapshot_to_json(), ast_channel_uniqueid(), ast_format_cache_get, ast_format_cap_alloc, ast_format_cap_append, ast_format_cap_append_by_type(), AST_FORMAT_CAP_FLAG_DEFAULT, ast_json_object_get(), AST_MEDIA_TYPE_AUDIO, ast_pthread_create_detached, ast_request(), ast_set_variables(), ast_str_append(), ast_str_create, ast_strdupa, ast_strip(), ast_strlen_zero(), ari_channel_thread_data::chan, chan_data_destroy(), json_to_ast_variables(), NULL, save_dialstring(), stasis_app_subscribe_channel(), ari_channel_thread_data::stasis_stuff, strsep(), thread, ast_assigned_ids::uniqueid, and ast_assigned_ids::uniqueid2.

Referenced by ast_ari_channels_create_cb().

◆ ast_ari_channels_dial()

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.

Parameters
headersHTTP headers
argsSwagger parameters
[out]responseHTTP response

Definition at line 1939 of file resource_channels.c.

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 }
@ AST_CHANNEL_REQUESTOR_BRIDGE_PEER
Definition: channel.h:1477
unsigned short ast_channel_transfercapability(const struct ast_channel *chan)
struct ast_party_dialed * ast_channel_dialed(struct ast_channel *chan)
#define ast_channel_lock_both(chan1, chan2)
Lock two channels.
Definition: channel.h:2929
int ast_channel_datastore_inherit(struct ast_channel *from, struct ast_channel *to)
Inherit datastores from a parent to a child.
Definition: channel.c:2367
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:6512
ast_channel_adsicpe
Definition: channel.h:868
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:6849
const char * ast_channel_language(const struct ast_channel *chan)
const char * ast_channel_musicclass(const struct ast_channel *chan)
struct ast_party_caller * ast_channel_caller(struct ast_channel *chan)
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:8376
struct ast_party_redirecting * ast_channel_redirecting(struct ast_channel *chan)
void ast_channel_transfercapability_set(struct ast_channel *chan, unsigned short value)
void ast_channel_adsicpe_set(struct ast_channel *chan, enum ast_channel_adsicpe value)
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:2129
ast_channel_state
ast_channel states
Definition: channelstate.h:35
@ AST_STATE_DOWN
Definition: channelstate.h:36
@ AST_STATE_RESERVED
Definition: channelstate.h:37
void ast_channel_stage_snapshot_done(struct ast_channel *chan)
Clear flag to indicate channel snapshot is being staged, and publish snapshot.
void ast_channel_stage_snapshot(struct ast_channel *chan)
Set flag to indicate channel snapshot is being staged.
int ast_max_forwards_decrement(struct ast_channel *chan)
Decrement the max forwards count for a particular channel.
Definition: max_forwards.c:135
static char * restore_dialstring(struct ast_channel *chan)
Retrieve the dialstring from the channel datastore.
int stasis_app_control_dial(struct stasis_app_control *control, const char *dialstring, unsigned int timeout)
Dial a channel.
Definition: control.c:1666
int transit_network_select
Transit Network Select.
Definition: channel.h:397

References ao2_cleanup, args, ast_ari_response_alloc_failed(), ast_ari_response_error(), ast_ari_response_no_content(), ast_channel_adsicpe_set(), ast_channel_caller(), ast_channel_cleanup, ast_channel_connected(), ast_channel_datastore_inherit(), ast_channel_dialed(), ast_channel_get_by_name(), ast_channel_inherit_variables(), ast_channel_language(), ast_channel_lock, ast_channel_lock_both, ast_channel_musicclass(), ast_channel_redirecting(), ast_channel_req_accountcodes(), AST_CHANNEL_REQUESTOR_BRIDGE_PEER, ast_channel_stage_snapshot(), ast_channel_stage_snapshot_done(), ast_channel_transfercapability(), ast_channel_transfercapability_set(), ast_channel_unlock, ast_connected_line_copy_from_caller(), ast_max_forwards_decrement(), ast_party_redirecting_copy(), AST_STATE_DOWN, AST_STATE_RESERVED, ast_strdupa, ast_strlen_zero(), find_control(), NULL, RAII_VAR, restore_dialstring(), stasis_app_control_dial(), and ast_party_dialed::transit_network_select.

Referenced by ast_ari_channels_dial_cb().

◆ ast_ari_channels_external_media()

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.

Create a channel to an External Media source/sink.

Parameters
headersHTTP headers
argsSwagger parameters
[out]responseHTTP response

Definition at line 2181 of file resource_channels.c.

2183 {
2184  struct ast_variable *variables = NULL;
2185  char *external_host;
2186  char *host = NULL;
2187  char *port = NULL;
2188 
2189  ast_assert(response != NULL);
2190 
2191  /* Parse any query parameters out of the body parameter */
2192  if (args->variables) {
2193  struct ast_json *json_variables;
2194 
2196  json_variables = ast_json_object_get(args->variables, "variables");
2197  if (json_variables
2198  && json_to_ast_variables(response, json_variables, &variables)) {
2199  return;
2200  }
2201  }
2202 
2203  if (ast_strlen_zero(args->app)) {
2204  ast_ari_response_error(response, 400, "Bad Request", "app cannot be empty");
2205  return;
2206  }
2207 
2208  if (ast_strlen_zero(args->external_host)) {
2209  ast_ari_response_error(response, 400, "Bad Request", "external_host cannot be empty");
2210  return;
2211  }
2212 
2213  external_host = ast_strdupa(args->external_host);
2214  if (!ast_sockaddr_split_hostport(external_host, &host, &port, PARSE_PORT_REQUIRE)) {
2215  ast_ari_response_error(response, 400, "Bad Request", "external_host must be <host>:<port>");
2216  return;
2217  }
2218 
2219  if (ast_strlen_zero(args->format)) {
2220  ast_ari_response_error(response, 400, "Bad Request", "format cannot be empty");
2221  return;
2222  }
2223 
2224  if (ast_strlen_zero(args->encapsulation)) {
2225  args->encapsulation = "rtp";
2226  }
2227  if (ast_strlen_zero(args->transport)) {
2228  args->transport = "udp";
2229  }
2230  if (ast_strlen_zero(args->connection_type)) {
2231  args->connection_type = "client";
2232  }
2233  if (ast_strlen_zero(args->direction)) {
2234  args->direction = "both";
2235  }
2236 
2237  if (strcasecmp(args->encapsulation, "rtp") == 0 && strcasecmp(args->transport, "udp") == 0) {
2238  external_media_rtp_udp(args, variables, response);
2239  } else if (strcasecmp(args->encapsulation, "audiosocket") == 0 && strcasecmp(args->transport, "tcp") == 0) {
2240  external_media_audiosocket_tcp(args, variables, response);
2241  } else {
2243  response, 501, "Not Implemented",
2244  "The encapsulation and/or transport is not supported");
2245  }
2246 }
@ PARSE_PORT_REQUIRE
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
static void external_media_audiosocket_tcp(struct ast_ari_channels_external_media_args *args, struct ast_variable *variables, struct ast_ari_response *response)
static void external_media_rtp_udp(struct ast_ari_channels_external_media_args *args, struct ast_variable *variables, struct ast_ari_response *response)
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.

References args, ast_ari_channels_external_media_parse_body(), ast_ari_response_error(), ast_assert, ast_json_object_get(), ast_sockaddr_split_hostport(), ast_strdupa, ast_strlen_zero(), external_media_audiosocket_tcp(), external_media_rtp_udp(), json_to_ast_variables(), NULL, and PARSE_PORT_REQUIRE.

Referenced by ast_ari_channels_external_media_cb().

◆ ast_ari_channels_get()

void ast_ari_channels_get ( struct ast_variable headers,
struct ast_ari_channels_get_args args,
struct ast_ari_response response 
)

Channel details.

Parameters
headersHTTP headers
argsSwagger parameters
[out]responseHTTP response

Definition at line 888 of file resource_channels.c.

891 {
892  struct ast_channel_snapshot *snapshot;
893 
894  snapshot = ast_channel_snapshot_get_latest(args->channel_id);
895  if (!snapshot) {
897  response, 404, "Not Found",
898  "Channel not found");
899  return;
900  }
901 
902  ast_ari_response_ok(response,
904  ao2_ref(snapshot, -1);
905 }

References ao2_ref, args, ast_ari_response_error(), ast_ari_response_ok(), ast_channel_snapshot_get_latest(), ast_channel_snapshot_to_json(), and NULL.

Referenced by ast_ari_channels_get_cb().

◆ ast_ari_channels_get_channel_var()

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.

Parameters
headersHTTP headers
argsSwagger parameters
[out]responseHTTP response

Definition at line 1472 of file resource_channels.c.

1475 {
1476  RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
1477  RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
1478  RAII_VAR(struct ast_str *, value, ast_str_create(32), ast_free);
1479  RAII_VAR(struct ast_channel *, channel, NULL, ast_channel_cleanup);
1480 
1481  ast_assert(response != NULL);
1482 
1483  if (!value) {
1485  return;
1486  }
1487 
1488  if (ast_strlen_zero(args->variable)) {
1490  response, 400, "Bad Request",
1491  "Variable name is required");
1492  return;
1493  }
1494 
1495  if (ast_strlen_zero(args->channel_id)) {
1497  response, 400, "Bad Request",
1498  "Channel ID is required");
1499  return;
1500  }
1501 
1502  channel = ast_channel_get_by_name(args->channel_id);
1503  if (!channel) {
1505  response, 404, "Channel Not Found",
1506  "Provided channel was not found");
1507  return;
1508  }
1509 
1510  /* You may be tempted to lock the channel you're about to read from. You
1511  * would be wrong. Some dialplan functions put the channel into
1512  * autoservice, which deadlocks if the channel is already locked.
1513  * ast_str_retrieve_variable() does its own locking, and the dialplan
1514  * functions need to as well. We should be fine without the lock.
1515  */
1516 
1517  if (args->variable[strlen(args->variable) - 1] == ')') {
1518  if (ast_func_read2(channel, args->variable, &value, 0)) {
1520  response, 500, "Error With Function",
1521  "Unable to read provided function");
1522  return;
1523  }
1524  } else {
1525  if (!ast_str_retrieve_variable(&value, 0, channel, NULL, args->variable)) {
1527  response, 404, "Variable Not Found",
1528  "Provided variable was not found");
1529  return;
1530  }
1531  }
1532 
1533  if (!(json = ast_json_pack("{s: s}", "value", S_OR(ast_str_buffer(value), "")))) {
1535  return;
1536  }
1537 
1538  ast_ari_response_ok(response, ast_json_ref(json));
1539 }
struct ast_json * ast_json_ref(struct ast_json *value)
Increase refcount on value.
Definition: json.c:67
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_json * ast_json_pack(char const *format,...)
Helper for creating complex JSON values.
Definition: json.c:591
const char * ast_str_retrieve_variable(struct ast_str **buf, ssize_t maxlen, struct ast_channel *chan, struct varshead *headp, const char *var)
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
int value
Definition: syslog.c:37

References ao2_cleanup, args, ast_ari_response_alloc_failed(), ast_ari_response_error(), ast_ari_response_ok(), ast_assert, ast_channel_cleanup, ast_channel_get_by_name(), ast_free, ast_func_read2(), ast_json_pack(), ast_json_ref(), ast_json_unref(), ast_str_buffer(), ast_str_create, ast_str_retrieve_variable(), ast_strlen_zero(), NULL, RAII_VAR, S_OR, and value.

Referenced by ast_ari_channels_get_channel_var_cb().

◆ ast_ari_channels_hangup()

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.

Parameters
headersHTTP headers
argsSwagger parameters
[out]responseHTTP response

Definition at line 907 of file resource_channels.c.

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 }
#define AST_CAUSE_NORMAL
Definition: causes.h:151
@ AST_SOFTHANGUP_EXPLICIT
Definition: channel.h:1148
int ast_softhangup(struct ast_channel *chan, int cause)
Softly hangup up a channel.
Definition: channel.c:2470
void ast_channel_hangupcause_set(struct ast_channel *chan, int value)
static int convert_reason_to_hangup_code(const char *reason)
Return the corresponded hangup code of the given reason.

References ao2_cleanup, args, ast_ari_response_error(), ast_ari_response_no_content(), AST_CAUSE_NORMAL, ast_channel_get_by_name(), ast_channel_hangupcause_set(), ast_softhangup(), AST_SOFTHANGUP_EXPLICIT, ast_strlen_zero(), convert_reason_to_hangup_code(), NULL, and RAII_VAR.

Referenced by ast_ari_channels_hangup_cb().

◆ ast_ari_channels_hold()

void ast_ari_channels_hold ( struct ast_variable headers,
struct ast_ari_channels_hold_args args,
struct ast_ari_response response 
)

Hold a channel.

Parameters
headersHTTP headers
argsSwagger parameters
[out]responseHTTP response

Definition at line 514 of file resource_channels.c.

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 }
void stasis_app_control_hold(struct stasis_app_control *control)
Place the channel associated with the control on hold.
Definition: control.c:748

References ao2_cleanup, args, ast_ari_response_no_content(), channel_state_invalid(), find_control(), NULL, RAII_VAR, and stasis_app_control_hold().

Referenced by ast_ari_channels_hold_cb().

◆ ast_ari_channels_list()

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.

Parameters
headersHTTP headers
argsSwagger parameters
[out]responseHTTP response

Definition at line 956 of file resource_channels.c.

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 }
#define ao2_iterator_next(iter)
Definition: astobj2.h:1911
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
struct ao2_container * ast_channel_cache_all(void)
int ast_json_array_append(struct ast_json *array, struct ast_json *value)
Append to an array.
Definition: json.c:368
struct ast_json * ast_json_array_create(void)
Create a empty JSON array.
Definition: json.c:352
struct stasis_message_sanitizer * stasis_app_get_sanitizer(void)
Get the Stasis message sanitizer for app_stasis applications.
Definition: res_stasis.c:2264
Generic container type.
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1821
Structure containing callbacks for Stasis message sanitization.
Definition: stasis.h:200
int(* channel_snapshot)(const struct ast_channel_snapshot *snapshot)
Callback which determines whether a channel should be sanitized from a message based on the channel's...
Definition: stasis.h:221

References ao2_cleanup, ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_ref, ast_ari_response_alloc_failed(), ast_ari_response_ok(), ast_channel_cache_all(), ast_channel_snapshot_to_json(), ast_json_array_append(), ast_json_array_create(), ast_json_ref(), ast_json_unref(), stasis_message_sanitizer::channel_snapshot, NULL, RAII_VAR, and stasis_app_get_sanitizer().

Referenced by ast_ari_channels_list_cb().

◆ ast_ari_channels_move()

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.

Parameters
headersHTTP headers
argsSwagger parameters
[out]responseHTTP response

Definition at line 256 of file resource_channels.c.

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 }
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

References ao2_cleanup, args, ast_ari_response_error(), ast_ari_response_no_content(), find_control(), NULL, RAII_VAR, and stasis_app_control_move().

Referenced by ast_ari_channels_move_cb().

◆ ast_ari_channels_mute()

void ast_ari_channels_mute ( struct ast_variable headers,
struct ast_ari_channels_mute_args args,
struct ast_ari_response response 
)

Mute a channel.

Parameters
headersHTTP headers
argsSwagger parameters
[out]responseHTTP response

Definition at line 403 of file resource_channels.c.

406 {
407  RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
408  unsigned int direction = 0;
409  enum ast_frame_type frametype = AST_FRAME_VOICE;
410 
411  control = find_control(response, args->channel_id);
412  if (control == NULL) {
413  return;
414  }
415 
416  if (channel_state_invalid(control, response)) {
417  return;
418  }
419 
420  if (ast_strlen_zero(args->direction)) {
422  response, 400, "Bad Request",
423  "Direction is required");
424  return;
425  }
426 
427  if (!strcmp(args->direction, "in")) {
429  } else if (!strcmp(args->direction, "out")) {
431  } else if (!strcmp(args->direction, "both")) {
433  } else {
435  response, 400, "Bad Request",
436  "Invalid direction specified");
437  return;
438  }
439 
440  stasis_app_control_mute(control, direction, frametype);
441 
442  ast_ari_response_no_content(response);
443 }
#define AST_MUTE_DIRECTION_READ
Definition: channel.h:4800
#define AST_MUTE_DIRECTION_WRITE
Definition: channel.h:4801
direction
ast_frame_type
Frame types.
@ AST_FRAME_VOICE
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

References ao2_cleanup, args, ast_ari_response_error(), ast_ari_response_no_content(), AST_FRAME_VOICE, AST_MUTE_DIRECTION_READ, AST_MUTE_DIRECTION_WRITE, ast_strlen_zero(), channel_state_invalid(), find_control(), NULL, RAII_VAR, and stasis_app_control_mute().

Referenced by ast_ari_channels_mute_cb().

◆ ast_ari_channels_originate()

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).

The new channel is created immediately and a snapshot of it returned. If a Stasis application is provided it will be automatically subscribed to the originated channel for further events and updates.

Parameters
headersHTTP headers
argsSwagger parameters
[out]responseHTTP response

Definition at line 1433 of file resource_channels.c.

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 }
void ast_variables_destroy(struct ast_variable *var)
Free variable list.
Definition: extconf.c:1262
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)
int ast_ari_channels_originate_parse_body(struct ast_json *body, struct ast_ari_channels_originate_args *args)
Body parsing function for /channels.

References args, ari_channels_handle_originate_with_id(), ast_ari_channels_originate_parse_body(), ast_channel_cleanup, ast_json_object_get(), ast_variables_destroy(), json_to_ast_variables(), and NULL.

Referenced by ast_ari_channels_originate_cb().

◆ ast_ari_channels_originate_with_id()

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).

The new channel is created immediately and a snapshot of it returned. If a Stasis application is provided it will be automatically subscribed to the originated channel for further events and updates.

Parameters
headersHTTP headers
argsSwagger parameters
[out]responseHTTP response

Definition at line 1394 of file resource_channels.c.

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 }
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}.

References args, ari_channels_handle_originate_with_id(), ast_ari_channels_originate_with_id_parse_body(), ast_channel_cleanup, ast_json_object_get(), ast_variables_destroy(), json_to_ast_variables(), and NULL.

Referenced by ast_ari_channels_originate_with_id_cb().

◆ ast_ari_channels_play()

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.

The media URI may be any of a number of URI's. Currently sound:, recording:, number:, digits:, characters:, and tone: URI's are supported. This operation creates a playback resource that can be used to control the playback of media (pause, rewind, fast forward, etc.)

Parameters
headersHTTP headers
argsSwagger parameters
[out]responseHTTP response

Definition at line 718 of file resource_channels.c.

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 }
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)

References args, and ari_channels_handle_play().

Referenced by ast_ari_channels_play_cb().

◆ ast_ari_channels_play_with_id()

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.

The media URI may be any of a number of URI's. Currently sound:, recording:, number:, digits:, characters:, and tone: URI's are supported. This operation creates a playback resource that can be used to control the playback of media (pause, rewind, fast forward, etc.)

Parameters
headersHTTP headers
argsSwagger parameters
[out]responseHTTP response

Definition at line 733 of file resource_channels.c.

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 }

References args, and ari_channels_handle_play().

Referenced by ast_ari_channels_play_with_id_cb().

◆ ast_ari_channels_record()

void ast_ari_channels_record ( struct ast_variable headers,
struct ast_ari_channels_record_args args,
struct ast_ari_response response 
)

Start a recording.

Record audio from a channel. Note that this will not capture audio sent to the channel. The bridge itself has a record feature if that's what you want.

Parameters
headersHTTP headers
argsSwagger parameters
[out]responseHTTP response

Definition at line 748 of file resource_channels.c.

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 }
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:191
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:1979
@ AST_RECORD_IF_EXISTS_ERROR
int errno
struct stasis_app_recording_options * stasis_app_recording_options_create(const char *name, const char *format)
Allocate a recording options object.
enum ast_record_if_exists stasis_app_recording_if_exists_parse(const char *str)
Parse a string into the if_exists enum.
#define STASIS_APP_RECORDING_TERMINATE_INVALID
struct ast_json * stasis_app_recording_to_json(const struct stasis_app_recording *recording)
Construct a JSON model of a recording.
char stasis_app_recording_termination_parse(const char *str)
Parse a string into the recording termination enum.
struct stasis_app_recording * stasis_app_control_record(struct stasis_app_control *control, struct stasis_app_recording_options *options)
Record media from a channel.
#define ast_string_field_build(x, field, fmt, args...)
Set a field to a complex (built) value.
Definition: stringfields.h:555
static struct test_options options
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:723
const struct ast_flags ast_uri_http
Definition: main/utils.c:719

References ao2_cleanup, args, ast_ari_response_created(), ast_ari_response_error(), ast_asprintf, ast_assert, ast_free, ast_get_format_for_file_ext(), ast_log, ast_malloc, AST_RECORD_IF_EXISTS_ERROR, ast_string_field_build, ast_uri_encode(), ast_uri_http, errno, find_control(), LOG_WARNING, NULL, options, RAII_VAR, stasis_app_control_record(), stasis_app_recording_if_exists_parse(), stasis_app_recording_options_create(), STASIS_APP_RECORDING_TERMINATE_INVALID, stasis_app_recording_termination_parse(), and stasis_app_recording_to_json().

Referenced by ast_ari_channels_record_cb().

◆ ast_ari_channels_redirect()

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.

Parameters
headersHTTP headers
argsSwagger parameters
[out]responseHTTP response

Definition at line 276 of file resource_channels.c.

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 }
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

References ao2_cleanup, args, ast_ari_response_error(), ast_ari_response_no_content(), ast_channel_snapshot_get_latest(), ast_strdupa, ast_strlen_zero(), channel_state_invalid(), find_control(), NULL, RAII_VAR, and stasis_app_control_redirect().

Referenced by ast_ari_channels_redirect_cb().

◆ ast_ari_channels_ring()

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.

Parameters
headersHTTP headers
argsSwagger parameters
[out]responseHTTP response

Definition at line 363 of file resource_channels.c.

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 }
int stasis_app_control_ring(struct stasis_app_control *control)
Indicate ringing to the channel associated with this control.
Definition: control.c:592

References ao2_cleanup, args, ast_ari_response_no_content(), channel_state_invalid(), find_control(), NULL, RAII_VAR, and stasis_app_control_ring().

Referenced by ast_ari_channels_ring_cb().

◆ ast_ari_channels_ring_stop()

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.

Parameters
headersHTTP headers
argsSwagger parameters
[out]responseHTTP response

Definition at line 383 of file resource_channels.c.

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 }
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

References ao2_cleanup, args, ast_ari_response_no_content(), channel_state_invalid(), find_control(), NULL, RAII_VAR, and stasis_app_control_ring_stop().

Referenced by ast_ari_channels_ring_stop_cb().

◆ ast_ari_channels_rtpstatistics()

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.

Parameters
headersHTTP headers
argsSwagger parameters
[out]responseHTTP response

Definition at line 2028 of file resource_channels.c.

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 }
const struct ast_channel_tech * ast_channel_tech(const struct ast_channel *chan)
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:4012
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:2198
Structure to describe a channel "technology", ie a channel driver See for examples:
Definition: channel.h:628
const char *const type
Definition: channel.h:629
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

References ao2_cleanup, args, ast_ari_response_error(), ast_ari_response_ok(), ast_channel_cleanup, ast_channel_get_by_name(), ast_channel_lock, ast_channel_tech(), ast_channel_unlock, ast_rtp_instance_get_glue(), ast_rtp_instance_get_stats_all_json(), ast_rtp_glue::get_rtp_info, NULL, RAII_VAR, and ast_channel_tech::type.

Referenced by ast_ari_channels_rtpstatistics_cb().

◆ ast_ari_channels_send_dtmf()

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.

Parameters
headersHTTP headers
argsSwagger parameters
[out]responseHTTP response

Definition at line 487 of file resource_channels.c.

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 }
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

References ao2_cleanup, args, ast_ari_response_error(), ast_ari_response_no_content(), ast_strlen_zero(), channel_state_invalid(), find_control(), NULL, RAII_VAR, and stasis_app_control_dtmf().

Referenced by ast_ari_channels_send_dtmf_cb().

◆ ast_ari_channels_set_channel_var()

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.

Parameters
headersHTTP headers
argsSwagger parameters
[out]responseHTTP response

Definition at line 1541 of file resource_channels.c.

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 }
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

References ao2_cleanup, args, ast_ari_response_error(), ast_ari_response_no_content(), ast_assert, ast_strlen_zero(), find_control(), NULL, RAII_VAR, and stasis_app_control_set_channel_var().

Referenced by ast_ari_channels_set_channel_var_cb().

◆ ast_ari_channels_snoop_channel()

void ast_ari_channels_snoop_channel ( struct ast_variable headers,
struct ast_ari_channels_snoop_channel_args args,
struct ast_ari_response response 
)

Start snooping.

Snoop (spy/whisper) on a specific channel.

Parameters
headersHTTP headers
argsSwagger parameters
[out]responseHTTP response

Definition at line 1651 of file resource_channels.c.

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 }
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)

References args, and ari_channels_handle_snoop_channel().

Referenced by ast_ari_channels_snoop_channel_cb().

◆ ast_ari_channels_snoop_channel_with_id()

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.

Snoop (spy/whisper) on a specific channel.

Parameters
headersHTTP headers
argsSwagger parameters
[out]responseHTTP response

Definition at line 1665 of file resource_channels.c.

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 }

References args, and ari_channels_handle_snoop_channel().

Referenced by ast_ari_channels_snoop_channel_with_id_cb().

◆ ast_ari_channels_start_moh()

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.

Using media operations such as /play on a channel playing MOH in this manner will suspend MOH without resuming automatically. If continuing music on hold is desired, the stasis application must reinitiate music on hold.

Parameters
headersHTTP headers
argsSwagger parameters
[out]responseHTTP response

Definition at line 556 of file resource_channels.c.

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 }
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

References ao2_cleanup, args, ast_ari_response_no_content(), channel_state_invalid(), find_control(), NULL, RAII_VAR, and stasis_app_control_moh_start().

Referenced by ast_ari_channels_start_moh_cb().

◆ ast_ari_channels_start_silence()

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.

Using media operations such as /play on a channel playing silence in this manner will suspend silence without resuming automatically.

Parameters
headersHTTP headers
argsSwagger parameters
[out]responseHTTP response

Definition at line 596 of file resource_channels.c.

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 }
void stasis_app_control_silence_start(struct stasis_app_control *control)
Start playing silence to a channel.
Definition: control.c:832

References ao2_cleanup, args, ast_ari_response_no_content(), channel_state_invalid(), find_control(), NULL, RAII_VAR, and stasis_app_control_silence_start().

Referenced by ast_ari_channels_start_silence_cb().

◆ ast_ari_channels_stop_moh()

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.

Parameters
headersHTTP headers
argsSwagger parameters
[out]responseHTTP response

Definition at line 576 of file resource_channels.c.

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 }
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

References ao2_cleanup, args, ast_ari_response_no_content(), channel_state_invalid(), find_control(), NULL, RAII_VAR, and stasis_app_control_moh_stop().

Referenced by ast_ari_channels_stop_moh_cb().

◆ ast_ari_channels_stop_silence()

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.

Parameters
headersHTTP headers
argsSwagger parameters
[out]responseHTTP response

Definition at line 616 of file resource_channels.c.

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 }
void stasis_app_control_silence_stop(struct stasis_app_control *control)
Stop playing silence to a channel.
Definition: control.c:855

References ao2_cleanup, args, ast_ari_response_no_content(), channel_state_invalid(), find_control(), NULL, RAII_VAR, and stasis_app_control_silence_stop().

Referenced by ast_ari_channels_stop_silence_cb().

◆ ast_ari_channels_unhold()

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.

Parameters
headersHTTP headers
argsSwagger parameters
[out]responseHTTP response

Definition at line 535 of file resource_channels.c.

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 }
void stasis_app_control_unhold(struct stasis_app_control *control)
Remove the channel associated with the control from hold.
Definition: control.c:761

References ao2_cleanup, args, ast_ari_response_no_content(), channel_state_invalid(), find_control(), NULL, RAII_VAR, and stasis_app_control_unhold().

Referenced by ast_ari_channels_unhold_cb().

◆ ast_ari_channels_unmute()

void ast_ari_channels_unmute ( struct ast_variable headers,
struct ast_ari_channels_unmute_args args,
struct ast_ari_response response 
)

Unmute a channel.

Parameters
headersHTTP headers
argsSwagger parameters
[out]responseHTTP response

Definition at line 445 of file resource_channels.c.

448 {
449  RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
450  unsigned int direction = 0;
451  enum ast_frame_type frametype = AST_FRAME_VOICE;
452 
453  control = find_control(response, args->channel_id);
454  if (control == NULL) {
455  return;
456  }
457 
458  if (channel_state_invalid(control, response)) {
459  return;
460  }
461 
462  if (ast_strlen_zero(args->direction)) {
464  response, 400, "Bad Request",
465  "Direction is required");
466  return;
467  }
468 
469  if (!strcmp(args->direction, "in")) {
471  } else if (!strcmp(args->direction, "out")) {
473  } else if (!strcmp(args->direction, "both")) {
475  } else {
477  response, 400, "Bad Request",
478  "Invalid direction specified");
479  return;
480  }
481 
482  stasis_app_control_unmute(control, direction, frametype);
483 
484  ast_ari_response_no_content(response);
485 }
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

References ao2_cleanup, args, ast_ari_response_error(), ast_ari_response_no_content(), AST_FRAME_VOICE, AST_MUTE_DIRECTION_READ, AST_MUTE_DIRECTION_WRITE, ast_strlen_zero(), channel_state_invalid(), find_control(), NULL, RAII_VAR, and stasis_app_control_unmute().

Referenced by ast_ari_channels_unmute_cb().

◆ chan_data_destroy()

static void chan_data_destroy ( struct ari_channel_thread_data chan_data)
static

Definition at line 1684 of file resource_channels.c.

1685 {
1686  ast_free(chan_data->stasis_stuff);
1687  ast_hangup(chan_data->chan);
1688  ast_free(chan_data);
1689 }
void ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition: channel.c:2542

References ast_free, ast_hangup(), ari_channel_thread_data::chan, and ari_channel_thread_data::stasis_stuff.

Referenced by ari_channel_thread(), and ast_ari_channels_create().

◆ channel_state_invalid()

static int channel_state_invalid ( struct stasis_app_control control,
struct ast_ari_response response 
)
static

Ensure channel is in a state that allows operation to be performed.

Since Asterisk 14, it has been possible for down channels, as well as unanswered outbound channels to enter Stasis. While some operations are fine to perform on such channels, operations that

  • Attempt to manipulate channel state
  • Attempt to play media
  • Attempt to control the channel's location in the dialplan

are invalid. This function can be used to determine if the channel is in an appropriate state.

Note
When this function returns an error, the HTTP response is taken care of.
Parameters
controlThe app control
responseResponse to fill in if there is an error
Return values
0Channel is in a valid state. Continue on!
non-zeroChannel is in an invalid state. Bail!

Definition at line 108 of file resource_channels.c.

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 }
@ AST_STATE_RINGING
Definition: channelstate.h:41
enum ast_channel_state state

References ao2_ref, ast_ari_response_error(), AST_STATE_DOWN, AST_STATE_RESERVED, AST_STATE_RINGING, stasis_app_control_get_snapshot(), and ast_channel_snapshot::state.

Referenced by ari_channels_handle_play(), ast_ari_channels_answer(), ast_ari_channels_continue_in_dialplan(), ast_ari_channels_hold(), ast_ari_channels_mute(), ast_ari_channels_redirect(), ast_ari_channels_ring(), ast_ari_channels_ring_stop(), ast_ari_channels_send_dtmf(), ast_ari_channels_start_moh(), ast_ari_channels_start_silence(), ast_ari_channels_stop_moh(), ast_ari_channels_stop_silence(), ast_ari_channels_unhold(), and ast_ari_channels_unmute().

◆ convert_reason_to_hangup_code()

static int convert_reason_to_hangup_code ( const char *  reason)
static

Return the corresponded hangup code of the given reason.

Definition at line 53 of file resource_channels.c.

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 }
#define AST_CAUSE_CONGESTION
Definition: causes.h:153
#define AST_CAUSE_UNALLOCATED
Definition: causes.h:98
#define AST_CAUSE_INTERWORKING
Definition: causes.h:146
#define AST_CAUSE_BEARERCAPABILITY_NOTAVAIL
Definition: causes.h:130
#define AST_CAUSE_INVALID_NUMBER_FORMAT
Definition: causes.h:116
#define AST_CAUSE_FAILURE
Definition: causes.h:150
#define AST_CAUSE_NO_USER_RESPONSE
Definition: causes.h:108
#define AST_CAUSE_CALL_REJECTED
Definition: causes.h:111
#define AST_CAUSE_ANSWERED_ELSEWHERE
Definition: causes.h:114
#define AST_CAUSE_NORMAL_UNSPECIFIED
Definition: causes.h:119
#define AST_CAUSE_NOANSWER
Definition: causes.h:152
#define AST_CAUSE_BUSY
Definition: causes.h:149

References AST_CAUSE_ANSWERED_ELSEWHERE, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL, AST_CAUSE_BUSY, AST_CAUSE_CALL_REJECTED, AST_CAUSE_CONGESTION, AST_CAUSE_FAILURE, AST_CAUSE_INTERWORKING, AST_CAUSE_INVALID_NUMBER_FORMAT, AST_CAUSE_NO_USER_RESPONSE, AST_CAUSE_NOANSWER, AST_CAUSE_NORMAL, AST_CAUSE_NORMAL_UNSPECIFIED, and AST_CAUSE_UNALLOCATED.

Referenced by ast_ari_channels_hangup().

◆ external_media_audiosocket_tcp()

static void external_media_audiosocket_tcp ( struct ast_ari_channels_external_media_args args,
struct ast_variable variables,
struct ast_ari_response response 
)
static

Definition at line 2128 of file resource_channels.c.

2131 {
2132  size_t endpoint_len;
2133  char *endpoint;
2134  struct ast_channel *chan;
2135  struct varshead *vars;
2136 
2137  if (ast_strlen_zero(args->data)) {
2138  ast_ari_response_error(response, 400, "Bad Request", "data can not be empty");
2139  return;
2140  }
2141 
2142  endpoint_len = strlen("AudioSocket/") + strlen(args->external_host) + 1 + strlen(args->data) + 1;
2143  endpoint = ast_alloca(endpoint_len);
2144  /* The UUID is stored in the arbitrary data field */
2145  snprintf(endpoint, endpoint_len, "AudioSocket/%s/%s", args->external_host, args->data);
2146 
2148  endpoint,
2149  NULL,
2150  NULL,
2151  0,
2152  NULL,
2153  args->app,
2154  args->data,
2155  NULL,
2156  0,
2157  variables,
2158  args->channel_id,
2159  NULL,
2160  NULL,
2161  args->format,
2162  response);
2163  ast_variables_destroy(variables);
2164 
2165  if (!chan) {
2166  return;
2167  }
2168 
2169  ast_channel_lock(chan);
2170  vars = ast_channel_varshead(chan);
2171  if (vars && !AST_LIST_EMPTY(vars)) {
2172  ast_json_object_set(response->message, "channelvars", ast_json_channel_vars(vars));
2173  }
2174  ast_channel_unlock(chan);
2175  ast_channel_unref(chan);
2176 }
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: astmm.h:288
struct varshead * ast_channel_varshead(struct ast_channel *chan)
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_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_LIST_EMPTY(head)
Checks whether the specified list contains any entries.
Definition: linkedlists.h:450
struct ast_json * message
Definition: ari.h:94

References args, ari_channels_handle_originate_with_id(), ast_alloca, ast_ari_response_error(), ast_channel_lock, ast_channel_unlock, ast_channel_unref, ast_channel_varshead(), ast_json_channel_vars(), ast_json_object_set(), AST_LIST_EMPTY, ast_strlen_zero(), ast_variables_destroy(), ast_ari_response::message, and NULL.

Referenced by ast_ari_channels_external_media().

◆ external_media_rtp_udp()

static void external_media_rtp_udp ( struct ast_ari_channels_external_media_args args,
struct ast_variable variables,
struct ast_ari_response response 
)
static

Definition at line 2084 of file resource_channels.c.

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  args->data,
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 }

References args, ari_channels_handle_originate_with_id(), ast_alloca, ast_channel_lock, ast_channel_unlock, ast_channel_unref, ast_channel_varshead(), ast_json_channel_vars(), ast_json_object_set(), AST_LIST_EMPTY, ast_variables_destroy(), ast_ari_response::message, and NULL.

Referenced by ast_ari_channels_external_media().

◆ find_control()

static struct stasis_app_control* find_control ( struct ast_ari_response response,
const char *  channel_id 
)
static

Finds the control object for a channel, filling the response with an error, if appropriate.

Parameters
[out]responseResponse to fill with an error if control is not found.
channel_idID of the channel to lookup.
Returns
Channel control object.
Return values
NULLif control object does not exist.

Definition at line 152 of file resource_channels.c.

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 }
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

References ao2_cleanup, ao2_ref, ast_ari_response_error(), ast_assert, ast_channel_get_by_name(), NULL, RAII_VAR, and stasis_app_control_find_by_channel_id().

Referenced by ari_channels_handle_play(), ast_ari_channels_answer(), ast_ari_channels_continue_in_dialplan(), ast_ari_channels_dial(), ast_ari_channels_hold(), ast_ari_channels_move(), ast_ari_channels_mute(), ast_ari_channels_record(), ast_ari_channels_redirect(), ast_ari_channels_ring(), ast_ari_channels_ring_stop(), ast_ari_channels_send_dtmf(), ast_ari_channels_set_channel_var(), ast_ari_channels_start_moh(), ast_ari_channels_start_silence(), ast_ari_channels_stop_moh(), ast_ari_channels_stop_silence(), ast_ari_channels_unhold(), and ast_ari_channels_unmute().

◆ json_to_ast_variables()

static int json_to_ast_variables ( struct ast_ari_response response,
struct ast_json json_variables,
struct ast_variable **  variables 
)
static

Definition at line 1373 of file resource_channels.c.

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 }
ast_json_to_ast_vars_code
Definition: json.h:1071
@ AST_JSON_TO_AST_VARS_CODE_INVALID_TYPE
Conversion failed because invalid value type supplied.
Definition: json.h:1078
@ AST_JSON_TO_AST_VARS_CODE_SUCCESS
Conversion successful.
Definition: json.h:1073
@ AST_JSON_TO_AST_VARS_CODE_OOM
Conversion failed because of allocation failure. (Out Of Memory)
Definition: json.h:1080
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

References ast_ari_response_alloc_failed(), ast_ari_response_error(), ast_json_to_ast_variables(), AST_JSON_TO_AST_VARS_CODE_INVALID_TYPE, AST_JSON_TO_AST_VARS_CODE_OOM, AST_JSON_TO_AST_VARS_CODE_SUCCESS, ast_log, and AST_LOG_ERROR.

Referenced by ast_ari_channels_create(), ast_ari_channels_external_media(), ast_ari_channels_originate(), and ast_ari_channels_originate_with_id().

◆ restore_dialstring()

static char* restore_dialstring ( struct ast_channel chan)
static

Retrieve the dialstring from the channel datastore.

Precondition
chan is locked
Parameters
chanChannel that was previously created in ARI
Return values
NULLFailed to find datastore
non-NULLThe dialstring

Definition at line 1766 of file resource_channels.c.

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 }
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:2398
struct ast_datastore_info dialstring_info
Structure for a data store object.
Definition: datastore.h:64
void * data
Definition: datastore.h:66

References ast_channel_datastore_find(), ast_datastore::data, dialstring_info, and NULL.

Referenced by ast_ari_channels_dial().

◆ save_dialstring()

static int save_dialstring ( struct ast_channel chan,
const char *  dialstring 
)
static

Save dialstring onto a channel datastore.

This will later be retrieved when it comes time to actually dial the channel

Parameters
chanThe channel on which to save the dialstring
dialstringThe dialstring to save
Return values
0on success.
-1on error.

Definition at line 1732 of file resource_channels.c.

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 }
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:241
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
Definition: channel.c:2384
#define ast_datastore_alloc(info, uid)
Definition: datastore.h:85
int ast_datastore_free(struct ast_datastore *datastore)
Free a data store object.
Definition: datastore.c:68

References ast_channel_datastore_add(), ast_channel_lock, ast_channel_unlock, ast_datastore_alloc, ast_datastore_free(), ast_strdup, ast_datastore::data, dialstring_info, and NULL.

Referenced by ast_ari_channels_create().

Variable Documentation

◆ dialstring_info

struct ast_datastore_info dialstring_info
Initial value:
= {
.type = "ARI Dialstring",
.destroy = ast_free_ptr,
}
void ast_free_ptr(void *ptr)
free() wrapper
Definition: astmm.c:1739

Definition at line 1698 of file resource_channels.c.

Referenced by restore_dialstring(), and save_dialstring().