Asterisk - The Open Source Telephony Project GIT-master-77d630f
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 "asterisk/websocket_client.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_progress (struct ast_variable *headers, struct ast_ari_channels_progress_args *args, struct ast_ari_response *response)
 Indicate progress on a channel. 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_transfer_progress (struct ast_variable *headers, struct ast_ari_channels_transfer_progress_args *args, struct ast_ari_response *response)
 Inform the channel about the progress of the attended/blind transfer. 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 int external_media_audiosocket_tcp (struct ast_ari_channels_external_media_args *args, struct ast_variable *variables, struct ast_ari_response *response)
 
static int external_media_rtp_udp (struct ast_ari_channels_external_media_args *args, struct ast_variable *variables, struct ast_ari_response *response)
 
static int external_media_websocket (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 1719 of file resource_channels.c.

1720{
1721 struct ari_channel_thread_data *chan_data = data;
1722 struct ast_app *stasis_app;
1723
1724 stasis_app = pbx_findapp("Stasis");
1725 if (!stasis_app) {
1726 ast_log(LOG_ERROR, "Stasis dialplan application is not registered");
1727 chan_data_destroy(chan_data);
1728 return NULL;
1729 }
1730
1731 pbx_exec(chan_data->chan, stasis_app, ast_str_buffer(chan_data->stasis_stuff));
1732
1733 chan_data_destroy(chan_data);
1734
1735 return NULL;
1736}
#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:761
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 1084 of file resource_channels.c.

1099{
1100 char *dialtech;
1101 char *dialdevice = NULL;
1102 struct ast_dial *dial;
1103 char *caller_id = NULL;
1104 char *cid_num = NULL;
1105 char *cid_name = NULL;
1106 char *stuff;
1107 struct ast_channel *other = NULL;
1108 struct ast_channel *chan = NULL;
1110 struct ast_assigned_ids assignedids = {
1111 .uniqueid = args_channel_id,
1112 .uniqueid2 = args_other_channel_id,
1113 };
1114 struct ari_origination *origination;
1115 pthread_t thread;
1116 struct ast_format_cap *format_cap = NULL;
1117
1118 if ((assignedids.uniqueid && AST_MAX_PUBLIC_UNIQUEID < strlen(assignedids.uniqueid))
1119 || (assignedids.uniqueid2 && AST_MAX_PUBLIC_UNIQUEID < strlen(assignedids.uniqueid2))) {
1120 ast_ari_response_error(response, 400, "Bad Request",
1121 "Uniqueid length exceeds maximum of %d", AST_MAX_PUBLIC_UNIQUEID);
1122 return NULL;
1123 }
1124
1125 if (ast_strlen_zero(args_endpoint)) {
1126 ast_ari_response_error(response, 400, "Bad Request",
1127 "Endpoint must be specified");
1128 return NULL;
1129 }
1130
1131 if (!ast_strlen_zero(args_originator) && !ast_strlen_zero(args_formats)) {
1132 ast_ari_response_error(response, 400, "Bad Request",
1133 "Originator and formats can't both be specified");
1134 return NULL;
1135 }
1136
1137 dialtech = ast_strdupa(args_endpoint);
1138 if ((stuff = strchr(dialtech, '/'))) {
1139 *stuff++ = '\0';
1140 dialdevice = stuff;
1141 }
1142
1143 if (ast_strlen_zero(dialtech) || ast_strlen_zero(dialdevice)) {
1144 ast_ari_response_error(response, 400, "Bad Request",
1145 "Invalid endpoint specified");
1146 return NULL;
1147 }
1148
1149 if (!ast_strlen_zero(args_app)) {
1150 RAII_VAR(struct ast_str *, appdata, ast_str_create(64), ast_free);
1151
1152 if (!appdata) {
1154 return NULL;
1155 }
1156
1157 ast_str_set(&appdata, 0, "%s", args_app);
1158 if (!ast_strlen_zero(args_app_args)) {
1159 ast_str_append(&appdata, 0, ",%s", args_app_args);
1160 }
1161
1162 origination = ast_calloc(1, sizeof(*origination) + ast_str_size(appdata) + 1);
1163 if (!origination) {
1165 return NULL;
1166 }
1167
1168 strcpy(origination->appdata, ast_str_buffer(appdata));
1169 } else if (!ast_strlen_zero(args_extension)) {
1170 origination = ast_calloc(1, sizeof(*origination) + 1);
1171 if (!origination) {
1173 return NULL;
1174 }
1175
1176 ast_copy_string(origination->context, S_OR(args_context, "default"), sizeof(origination->context));
1177 ast_copy_string(origination->exten, args_extension, sizeof(origination->exten));
1178
1179 if (!ast_strlen_zero(args_label)) {
1180 /* A label was provided in the request, use that */
1181 int ipri = 1;
1182 if (sscanf(args_label, "%30d", &ipri) != 1) {
1183 ipri = ast_findlabel_extension(chan, origination->context, origination->exten, args_label, args_caller_id);
1184
1185 if (ipri == -1) {
1186 ast_log(AST_LOG_ERROR, "Requested label: %s can not be found in context: %s\n", args_label, args_context);
1187 ast_ari_response_error(response, 404, "Not Found", "Requested label can not be found");
1188 return NULL;
1189 }
1190 } else {
1191 ast_debug(3, "Numeric value provided for label, jumping to that priority\n");
1192 }
1193
1194 if (ipri == 0) {
1195 ast_log(AST_LOG_ERROR, "Invalid priority label '%s' specified for extension %s in context: %s\n",
1196 args_label, args_extension, args_context);
1197 ast_ari_response_error(response, 400, "Bad Request", "Requested priority is illegal");
1198 return NULL;
1199 }
1200
1201 /* Our priority was provided by a label */
1202 origination->priority = ipri;
1203 } else {
1204 /* No label provided, use provided priority */
1205 origination->priority = args_priority ? args_priority : 1;
1206 }
1207
1208 origination->appdata[0] = '\0';
1209 } else {
1210 ast_ari_response_error(response, 400, "Bad Request",
1211 "Application or extension must be specified");
1212 return NULL;
1213 }
1214
1215 dial = ast_dial_create();
1216 if (!dial) {
1218 ast_free(origination);
1219 return NULL;
1220 }
1221 ast_dial_set_user_data(dial, origination);
1222
1223 if (ast_dial_append(dial, dialtech, dialdevice, &assignedids)) {
1225 ast_dial_destroy(dial);
1226 ast_free(origination);
1227 return NULL;
1228 }
1229
1230 if (args_timeout > 0) {
1231 ast_dial_set_global_timeout(dial, args_timeout * 1000);
1232 } else if (args_timeout == -1) {
1234 } else {
1235 ast_dial_set_global_timeout(dial, 30000);
1236 }
1237
1238 if (!ast_strlen_zero(args_caller_id)) {
1239 caller_id = ast_strdupa(args_caller_id);
1240 ast_callerid_parse(caller_id, &cid_name, &cid_num);
1241
1242 if (ast_is_shrinkable_phonenumber(cid_num)) {
1243 ast_shrink_phone_number(cid_num);
1244 }
1245 }
1246
1247 if (!ast_strlen_zero(args_originator)) {
1248 other = ast_channel_get_by_name(args_originator);
1249 if (!other) {
1251 response, 400, "Bad Request",
1252 "Provided originator channel was not found");
1253 ast_dial_destroy(dial);
1254 ast_free(origination);
1255 return NULL;
1256 }
1257 }
1258
1259 if (!ast_strlen_zero(args_formats)) {
1260 char *format_name;
1261 char *formats_copy = ast_strdupa(args_formats);
1262
1265 ast_dial_destroy(dial);
1266 ast_free(origination);
1267 ast_channel_cleanup(other);
1268 return NULL;
1269 }
1270
1271 while ((format_name = ast_strip(strsep(&formats_copy, ",")))) {
1272 struct ast_format *fmt = ast_format_cache_get(format_name);
1273
1274 if (!fmt || ast_format_cap_append(format_cap, fmt, 0)) {
1275 if (!fmt) {
1277 response, 400, "Bad Request",
1278 "Provided format (%s) was not found", format_name);
1279 } else {
1281 }
1282 ast_dial_destroy(dial);
1283 ast_free(origination);
1284 ast_channel_cleanup(other);
1285 ao2_ref(format_cap, -1);
1286 ao2_cleanup(fmt);
1287 return NULL;
1288 }
1289 ao2_ref(fmt, -1);
1290 }
1291 }
1292
1293 if (ast_dial_prerun(dial, other, format_cap)) {
1295 ast_ari_response_error(response, 409, "Conflict",
1296 "Channel with given unique ID already exists");
1297 } else {
1299 }
1300 ast_dial_destroy(dial);
1301 ast_free(origination);
1302 ast_channel_cleanup(other);
1303 return NULL;
1304 }
1305
1306 ast_channel_cleanup(other);
1307 ao2_cleanup(format_cap);
1308
1309 chan = ast_dial_get_channel(dial, 0);
1310 if (!chan) {
1312 ast_dial_destroy(dial);
1313 ast_free(origination);
1314 return NULL;
1315 }
1316
1317 if (!ast_strlen_zero(cid_num) || !ast_strlen_zero(cid_name)) {
1319
1320 /*
1321 * It seems strange to set the CallerID on an outgoing call leg
1322 * to whom we are calling, but this function's callers are doing
1323 * various Originate methods. This call leg goes to the local
1324 * user. Once the called party answers, the dialplan needs to
1325 * be able to access the CallerID from the CALLERID function as
1326 * if the called party had placed this call.
1327 */
1328 ast_set_callerid(chan, cid_num, cid_name, cid_num);
1329
1331 if (!ast_strlen_zero(cid_num)) {
1332 connected.id.number.valid = 1;
1333 connected.id.number.str = (char *) cid_num;
1335 }
1336 if (!ast_strlen_zero(cid_name)) {
1337 connected.id.name.valid = 1;
1338 connected.id.name.str = (char *) cid_name;
1340 }
1342 }
1343
1344 ast_channel_lock(chan);
1345 if (variables) {
1346 ast_set_variables(chan, variables);
1347 }
1349
1350 if (!ast_strlen_zero(args_app)) {
1351 struct ast_channel *local_peer;
1352
1353 stasis_app_subscribe_channel(args_app, chan);
1354
1355 /* Subscribe to the Local channel peer also. */
1356 local_peer = ast_local_get_peer(chan);
1357 if (local_peer) {
1358 stasis_app_subscribe_channel(args_app, local_peer);
1359 ast_channel_unref(local_peer);
1360 }
1361 }
1362
1364 ast_channel_unlock(chan);
1365
1366 /* Before starting the async dial bump the ref in case the dial quickly goes away and takes
1367 * the reference with it
1368 */
1369 ast_channel_ref(chan);
1370
1373 ast_dial_destroy(dial);
1374 ast_free(origination);
1375 } else {
1377 }
1378
1379 return chan;
1380}
pthread_t thread
Definition: app_sla.c:335
void ast_ari_response_error(struct ast_ari_response *response, int response_code, const char *response_text, const char *message_fmt,...)
Fill in an error ast_ari_response.
Definition: res_ari.c:212
void ast_ari_response_ok(struct ast_ari_response *response, struct ast_json *message)
Fill in an OK (200) ast_ari_response.
Definition: res_ari.c:229
void ast_ari_response_alloc_failed(struct ast_ari_response *response)
Fill in response with a 500 message for allocation failures.
Definition: res_ari.c:251
char * strsep(char **str, const char *delims)
#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:1162
void ast_shrink_phone_number(char *n)
Shrink a phone number in place to just digits (more accurately it just removes ()'s,...
Definition: callerid.c:1101
int ast_is_shrinkable_phonenumber(const char *exten)
Check if a string consists only of digits and + # ( ) - . (meaning it can be cleaned with ast_shrink_...
Definition: callerid.c:1157
#define AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED
Definition: callerid.h:437
#define AST_MAX_PUBLIC_UNIQUEID
Definition: channel.h:147
enum ast_channel_error ast_channel_errno(void)
Get error code for latest channel operation.
Definition: channel.c:10975
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:8322
#define ast_channel_lock(chan)
Definition: channel.h:2972
void ast_set_variables(struct ast_channel *chan, struct ast_variable *vars)
adds a list of channel variables to a channel
Definition: channel.c:8129
struct ast_flags * ast_channel_flags(struct ast_channel *chan)
@ AST_CHANNEL_ERROR_ID_EXISTS
Definition: channel.h:4875
#define ast_channel_ref(c)
Increase channel reference count.
Definition: channel.h:2997
struct ast_party_connected_line * ast_channel_connected(struct ast_channel *chan)
@ AST_FLAG_ORIGINATED
Definition: channel.h:1059
const char * ast_channel_uniqueid(const struct ast_channel *chan)
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:7316
struct ast_channel * ast_channel_get_by_name(const char *search)
Find a channel by name or uniqueid.
Definition: channel.c:1398
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:3008
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:2013
#define ast_channel_cleanup(c)
Cleanup a channel reference.
Definition: channel.h:3019
#define ast_channel_unlock(chan)
Definition: channel.h:2973
struct ast_channel * ast_local_get_peer(struct ast_channel *ast)
Get the other local channel in the pair.
Definition: core_local.c:288
int ast_dial_append(struct ast_dial *dial, const char *tech, const char *device, const struct ast_assigned_ids *assignedids)
Append a channel.
Definition: dial.c:280
struct ast_dial * ast_dial_create(void)
New dialing structure.
Definition: dial.c:223
void ast_dial_set_user_data(struct ast_dial *dial, void *user_data)
Set user data on a dial structure.
Definition: dial.c:1274
int ast_dial_prerun(struct ast_dial *dial, struct ast_channel *chan, struct ast_format_cap *cap)
Request all appended channels, but do not dial.
Definition: dial.c:431
void ast_dial_set_global_timeout(struct ast_dial *dial, int timeout)
Set the maximum time (globally) allowed for trying to ring phones.
Definition: dial.c:1284
struct ast_channel * ast_dial_get_channel(struct ast_dial *dial, int num)
Get the dialing channel, if prerun has been executed.
Definition: dial.c:1258
int ast_dial_destroy(struct ast_dial *dial)
Destroys a dialing structure.
Definition: dial.c:1091
char connected
Definition: eagi_proxy.c:82
#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,...
#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:4201
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:2063
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:1139
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one.
Definition: strings.h:80
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
Definition: strings.h:659
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
Definition: strings.h:1113
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:425
char * ast_strip(char *s)
Strip leading/trailing whitespace from a string.
Definition: strings.h:223
size_t ast_str_size(const struct ast_str *buf)
Returns the current maximum length (without reallocation) of the current buffer.
Definition: strings.h:742
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:606
const char * uniqueid2
Definition: channel.h:608
const char * uniqueid
Definition: channel.h:607
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:458
Support for dynamic strings.
Definition: strings.h:623
#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:978
#define ast_pthread_create_detached(a, b, c, d)
Definition: utils.h:625
#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(), 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(), external_media_rtp_udp(), and external_media_websocket().

◆ 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 657 of file resource_channels.c.

666{
667 RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
668 RAII_VAR(struct ast_channel_snapshot *, snapshot, NULL, ao2_cleanup);
669 RAII_VAR(struct stasis_app_playback *, playback, NULL, ao2_cleanup);
670 RAII_VAR(char *, playback_url, NULL, ast_free);
671 struct ast_json *json;
672 const char *language;
673
674 ast_assert(response != NULL);
675
676 control = find_control(response, args_channel_id);
677 if (control == NULL) {
678 /* Response filled in by find_control */
679 return;
680 }
681
682 if (channel_state_invalid(control, response)) {
683 return;
684 }
685
686 snapshot = stasis_app_control_get_snapshot(control);
687 if (!snapshot) {
689 response, 404, "Not Found",
690 "Channel not found");
691 return;
692 }
693
694 if (args_skipms < 0) {
696 response, 400, "Bad Request",
697 "skipms cannot be negative");
698 return;
699 }
700
701 if (args_offsetms < 0) {
703 response, 400, "Bad Request",
704 "offsetms cannot be negative");
705 return;
706 }
707
708 language = S_OR(args_lang, snapshot->base->language);
709
710 playback = stasis_app_control_play_uri(control, args_media, args_media_count, language,
711 args_channel_id, STASIS_PLAYBACK_TARGET_CHANNEL, args_skipms, args_offsetms, args_playback_id);
712 if (!playback) {
714 response, 500, "Internal Server Error",
715 "Failed to queue media for playback");
716 return;
717 }
718
719 if (ast_asprintf(&playback_url, "/playbacks/%s",
720 stasis_app_playback_get_id(playback)) == -1) {
721 playback_url = NULL;
723 response, 500, "Internal Server Error",
724 "Out of memory");
725 return;
726 }
727
728 json = stasis_app_playback_to_json(playback);
729 if (!json) {
731 response, 500, "Internal Server Error",
732 "Out of memory");
733 return;
734 }
735
736 ast_ari_response_created(response, playback_url, json);
737}
void ast_ari_response_created(struct ast_ari_response *response, const char *url, struct ast_json *message)
Fill in a Created (201) ast_ari_response.
Definition: res_ari.c:258
#define ast_asprintf(ret, fmt,...)
A wrapper for asprintf()
Definition: astmm.h:267
static char language[MAX_LANGUAGE]
Definition: chan_iax2.c:348
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:901
@ STASIS_PLAYBACK_TARGET_CHANNEL
struct stasis_app_playback * stasis_app_control_play_uri(struct stasis_app_control *control, const char **media, size_t media_count, const char *language, const char *target_id, enum stasis_app_playback_target_type target_type, int skipms, long offsetms, const char *id)
Play a file to the control's channel.
struct ast_json * stasis_app_playback_to_json(const struct stasis_app_playback *playback)
Convert a playback to its JSON representation.
const char * stasis_app_playback_get_id(struct stasis_app_playback *playback)
Gets the unique id of a playback object.
Abstract JSON element (object, array, string, int, ...).
#define ast_assert(a)
Definition: utils.h:776

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 1593 of file resource_channels.c.

1601{
1602 enum stasis_app_snoop_direction spy, whisper;
1603 RAII_VAR(struct ast_channel *, chan, NULL, ast_channel_cleanup);
1604 RAII_VAR(struct ast_channel *, snoop, NULL, ast_channel_cleanup);
1605 RAII_VAR(struct ast_channel_snapshot *, snapshot, NULL, ao2_cleanup);
1606
1607 ast_assert(response != NULL);
1608
1609 if (ast_strlen_zero(args_spy) || !strcmp(args_spy, "none")) {
1611 } else if (!strcmp(args_spy, "both")) {
1613 } else if (!strcmp(args_spy, "out")) {
1615 } else if (!strcmp(args_spy, "in")) {
1617 } else {
1619 response, 400, "Bad Request",
1620 "Invalid direction specified for spy");
1621 return;
1622 }
1623
1624 if (ast_strlen_zero(args_whisper) || !strcmp(args_whisper, "none")) {
1626 } else if (!strcmp(args_whisper, "both")) {
1628 } else if (!strcmp(args_whisper, "out")) {
1630 } else if (!strcmp(args_whisper, "in")) {
1631 whisper = STASIS_SNOOP_DIRECTION_IN;
1632 } else {
1634 response, 400, "Bad Request",
1635 "Invalid direction specified for whisper");
1636 return;
1637 }
1638
1641 response, 400, "Bad Request",
1642 "Direction must be specified for at least spy or whisper");
1643 return;
1644 } else if (ast_strlen_zero(args_app)) {
1646 response, 400, "Bad Request",
1647 "Application name is required");
1648 return;
1649 }
1650
1651 chan = ast_channel_get_by_name(args_channel_id);
1652 if (chan == NULL) {
1654 response, 404, "Channel Not Found",
1655 "Provided channel was not found");
1656 return;
1657 }
1658
1659 snoop = stasis_app_control_snoop(chan, spy, whisper, args_app, args_app_args,
1660 args_snoop_id);
1661 if (snoop == NULL) {
1663 response, 500, "Internal error",
1664 "Snoop channel could not be created");
1665 return;
1666 }
1667
1670}
struct ast_channel * stasis_app_control_snoop(struct ast_channel *chan, enum stasis_app_snoop_direction spy, enum stasis_app_snoop_direction whisper, const char *app, const char *app_args, const char *snoop_id)
Create a snoop on the provided channel.
stasis_app_snoop_direction
Directions for audio stream flow.
@ STASIS_SNOOP_DIRECTION_IN
Audio stream in from the channel.
@ STASIS_SNOOP_DIRECTION_OUT
Audio stream out to the channel.
@ STASIS_SNOOP_DIRECTION_NONE
No direction.
@ STASIS_SNOOP_DIRECTION_BOTH
Audio stream to AND from the channel.

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 1034 of file resource_channels.c.

1035{
1036 struct ast_dial *dial = data;
1037 struct ari_origination *origination = ast_dial_get_user_data(dial);
1038 enum ast_dial_result res;
1039
1040 res = ast_dial_run(dial, NULL, 0);
1041 if (res != AST_DIAL_RESULT_ANSWERED) {
1042 goto end;
1043 }
1044
1045 if (!ast_strlen_zero(origination->appdata)) {
1046 struct ast_app *app = pbx_findapp("Stasis");
1047
1048 if (app) {
1049 ast_verb(4, "Launching Stasis(%s) on %s\n", origination->appdata,
1051 pbx_exec(ast_dial_answered(dial), app, origination->appdata);
1052 } else {
1053 ast_log(LOG_WARNING, "No such application 'Stasis'\n");
1054 }
1055 } else {
1056 struct ast_channel *answered = ast_dial_answered(dial);
1057
1058 if (!ast_strlen_zero(origination->context)) {
1059 ast_channel_context_set(answered, origination->context);
1060 }
1061
1062 if (!ast_strlen_zero(origination->exten)) {
1063 ast_channel_exten_set(answered, origination->exten);
1064 }
1065
1066 if (origination->priority > 0) {
1067 ast_channel_priority_set(answered, origination->priority);
1068 }
1069
1070 if (ast_pbx_run(answered)) {
1071 ast_log(LOG_ERROR, "Failed to start PBX on %s\n", ast_channel_name(answered));
1072 } else {
1073 /* PBX will have taken care of hanging up, so we steal the answered channel so dial doesn't do it */
1075 }
1076 }
1077
1078end:
1079 ast_dial_destroy(dial);
1080 ast_free(origination);
1081 return NULL;
1082}
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
struct ast_channel * ast_dial_answered(struct ast_dial *dial)
Return channel that answered.
Definition: dial.c:977
enum ast_dial_result ast_dial_run(struct ast_dial *dial, struct ast_channel *chan, int async)
Execute dialing synchronously or asynchronously.
Definition: dial.c:935
struct ast_channel * ast_dial_answered_steal(struct ast_dial *dial)
Steal the channel that answered.
Definition: dial.c:989
void * ast_dial_get_user_data(struct ast_dial *dial)
Return the user data on a dial structure.
Definition: dial.c:1279
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:4776

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 339 of file resource_channels.c.

342{
343 RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
344
345 control = find_control(response, args->channel_id);
346 if (control == NULL) {
347 return;
348 }
349
350 if (channel_state_invalid(control, response)) {
351 return;
352 }
353
354 if (stasis_app_control_answer(control) != 0) {
356 response, 500, "Internal Server Error",
357 "Failed to answer channel");
358 return;
359 }
360
362}
void ast_ari_response_no_content(struct ast_ari_response *response)
Fill in a No Content (204) ast_ari_response.
Definition: res_ari.c:237
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 181 of file resource_channels.c.

185{
186 RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
187 RAII_VAR(struct ast_channel_snapshot *, snapshot, NULL, ao2_cleanup);
188 int ipri;
189 const char *context;
190 const char *exten;
191
192 ast_assert(response != NULL);
193
194 control = find_control(response, args->channel_id);
195 if (control == NULL) {
196 return;
197 }
198
199 if (channel_state_invalid(control, response)) {
200 return;
201 }
202
203 snapshot = stasis_app_control_get_snapshot(control);
204 if (!snapshot) {
205 ast_ari_response_error(response, 404, "Not Found", "Channel not found");
206 return;
207 }
208
209 if (ast_strlen_zero(args->context)) {
210 context = snapshot->dialplan->context;
211 exten = S_OR(args->extension, snapshot->dialplan->exten);
212 } else {
213 context = args->context;
214 exten = S_OR(args->extension, "s");
215 }
216
217 if (!ast_strlen_zero(args->label)) {
218 /* A label was provided in the request, use that */
219
220 if (sscanf(args->label, "%30d", &ipri) != 1) {
221 ipri = ast_findlabel_extension(NULL, context, exten, args->label, NULL);
222 if (ipri == -1) {
223 ast_log(AST_LOG_ERROR, "Requested label: %s can not be found in context: %s\n", args->label, context);
224 ast_ari_response_error(response, 404, "Not Found", "Requested label can not be found");
225 return;
226 }
227 } else {
228 ast_debug(3, "Numeric value provided for label, jumping to that priority\n");
229 }
230
231 if (ipri == 0) {
232 ast_log(AST_LOG_ERROR, "Invalid priority label '%s' specified for extension %s in context: %s\n",
233 args->label, exten, context);
234 ast_ari_response_error(response, 400, "Bad Request", "Requested priority is illegal");
235 return;
236 }
237
238 } else if (args->priority) {
239 /* No label provided, use provided priority */
240 ipri = args->priority;
241 } else if (ast_strlen_zero(args->context) && ast_strlen_zero(args->extension)) {
242 /* Special case. No exten, context, or priority provided, then move on to the next priority */
243 ipri = snapshot->dialplan->priority + 1;
244 } else {
245 ipri = 1;
246 }
247
248
249 if (stasis_app_control_continue(control, context, exten, ipri)) {
251 return;
252 }
253
255}
int stasis_app_control_continue(struct stasis_app_control *control, const char *context, const char *extension, int priority)
Exit res_stasis and continue execution in the dialplan.
Definition: control.c:415

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(), voicemailpwcheck::context, 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 1799 of file resource_channels.c.

1802{
1803 RAII_VAR(struct ast_variable *, variables, NULL, ast_variables_destroy);
1804 struct ast_assigned_ids assignedids;
1805 struct ari_channel_thread_data *chan_data;
1806 struct ast_channel_snapshot *snapshot;
1807 pthread_t thread;
1808 char *dialtech;
1809 char *dialdevice = NULL;
1810 char *stuff;
1811 int cause;
1812 struct ast_format_cap *request_cap;
1813 struct ast_channel *originator = NULL;
1814
1815 /* Parse any query parameters out of the body parameter */
1816 if (args->variables) {
1817 struct ast_json *json_variables;
1818
1820 json_variables = ast_json_object_get(args->variables, "variables");
1821 if (json_variables
1822 && json_to_ast_variables(response, json_variables, &variables)) {
1823 return;
1824 }
1825 }
1826
1827 assignedids.uniqueid = args->channel_id;
1828 assignedids.uniqueid2 = args->other_channel_id;
1829
1830 if (!ast_strlen_zero(args->originator) && !ast_strlen_zero(args->formats)) {
1831 ast_ari_response_error(response, 400, "Bad Request",
1832 "Originator and formats can't both be specified");
1833 return;
1834 }
1835
1836 if (ast_strlen_zero(args->endpoint)) {
1837 ast_ari_response_error(response, 400, "Bad Request",
1838 "Endpoint must be specified");
1839 return;
1840 }
1841
1842 chan_data = ast_calloc(1, sizeof(*chan_data));
1843 if (!chan_data) {
1845 return;
1846 }
1847
1848 chan_data->stasis_stuff = ast_str_create(32);
1849 if (!chan_data->stasis_stuff) {
1851 chan_data_destroy(chan_data);
1852 return;
1853 }
1854
1855 ast_str_append(&chan_data->stasis_stuff, 0, "%s", args->app);
1856 if (!ast_strlen_zero(args->app_args)) {
1857 ast_str_append(&chan_data->stasis_stuff, 0, ",%s", args->app_args);
1858 }
1859
1860 dialtech = ast_strdupa(args->endpoint);
1861 if ((stuff = strchr(dialtech, '/'))) {
1862 *stuff++ = '\0';
1863 dialdevice = stuff;
1864 }
1865
1866 if (ast_strlen_zero(dialtech) || ast_strlen_zero(dialdevice)) {
1867 ast_ari_response_error(response, 400, "Bad Request",
1868 "Invalid endpoint specified");
1869 chan_data_destroy(chan_data);
1870 return;
1871 }
1872
1873 if (!ast_strlen_zero(args->originator)) {
1874 originator = ast_channel_get_by_name(args->originator);
1875 }
1876
1877 if (originator) {
1878 request_cap = ao2_bump(ast_channel_nativeformats(originator));
1879 if (!ast_strlen_zero(args->app)) {
1880 stasis_app_subscribe_channel(args->app, originator);
1881 }
1882 } else if (!ast_strlen_zero(args->formats)) {
1883 char *format_name;
1884 char *formats_copy = ast_strdupa(args->formats);
1885
1886 if (!(request_cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
1888 chan_data_destroy(chan_data);
1889 return;
1890 }
1891
1892 while ((format_name = ast_strip(strsep(&formats_copy, ",")))) {
1893 struct ast_format *fmt = ast_format_cache_get(format_name);
1894
1895 if (!fmt || ast_format_cap_append(request_cap, fmt, 0)) {
1896 if (!fmt) {
1898 response, 400, "Bad Request",
1899 "Provided format (%s) was not found", format_name);
1900 } else {
1902 }
1903 ao2_ref(request_cap, -1);
1904 ao2_cleanup(fmt);
1905 chan_data_destroy(chan_data);
1906 return;
1907 }
1908 ao2_ref(fmt, -1);
1909 }
1910 } else {
1911 if (!(request_cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
1913 chan_data_destroy(chan_data);
1914 return;
1915 }
1916
1918 }
1919
1920 chan_data->chan = ast_request(dialtech, request_cap, &assignedids, originator, dialdevice, &cause);
1921 ao2_cleanup(request_cap);
1922
1923 if (!chan_data->chan) {
1925 ast_ari_response_error(response, 409, "Conflict",
1926 "Channel with given unique ID already exists");
1927 } else {
1929 }
1930 ast_channel_cleanup(originator);
1931 chan_data_destroy(chan_data);
1932 return;
1933 }
1934
1935 if (!ast_strlen_zero(args->app)) {
1936 stasis_app_subscribe_channel(args->app, chan_data->chan);
1937 }
1938
1939 if (variables) {
1940 ast_set_variables(chan_data->chan, variables);
1941 }
1942
1943 ast_channel_cleanup(originator);
1944
1945 if (save_dialstring(chan_data->chan, stuff)) {
1947 chan_data_destroy(chan_data);
1948 return;
1949 }
1950
1952
1955 chan_data_destroy(chan_data);
1956 } else {
1958 }
1959
1960 ao2_ref(snapshot, -1);
1961}
#define ao2_bump(obj)
Bump refcount on an AO2 object by one, returning the object.
Definition: astobj2.h:480
struct ast_format_cap * ast_channel_nativeformats(const struct ast_channel *chan)
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:6322
@ 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
void ast_variables_destroy(struct ast_variable *var)
Free variable list.
Definition: extconf.c:1260
struct ast_json * ast_json_object_get(struct ast_json *object, const char *key)
Get a field from a JSON object.
Definition: json.c:407
static int save_dialstring(struct ast_channel *chan, const char *dialstring)
Save dialstring onto a channel datastore.
static int json_to_ast_variables(struct ast_ari_response *response, struct ast_json *json_variables, struct ast_variable **variables)
static void * ari_channel_thread(void *data)
Thread that owns stasis-created channel.
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(), ast_variables_destroy(), ari_channel_thread_data::chan, chan_data_destroy(), json_to_ast_variables(), NULL, RAII_VAR, 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 1963 of file resource_channels.c.

1966{
1967 RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
1968 RAII_VAR(struct ast_channel *, caller, NULL, ast_channel_cleanup);
1969 RAII_VAR(struct ast_channel *, callee, NULL, ast_channel_cleanup);
1970 char *dialstring;
1971
1972 control = find_control(response, args->channel_id);
1973 if (control == NULL) {
1974 /* Response filled in by find_control */
1975 return;
1976 }
1977
1978 if (!ast_strlen_zero(args->caller)) {
1979 caller = ast_channel_get_by_name(args->caller);
1980 }
1981
1982 callee = ast_channel_get_by_name(args->channel_id);
1983 if (!callee) {
1984 ast_ari_response_error(response, 404, "Not Found",
1985 "Callee not found");
1986 return;
1987 }
1988
1989 if (ast_channel_state(callee) != AST_STATE_DOWN
1990 && ast_channel_state(callee) != AST_STATE_RESERVED) {
1991 ast_ari_response_error(response, 409, "Conflict",
1992 "Channel is not in the 'Down' state");
1993 return;
1994 }
1995
1996 /* XXX This is straight up copied from main/dial.c. It's probably good
1997 * to separate this to some common method.
1998 */
1999 if (caller) {
2000 ast_channel_lock_both(caller, callee);
2001 } else {
2002 ast_channel_lock(callee);
2003 }
2004
2005 dialstring = restore_dialstring(callee);
2006 if (!dialstring) {
2007 ast_channel_unlock(callee);
2008 if (caller) {
2009 ast_channel_unlock(caller);
2010 }
2011 ast_ari_response_error(response, 409, "Conflict",
2012 "Dialing a channel not created by ARI");
2013 return;
2014 }
2015 /* Make a copy of the dialstring just in case some jerk tries to hang up the
2016 * channel before we can actually dial
2017 */
2018 dialstring = ast_strdupa(dialstring);
2019
2021 if (caller) {
2022 ast_channel_inherit_variables(caller, callee);
2023 ast_channel_datastore_inherit(caller, callee);
2025
2026 /* Copy over callerid information */
2028
2030
2032
2033 ast_channel_language_set(callee, ast_channel_language(caller));
2036 ast_channel_musicclass_set(callee, ast_channel_musicclass(caller));
2037
2040 ast_channel_unlock(caller);
2041 }
2042
2044 ast_channel_unlock(callee);
2045
2046 if (stasis_app_control_dial(control, dialstring, args->timeout)) {
2048 return;
2049 }
2050
2052}
@ AST_CHANNEL_REQUESTOR_BRIDGE_PEER
Definition: channel.h:1525
const char * ast_channel_musicclass(const struct ast_channel *chan)
struct ast_party_redirecting * ast_channel_redirecting(struct ast_channel *chan)
unsigned short ast_channel_transfercapability(const struct ast_channel *chan)
#define ast_channel_lock_both(chan1, chan2)
Lock two channels.
Definition: channel.h:2979
int ast_channel_datastore_inherit(struct ast_channel *from, struct ast_channel *to)
Inherit datastores from a parent to a child.
Definition: channel.c:2338
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:6402
ast_channel_adsicpe
Definition: channel.h:888
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:6744
struct ast_party_dialed * ast_channel_dialed(struct ast_channel *chan)
const char * ast_channel_language(const 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:8307
struct ast_party_caller * ast_channel_caller(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:2103
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:1711
int transit_network_select
Transit Network Select.
Definition: channel.h:399

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. The combination of transport and encapsulation will select one of chan_rtp(udp/rtp), chan_audiosocket(tcp/audiosocket) or chan_websocket(websocket/none) channel drivers.

Parameters
headersHTTP headers
argsSwagger parameters
[out]responseHTTP response

Definition at line 2258 of file resource_channels.c.

2260{
2261 RAII_VAR(struct ast_variable *, variables, NULL, ast_variables_destroy);
2262 char *external_host;
2263 char *host = NULL;
2264 char *port = NULL;
2265
2266 ast_assert(response != NULL);
2267
2268 /* Parse any query parameters out of the body parameter */
2269 if (args->variables) {
2270 struct ast_json *json_variables;
2271
2273 json_variables = ast_json_object_get(args->variables, "variables");
2274 if (json_variables
2275 && json_to_ast_variables(response, json_variables, &variables)) {
2276 return;
2277 }
2278 }
2279
2280 if (ast_strlen_zero(args->app)) {
2281 ast_ari_response_error(response, 400, "Bad Request", "app cannot be empty");
2282 return;
2283 }
2284
2285 if (ast_strlen_zero(args->transport)) {
2286 args->transport = "udp";
2287 }
2288
2289 if (ast_strlen_zero(args->encapsulation)) {
2290 args->encapsulation = "rtp";
2291 }
2292 if (ast_strings_equal(args->transport, "websocket")) {
2293 if (!ast_strings_equal(args->encapsulation, "none")) {
2294 ast_ari_response_error(response, 400, "Bad Request", "encapsulation must be 'none' for websocket transport");
2295 return;
2296 }
2297 }
2298
2299 if (ast_strings_equal(args->encapsulation, "rtp")) {
2300 if (!ast_strings_equal(args->transport, "udp")) {
2301 ast_ari_response_error(response, 400, "Bad Request", "transport must be 'udp' for rtp encapsulation");
2302 return;
2303 }
2304 }
2305
2306 if (ast_strings_equal(args->encapsulation, "audiosocket")) {
2307 if (!ast_strings_equal(args->transport, "tcp")) {
2308 ast_ari_response_error(response, 400, "Bad Request", "transport must be 'tcp' for audiosocket encapsulation");
2309 return;
2310 }
2311 }
2312
2313 if (ast_strlen_zero(args->connection_type)) {
2314 args->connection_type = "client";
2315 }
2316 if (!ast_strings_equal(args->transport, "websocket")) {
2317 if (ast_strings_equal(args->connection_type, "server")) {
2318 ast_ari_response_error(response, 400, "Bad Request", "'server' connection_type can only be used with the websocket transport");
2319 return;
2320 }
2321 }
2322
2323 if (ast_strlen_zero(args->external_host)) {
2324 if (ast_strings_equal(args->connection_type, "client")) {
2325 ast_ari_response_error(response, 400, "Bad Request", "external_host is required for all but websocket server connections");
2326 return;
2327 } else {
2328 /* server is only valid for websocket, enforced above */
2329 args->external_host = "INCOMING";
2330 }
2331 }
2332
2333 if (ast_strings_equal(args->transport, "websocket")) {
2334 if (ast_strings_equal(args->connection_type, "client")) {
2335 struct ast_websocket_client *ws_client =
2337 ao2_cleanup(ws_client);
2338 if (!ws_client) {
2339 ast_ari_response_error(response, 400, "Bad Request", "external_host must be a valid websocket_client connection id.");
2340 return;
2341 }
2342 }
2343 } else {
2344 external_host = ast_strdupa(args->external_host);
2345 if (!ast_sockaddr_split_hostport(external_host, &host, &port, PARSE_PORT_REQUIRE)) {
2346 ast_ari_response_error(response, 400, "Bad Request", "external_host must be <host>:<port> for all transports other than websocket");
2347 return;
2348 }
2349 }
2350
2351 if (ast_strlen_zero(args->format)) {
2352 ast_ari_response_error(response, 400, "Bad Request", "format cannot be empty");
2353 return;
2354 }
2355
2356 if (ast_strlen_zero(args->direction)) {
2357 args->direction = "both";
2358 }
2359
2360 if (strcasecmp(args->encapsulation, "rtp") == 0 && strcasecmp(args->transport, "udp") == 0) {
2361 if (external_media_rtp_udp(args, variables, response)) {
2363 response, 500, "Internal Server Error",
2364 "An internal error prevented this request from being handled");
2365 }
2366 } else if (strcasecmp(args->encapsulation, "audiosocket") == 0 && strcasecmp(args->transport, "tcp") == 0) {
2367 if (external_media_audiosocket_tcp(args, variables, response)) {
2369 response, 500, "Internal Server Error",
2370 "An internal error prevented this request from being handled");
2371 }
2372 } else if (strcasecmp(args->encapsulation, "none") == 0 && strcasecmp(args->transport, "websocket") == 0) {
2373 if (external_media_websocket(args, variables, response)) {
2375 response, 500, "Internal Server Error",
2376 "An internal error prevented this request from being handled");
2377 }
2378 } else {
2380 response, 501, "Not Implemented",
2381 "The encapsulation and/or transport is not supported");
2382 }
2383}
@ 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 int external_media_audiosocket_tcp(struct ast_ari_channels_external_media_args *args, struct ast_variable *variables, struct ast_ari_response *response)
static int external_media_websocket(struct ast_ari_channels_external_media_args *args, struct ast_variable *variables, struct ast_ari_response *response)
static int 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.
int ast_strings_equal(const char *str1, const char *str2)
Compare strings for equality checking for NULL.
Definition: strings.c:238
struct ast_websocket_client * ast_websocket_client_retrieve_by_id(const char *id)
Retrieve a websocket client object by ID.

References ao2_cleanup, 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_strings_equal(), ast_strlen_zero(), ast_variables_destroy(), ast_websocket_client_retrieve_by_id(), external_media_audiosocket_tcp(), external_media_rtp_udp(), external_media_websocket(), json_to_ast_variables(), NULL, PARSE_PORT_REQUIRE, and RAII_VAR.

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 909 of file resource_channels.c.

912{
913 struct ast_channel_snapshot *snapshot;
914
915 snapshot = ast_channel_snapshot_get_latest(args->channel_id);
916 if (!snapshot) {
918 response, 404, "Not Found",
919 "Channel not found");
920 return;
921 }
922
923 ast_ari_response_ok(response,
925 ao2_ref(snapshot, -1);
926}

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 1493 of file resource_channels.c.

1496{
1497 RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
1498 RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
1499 RAII_VAR(struct ast_str *, value, ast_str_create(32), ast_free);
1500 RAII_VAR(struct ast_channel *, channel, NULL, ast_channel_cleanup);
1501
1502 ast_assert(response != NULL);
1503
1504 if (!value) {
1506 return;
1507 }
1508
1509 if (ast_strlen_zero(args->variable)) {
1511 response, 400, "Bad Request",
1512 "Variable name is required");
1513 return;
1514 }
1515
1516 if (ast_strlen_zero(args->channel_id)) {
1518 response, 400, "Bad Request",
1519 "Channel ID is required");
1520 return;
1521 }
1522
1523 channel = ast_channel_get_by_name(args->channel_id);
1524 if (!channel) {
1526 response, 404, "Channel Not Found",
1527 "Provided channel was not found");
1528 return;
1529 }
1530
1531 /* You may be tempted to lock the channel you're about to read from. You
1532 * would be wrong. Some dialplan functions put the channel into
1533 * autoservice, which deadlocks if the channel is already locked.
1534 * ast_str_retrieve_variable() does its own locking, and the dialplan
1535 * functions need to as well. We should be fine without the lock.
1536 */
1537
1538 if (args->variable[strlen(args->variable) - 1] == ')') {
1539 if (ast_func_read2(channel, args->variable, &value, 0)) {
1541 response, 500, "Error With Function",
1542 "Unable to read provided function");
1543 return;
1544 }
1545 } else {
1546 if (!ast_str_retrieve_variable(&value, 0, channel, NULL, args->variable)) {
1548 response, 404, "Variable Not Found",
1549 "Provided variable was not found");
1550 return;
1551 }
1552 }
1553
1554 if (!(json = ast_json_pack("{s: s}", "value", S_OR(ast_str_buffer(value), "")))) {
1556 return;
1557 }
1558
1559 ast_ari_response_ok(response, ast_json_ref(json));
1560}
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:612
struct ast_json * ast_json_ref(struct ast_json *value)
Increase refcount on value.
Definition: json.c:67
int ast_func_read2(struct ast_channel *chan, const char *function, struct ast_str **str, ssize_t maxlen)
executes a read operation on a function
const char * ast_str_retrieve_variable(struct ast_str **buf, ssize_t maxlen, struct ast_channel *chan, struct varshead *headp, const char *var)
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 928 of file resource_channels.c.

931{
932 RAII_VAR(struct ast_channel *, chan, NULL, ao2_cleanup);
933 int cause;
934
935 chan = ast_channel_get_by_name(args->channel_id);
936 if (chan == NULL) {
938 response, 404, "Not Found",
939 "Channel not found");
940 return;
941 }
942
943 if (!ast_strlen_zero(args->reason) && !ast_strlen_zero(args->reason_code)) {
944 ast_ari_response_error(response, 400, "Bad Request",
945 "The reason and reason_code can't both be specified");
946 return;
947 }
948
949 if (!ast_strlen_zero(args->reason_code)) {
950 /* reason_code allows any hangup code */
951 if (sscanf(args->reason_code, "%30d", &cause) != 1) {
953 response, 400, "Invalid Reason Code",
954 "Invalid reason for hangup reason code provided");
955 return;
956 }
957 } else if (!ast_strlen_zero(args->reason)) {
958 /* reason allows only listed hangup reason */
959 cause = convert_reason_to_hangup_code(args->reason);
960 if (cause == -1) {
962 response, 400, "Invalid Reason",
963 "Invalid reason for hangup reason provided");
964 return;
965 }
966 } else {
967 /* not specified. set default hangup */
968 cause = AST_CAUSE_NORMAL;
969 }
970
971 ast_channel_hangupcause_set(chan, cause);
973
975}
#define AST_CAUSE_NORMAL
Definition: causes.h:151
@ AST_SOFTHANGUP_EXPLICIT
Definition: channel.h:1168
int ast_softhangup(struct ast_channel *chan, int cause)
Softly hangup up a channel.
Definition: channel.c:2441
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 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
552
554}
void stasis_app_control_hold(struct stasis_app_control *control)
Place the channel associated with the control on hold.
Definition: control.c:789

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 977 of file resource_channels.c.

980{
981 RAII_VAR(struct ao2_container *, snapshots, NULL, ao2_cleanup);
982 RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
983 struct ao2_iterator i;
984 void *obj;
986
987 snapshots = ast_channel_cache_all();
988
989 json = ast_json_array_create();
990 if (!json) {
992 return;
993 }
994
995 i = ao2_iterator_init(snapshots, 0);
996 while ((obj = ao2_iterator_next(&i))) {
997 struct ast_channel_snapshot *snapshot = obj;
998 int r;
999
1000 if (sanitize && sanitize->channel_snapshot
1001 && sanitize->channel_snapshot(snapshot)) {
1002 ao2_ref(snapshot, -1);
1003 continue;
1004 }
1005
1007 json, ast_channel_snapshot_to_json(snapshot, NULL));
1008 if (r != 0) {
1011 ao2_ref(snapshot, -1);
1012 return;
1013 }
1014 ao2_ref(snapshot, -1);
1015 }
1017
1018 ast_ari_response_ok(response, ast_json_ref(json));
1019}
#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:378
struct ast_json * ast_json_array_create(void)
Create a empty JSON array.
Definition: json.c:362
struct stasis_message_sanitizer * stasis_app_get_sanitizer(void)
Get the Stasis message sanitizer for app_stasis applications.
Definition: res_stasis.c:2343
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 257 of file resource_channels.c.

260{
261 RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
262
263 control = find_control(response, args->channel_id);
264 if (!control) {
265 return;
266 }
267
268 if (stasis_app_control_move(control, args->app, args->app_args)) {
269 ast_ari_response_error(response, 500, "Internal Server Error",
270 "Failed to switch Stasis applications");
271 return;
272 }
273
275}
int stasis_app_control_move(struct stasis_app_control *control, const char *app_name, const char *app_args)
Exit res_stasis and move to another Stasis application.
Definition: control.c:477

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 424 of file resource_channels.c.

427{
428 RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
429 unsigned int direction = 0;
430 enum ast_frame_type frametype = AST_FRAME_VOICE;
431
432 control = find_control(response, args->channel_id);
433 if (control == NULL) {
434 return;
435 }
436
437 if (channel_state_invalid(control, response)) {
438 return;
439 }
440
441 if (ast_strlen_zero(args->direction)) {
443 response, 400, "Bad Request",
444 "Direction is required");
445 return;
446 }
447
448 if (!strcmp(args->direction, "in")) {
450 } else if (!strcmp(args->direction, "out")) {
452 } else if (!strcmp(args->direction, "both")) {
454 } else {
456 response, 400, "Bad Request",
457 "Invalid direction specified");
458 return;
459 }
460
461 stasis_app_control_mute(control, direction, frametype);
462
464}
#define AST_MUTE_DIRECTION_READ
Definition: channel.h:4790
#define AST_MUTE_DIRECTION_WRITE
Definition: channel.h:4791
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:672

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 1454 of file resource_channels.c.

1457{
1458 struct ast_variable *variables = NULL;
1459 struct ast_channel *chan;
1460
1461 /* Parse any query parameters out of the body parameter */
1462 if (args->variables) {
1463 struct ast_json *json_variables;
1464
1466 json_variables = ast_json_object_get(args->variables, "variables");
1467 if (json_variables
1468 && json_to_ast_variables(response, json_variables, &variables)) {
1469 return;
1470 }
1471 }
1472
1474 args->endpoint,
1475 args->extension,
1476 args->context,
1477 args->priority,
1478 args->label,
1479 args->app,
1480 args->app_args,
1481 args->caller_id,
1482 args->timeout,
1483 variables,
1484 args->channel_id,
1485 args->other_channel_id,
1486 args->originator,
1487 args->formats,
1488 response);
1489 ast_channel_cleanup(chan);
1490 ast_variables_destroy(variables);
1491}
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 1415 of file resource_channels.c.

1418{
1419 struct ast_variable *variables = NULL;
1420 struct ast_channel *chan;
1421
1422 /* Parse any query parameters out of the body parameter */
1423 if (args->variables) {
1424 struct ast_json *json_variables;
1425
1427 json_variables = ast_json_object_get(args->variables, "variables");
1428 if (json_variables
1429 && json_to_ast_variables(response, json_variables, &variables)) {
1430 return;
1431 }
1432 }
1433
1435 args->endpoint,
1436 args->extension,
1437 args->context,
1438 args->priority,
1439 args->label,
1440 args->app,
1441 args->app_args,
1442 args->caller_id,
1443 args->timeout,
1444 variables,
1445 args->channel_id,
1446 args->other_channel_id,
1447 args->originator,
1448 args->formats,
1449 response);
1450 ast_channel_cleanup(chan);
1451 ast_variables_destroy(variables);
1452}
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 739 of file resource_channels.c.

742{
744 args->channel_id,
745 args->media,
746 args->media_count,
747 args->lang,
748 args->offsetms,
749 args->skipms,
750 args->playback_id,
751 response);
752}
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 754 of file resource_channels.c.

757{
759 args->channel_id,
760 args->media,
761 args->media_count,
762 args->lang,
763 args->offsetms,
764 args->skipms,
765 args->playback_id,
766 response);
767}

References args, and ari_channels_handle_play().

Referenced by ast_ari_channels_play_with_id_cb().

◆ ast_ari_channels_progress()

void ast_ari_channels_progress ( struct ast_variable headers,
struct ast_ari_channels_progress_args args,
struct ast_ari_response response 
)

Indicate progress on a channel.

Parameters
headersHTTP headers
argsSwagger parameters
[out]responseHTTP response

Definition at line 404 of file resource_channels.c.

407{
408 RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
409
410 control = find_control(response, args->channel_id);
411 if (control == NULL) {
412 return;
413 }
414
415 if (channel_state_invalid(control, response)) {
416 return;
417 }
418
420
422}
int stasis_app_control_progress(struct stasis_app_control *control)
Indicate progress to the channel associated with this control.
Definition: control.c:648

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

Referenced by ast_ari_channels_progress_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 769 of file resource_channels.c.

772{
773 RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
774 RAII_VAR(struct stasis_app_recording *, recording, NULL, ao2_cleanup);
775 RAII_VAR(char *, recording_url, NULL, ast_free);
776 struct ast_json *json;
779 RAII_VAR(char *, uri_encoded_name, NULL, ast_free);
780 size_t uri_name_maxlen;
781
782 ast_assert(response != NULL);
783
784 if (args->max_duration_seconds < 0) {
786 response, 400, "Bad Request",
787 "max_duration_seconds cannot be negative");
788 return;
789 }
790
791 if (args->max_silence_seconds < 0) {
793 response, 400, "Bad Request",
794 "max_silence_seconds cannot be negative");
795 return;
796 }
797
798 control = find_control(response, args->channel_id);
799 if (control == NULL) {
800 /* Response filled in by find_control */
801 return;
802 }
803
805 if (options == NULL) {
807 response, 500, "Internal Server Error",
808 "Out of memory");
809 }
810 ast_string_field_build(options, target, "channel:%s", args->channel_id);
811 options->max_silence_seconds = args->max_silence_seconds;
812 options->max_duration_seconds = args->max_duration_seconds;
813 options->terminate_on =
815 options->if_exists =
817 options->beep = args->beep;
818
819 if (options->terminate_on == STASIS_APP_RECORDING_TERMINATE_INVALID) {
821 response, 400, "Bad Request",
822 "terminateOn invalid");
823 return;
824 }
825
826 if (options->if_exists == AST_RECORD_IF_EXISTS_ERROR) {
828 response, 400, "Bad Request",
829 "ifExists invalid");
830 return;
831 }
832
833 if (!ast_get_format_for_file_ext(options->format)) {
835 response, 422, "Unprocessable Entity",
836 "specified format is unknown on this system");
837 return;
838 }
839
840 recording = stasis_app_control_record(control, options);
841 if (recording == NULL) {
842 switch(errno) {
843 case EINVAL:
844 /* While the arguments are invalid, we should have
845 * caught them prior to calling record.
846 */
848 response, 500, "Internal Server Error",
849 "Error parsing request");
850 break;
851 case EEXIST:
852 ast_ari_response_error(response, 409, "Conflict",
853 "Recording '%s' already exists and can not be overwritten",
854 args->name);
855 break;
856 case ENOMEM:
858 response, 500, "Internal Server Error",
859 "Out of memory");
860 break;
861 case EPERM:
863 response, 400, "Bad Request",
864 "Recording name invalid");
865 break;
866 default:
868 "Unrecognized recording error: %s\n",
869 strerror(errno));
871 response, 500, "Internal Server Error",
872 "Internal Server Error");
873 break;
874 }
875 return;
876 }
877
878 uri_name_maxlen = strlen(args->name) * 3;
879 uri_encoded_name = ast_malloc(uri_name_maxlen);
880 if (!uri_encoded_name) {
882 response, 500, "Internal Server Error",
883 "Out of memory");
884 return;
885 }
886 ast_uri_encode(args->name, uri_encoded_name, uri_name_maxlen,
888
889 if (ast_asprintf(&recording_url, "/recordings/live/%s",
890 uri_encoded_name) == -1) {
891 recording_url = NULL;
893 response, 500, "Internal Server Error",
894 "Out of memory");
895 return;
896 }
897
898 json = stasis_app_recording_to_json(recording);
899 if (!json) {
901 response, 500, "Internal Server Error",
902 "Out of memory");
903 return;
904 }
905
906 ast_ari_response_created(response, recording_url, json);
907}
#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:2040
@ 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.
struct ast_json * stasis_app_recording_to_json(const struct stasis_app_recording *recording)
Construct a JSON model of a recording.
struct stasis_app_recording * stasis_app_control_record(struct stasis_app_control *control, struct stasis_app_recording_options *options)
Record media from a channel.
enum ast_record_if_exists stasis_app_recording_if_exists_parse(const char *str)
Parse a string into the if_exists enum.
#define STASIS_APP_RECORDING_TERMINATE_INVALID
char stasis_app_recording_termination_parse(const char *str)
Parse a string into the recording termination enum.
#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: utils.c:723
const struct ast_flags ast_uri_http
Definition: 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 277 of file resource_channels.c.

280{
281 RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
282 RAII_VAR(struct ast_channel_snapshot *, chan_snapshot, NULL, ao2_cleanup);
283 char *tech;
284 char *resource;
285 int tech_len;
286
287 control = find_control(response, args->channel_id);
288 if (!control) {
289 return;
290 }
291
292 if (channel_state_invalid(control, response)) {
293 return;
294 }
295
296 if (ast_strlen_zero(args->endpoint)) {
297 ast_ari_response_error(response, 400, "Not Found",
298 "Required parameter 'endpoint' not provided.");
299 return;
300 }
301
302 tech = ast_strdupa(args->endpoint);
303 if (!(resource = strchr(tech, '/')) || !(tech_len = resource - tech)) {
304 ast_ari_response_error(response, 422, "Unprocessable Entity",
305 "Endpoint parameter '%s' does not contain tech/resource", args->endpoint);
306 return;
307 }
308
309 *resource++ = '\0';
310 if (ast_strlen_zero(resource)) {
311 ast_ari_response_error(response, 422, "Unprocessable Entity",
312 "No resource provided in endpoint parameter '%s'", args->endpoint);
313 return;
314 }
315
316 chan_snapshot = ast_channel_snapshot_get_latest(args->channel_id);
317 if (!chan_snapshot) {
318 ast_ari_response_error(response, 500, "Internal Server Error",
319 "Unable to find channel snapshot for '%s'", args->channel_id);
320 return;
321 }
322
323 if (strncasecmp(chan_snapshot->base->type, tech, tech_len)) {
324 ast_ari_response_error(response, 422, "Unprocessable Entity",
325 "Endpoint technology '%s' does not match channel technology '%s'",
326 tech, chan_snapshot->base->type);
327 return;
328 }
329
330 if (stasis_app_control_redirect(control, resource)) {
331 ast_ari_response_error(response, 500, "Internal Server Error",
332 "Failed to redirect channel");
333 return;
334 }
335
337}
int stasis_app_control_redirect(struct stasis_app_control *control, const char *endpoint)
Redirect a channel in res_stasis to a particular endpoint.
Definition: control.c:526

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 364 of file resource_channels.c.

367{
368 RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
369
370 control = find_control(response, args->channel_id);
371 if (control == NULL) {
372 return;
373 }
374
375 if (channel_state_invalid(control, response)) {
376 return;
377 }
378
380
382}
int stasis_app_control_ring(struct stasis_app_control *control)
Indicate ringing to the channel associated with this control.
Definition: control.c:618

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 384 of file resource_channels.c.

387{
388 RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
389
390 control = find_control(response, args->channel_id);
391 if (control == NULL) {
392 return;
393 }
394
395 if (channel_state_invalid(control, response)) {
396 return;
397 }
398
400
402}
int stasis_app_control_ring_stop(struct stasis_app_control *control)
Stop locally generated ringing on the channel associated with this control.
Definition: control.c:633

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 2054 of file resource_channels.c.

2057{
2058 RAII_VAR(struct ast_channel *, chan, NULL, ast_channel_cleanup);
2059 RAII_VAR(struct ast_rtp_instance *, rtp, NULL, ao2_cleanup);
2060 struct ast_json *j_res;
2061 const struct ast_channel_tech *tech;
2062 struct ast_rtp_glue *glue;
2063
2064 chan = ast_channel_get_by_name(args->channel_id);
2065 if (!chan) {
2066 ast_ari_response_error(response, 404, "Not Found",
2067 "Channel not found");
2068 return;
2069 }
2070
2071 ast_channel_lock(chan);
2072 tech = ast_channel_tech(chan);
2073 if (!tech) {
2074 ast_channel_unlock(chan);
2075 ast_ari_response_error(response, 404, "Not Found",
2076 "Channel's tech not found");
2077 return;
2078 }
2079
2080 glue = ast_rtp_instance_get_glue(tech->type);
2081 if (!glue) {
2082 ast_channel_unlock(chan);
2083 ast_ari_response_error(response, 403, "Forbidden",
2084 "Unsupported channel type");
2085 return;
2086 }
2087
2088 glue->get_rtp_info(chan, &rtp);
2089 if (!rtp) {
2090 ast_channel_unlock(chan);
2091 ast_ari_response_error(response, 404, "Not Found",
2092 "RTP info not found");
2093 return;
2094 }
2095
2097 if (!j_res) {
2098 ast_channel_unlock(chan);
2099 ast_ari_response_error(response, 404, "Not Found",
2100 "Statistics not found");
2101 return;
2102 }
2103
2104 ast_channel_unlock(chan);
2105 ast_ari_response_ok(response, j_res);
2106
2107 return;
2108}
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:4281
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:2398
Structure to describe a channel "technology", ie a channel driver See for examples:
Definition: channel.h:648
const char *const type
Definition: channel.h:649
enum ast_rtp_glue_result(* get_rtp_info)(struct ast_channel *chan, struct ast_rtp_instance **instance)
Callback for retrieving the RTP instance carrying audio.
Definition: rtp_engine.h:787

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 508 of file resource_channels.c.

511{
512 RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
513
514 control = find_control(response, args->channel_id);
515 if (control == NULL) {
516 return;
517 }
518
519 if (channel_state_invalid(control, response)) {
520 return;
521 }
522
523 if (ast_strlen_zero(args->dtmf)) {
525 response, 400, "Bad Request",
526 "DTMF is required");
527 return;
528 }
529
530 stasis_app_control_dtmf(control, args->dtmf, args->before, args->between, args->duration, args->after);
531
533}
int stasis_app_control_dtmf(struct stasis_app_control *control, const char *dtmf, int before, int between, unsigned int duration, int after)
Send DTMF to the channel associated with this control.
Definition: control.c:591

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 1562 of file resource_channels.c.

1565{
1566 RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
1567
1568 ast_assert(response != NULL);
1569
1570 if (ast_strlen_zero(args->variable)) {
1572 response, 400, "Bad Request",
1573 "Variable name is required");
1574 return;
1575 }
1576
1577 control = find_control(response, args->channel_id);
1578 if (control == NULL) {
1579 /* response filled in by find_control */
1580 return;
1581 }
1582
1583 if (stasis_app_control_set_channel_var(control, args->variable, args->value)) {
1585 response, 400, "Bad Request",
1586 "Failed to execute function");
1587 return;
1588 }
1589
1591}
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:752

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 1672 of file resource_channels.c.

1675{
1677 args->channel_id,
1678 args->spy,
1679 args->whisper,
1680 args->app,
1681 args->app_args,
1682 args->snoop_id,
1683 response);
1684}
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 1686 of file resource_channels.c.

1689{
1691 args->channel_id,
1692 args->spy,
1693 args->whisper,
1694 args->app,
1695 args->app_args,
1696 args->snoop_id,
1697 response);
1698}

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 577 of file resource_channels.c.

580{
581 RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
582
583 control = find_control(response, args->channel_id);
584 if (control == NULL) {
585 /* Response filled in by find_control */
586 return;
587 }
588
589 if (channel_state_invalid(control, response)) {
590 return;
591 }
592
593 stasis_app_control_moh_start(control, args->moh_class);
595}
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:821

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 617 of file resource_channels.c.

620{
621 RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
622
623 control = find_control(response, args->channel_id);
624 if (control == NULL) {
625 /* Response filled in by find_control */
626 return;
627 }
628
629 if (channel_state_invalid(control, response)) {
630 return;
631 }
632
635}
void stasis_app_control_silence_start(struct stasis_app_control *control)
Start playing silence to a channel.
Definition: control.c:873

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 597 of file resource_channels.c.

600{
601 RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
602
603 control = find_control(response, args->channel_id);
604 if (control == NULL) {
605 /* Response filled in by find_control */
606 return;
607 }
608
609 if (channel_state_invalid(control, response)) {
610 return;
611 }
612
615}
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:839

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 637 of file resource_channels.c.

640{
641 RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
642
643 control = find_control(response, args->channel_id);
644 if (control == NULL) {
645 /* Response filled in by find_control */
646 return;
647 }
648
649 if (channel_state_invalid(control, response)) {
650 return;
651 }
652
655}
void stasis_app_control_silence_stop(struct stasis_app_control *control)
Stop playing silence to a channel.
Definition: control.c:896

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_transfer_progress()

void ast_ari_channels_transfer_progress ( struct ast_variable headers,
struct ast_ari_channels_transfer_progress_args args,
struct ast_ari_response response 
)

Inform the channel about the progress of the attended/blind transfer.

Parameters
headersHTTP headers
argsSwagger parameters
[out]responseHTTP response

Definition at line 2385 of file resource_channels.c.

2386{
2388 RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
2389 RAII_VAR(struct ast_channel *, chan, NULL, ast_channel_cleanup);
2390
2391 control = find_control(response, args->channel_id);
2392 if (control == NULL) {
2393 /* Response filled in by find_control */
2394 return;
2395 }
2396
2397 chan = ast_channel_get_by_name(args->channel_id);
2398 if (!chan) {
2399 ast_ari_response_error(response, 404, "Not Found",
2400 "Callee not found");
2401 return;
2402 }
2403
2404 if (ast_strlen_zero(args->states)) {
2405 ast_ari_response_error(response, 400, "Bad Request", "states must not be empty");
2406 return;
2407 }
2408
2409 if (strcasecmp(args->states, "channel_progress") == 0) {
2411 } else if (strcasecmp(args->states, "channel_answered") == 0) {
2413 } else if (strcasecmp(args->states, "channel_unavailable") == 0) {
2415 } else if (strcasecmp(args->states, "channel_declined") == 0) {
2417 } else {
2418 ast_ari_response_error(response, 400, "Bad Request", "Invalid states value");
2419 return;
2420 }
2421
2424}
int ast_indicate_data(struct ast_channel *chan, int condition, const void *data, size_t datalen)
Indicates condition of channel, with payload.
Definition: channel.c:4621
ast_control_transfer
@ AST_TRANSFER_FAILED
@ AST_TRANSFER_UNAVAILABLE
@ AST_TRANSFER_SUCCESS
@ AST_TRANSFER_PROGRESS
@ AST_CONTROL_TRANSFER

References ao2_cleanup, args, ast_ari_response_error(), ast_ari_response_no_content(), ast_channel_cleanup, ast_channel_get_by_name(), AST_CONTROL_TRANSFER, ast_indicate_data(), ast_strlen_zero(), AST_TRANSFER_FAILED, AST_TRANSFER_PROGRESS, AST_TRANSFER_SUCCESS, AST_TRANSFER_UNAVAILABLE, find_control(), NULL, and RAII_VAR.

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

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 466 of file resource_channels.c.

469{
470 RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
471 unsigned int direction = 0;
472 enum ast_frame_type frametype = AST_FRAME_VOICE;
473
474 control = find_control(response, args->channel_id);
475 if (control == NULL) {
476 return;
477 }
478
479 if (channel_state_invalid(control, response)) {
480 return;
481 }
482
483 if (ast_strlen_zero(args->direction)) {
485 response, 400, "Bad Request",
486 "Direction is required");
487 return;
488 }
489
490 if (!strcmp(args->direction, "in")) {
492 } else if (!strcmp(args->direction, "out")) {
494 } else if (!strcmp(args->direction, "both")) {
496 } else {
498 response, 400, "Bad Request",
499 "Invalid direction specified");
500 return;
501 }
502
503 stasis_app_control_unmute(control, direction, frametype);
504
506}
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:700

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 1705 of file resource_channels.c.

1706{
1707 ast_free(chan_data->stasis_stuff);
1708 ast_hangup(chan_data->chan);
1709 ast_free(chan_data);
1710}
void ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition: channel.c:2511

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 109 of file resource_channels.c.

111{
112 struct ast_channel_snapshot *snapshot;
113
114 snapshot = stasis_app_control_get_snapshot(control);
115 if (!snapshot) {
116 ast_ari_response_error(response, 404, "Not Found", "Channel not found");
117 return -1;
118 }
119
120 /* These channel states apply only to outbound channels:
121 * - Down: Channel has been created, and nothing else has been done
122 * - Reserved: For a PRI, an underlying B-channel is reserved,
123 * but the channel is not yet dialed
124 * - Ringing: The channel has been dialed.
125 *
126 * This does not affect inbound channels. Inbound channels, when they
127 * enter the dialplan, are in the "Ring" state. If they have already
128 * been answered, then they are in the "Up" state.
129 */
130 if (snapshot->state == AST_STATE_DOWN
131 || snapshot->state == AST_STATE_RESERVED
132 || snapshot->state == AST_STATE_RINGING) {
133 ast_ari_response_error(response, 412, "Precondition Failed",
134 "Channel in invalid state");
135 ao2_ref(snapshot, -1);
136
137 return -1;
138 }
139
140 ao2_ref(snapshot, -1);
141
142 return 0;
143}
@ 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_progress(), 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 54 of file resource_channels.c.

55{
56 if (!strcmp(reason, "normal")) {
57 return AST_CAUSE_NORMAL;
58 } else if (!strcmp(reason, "busy")) {
59 return AST_CAUSE_BUSY;
60 } else if (!strcmp(reason, "congestion")) {
62 } else if (!strcmp(reason, "no_answer")) {
63 return AST_CAUSE_NOANSWER;
64 } else if (!strcmp(reason, "timeout")) {
66 } else if (!strcmp(reason, "rejected")) {
68 } else if (!strcmp(reason, "unallocated")) {
70 } else if (!strcmp(reason, "normal_unspecified")) {
72 } else if (!strcmp(reason, "number_incomplete")) {
74 } else if (!strcmp(reason, "codec_mismatch")) {
76 } else if (!strcmp(reason, "interworking")) {
78 } else if (!strcmp(reason, "failure")) {
79 return AST_CAUSE_FAILURE;
80 } else if(!strcmp(reason, "answered_elsewhere")) {
82 }
83
84 return -1;
85}
#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 int 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 2157 of file resource_channels.c.

2160{
2161 char *endpoint;
2162 struct ast_channel *chan;
2163 struct varshead *vars;
2164
2165 if (ast_strlen_zero(args->data)) {
2166 ast_ari_response_error(response, 400, "Bad Request", "data can not be empty");
2167 return 1;
2168 }
2169
2170 if (ast_asprintf(&endpoint, "AudioSocket/%s/%s",
2171 args->external_host, args->data) == -1) {
2172 return 1;
2173 }
2174
2176 endpoint,
2177 NULL,
2178 NULL,
2179 0,
2180 NULL,
2181 args->app,
2182 args->data,
2183 NULL,
2184 0,
2185 variables,
2186 args->channel_id,
2187 NULL,
2188 NULL,
2189 args->format,
2190 response);
2191
2192 ast_free(endpoint);
2193
2194 if (!chan) {
2195 return 1;
2196 }
2197
2198 ast_channel_lock(chan);
2199 vars = ast_channel_varshead(chan);
2200 if (vars && !AST_LIST_EMPTY(vars)) {
2201 ast_json_object_set(response->message, "channelvars", ast_json_channel_vars(vars));
2202 }
2203 ast_channel_unlock(chan);
2204 ast_channel_unref(chan);
2205 return 0;
2206}
struct varshead * ast_channel_varshead(struct ast_channel *chan)
int ast_json_object_set(struct ast_json *object, const char *key, struct ast_json *value)
Set a field in a JSON object.
Definition: json.c:414
struct ast_json * ast_json_channel_vars(struct varshead *channelvars)
Construct a JSON object from a ast_var_t list.
Definition: json.c:941
#define AST_LIST_EMPTY(head)
Checks whether the specified list contains any entries.
Definition: linkedlists.h:450
struct ast_json * message
Definition: ari.h:103

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

Referenced by ast_ari_channels_external_media().

◆ external_media_rtp_udp()

static int 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 2110 of file resource_channels.c.

2113{
2114 char *endpoint;
2115 struct ast_channel *chan;
2116 struct varshead *vars;
2117
2118 if (ast_asprintf(&endpoint, "UnicastRTP/%s/c(%s)",
2119 args->external_host,
2120 args->format) == -1) {
2121 return 1;
2122 }
2123
2125 endpoint,
2126 NULL,
2127 NULL,
2128 0,
2129 NULL,
2130 args->app,
2131 args->data,
2132 NULL,
2133 0,
2134 variables,
2135 args->channel_id,
2136 NULL,
2137 NULL,
2138 args->format,
2139 response);
2140
2141 ast_free(endpoint);
2142
2143 if (!chan) {
2144 return 1;
2145 }
2146
2147 ast_channel_lock(chan);
2148 vars = ast_channel_varshead(chan);
2149 if (vars && !AST_LIST_EMPTY(vars)) {
2150 ast_json_object_set(response->message, "channelvars", ast_json_channel_vars(vars));
2151 }
2152 ast_channel_unlock(chan);
2153 ast_channel_unref(chan);
2154 return 0;
2155}

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

Referenced by ast_ari_channels_external_media().

◆ external_media_websocket()

static int external_media_websocket ( struct ast_ari_channels_external_media_args args,
struct ast_variable variables,
struct ast_ari_response response 
)
static

Definition at line 2208 of file resource_channels.c.

2211{
2212 char *endpoint;
2213 struct ast_channel *chan;
2214 struct varshead *vars;
2215
2216 if (ast_asprintf(&endpoint, "WebSocket/%s/c(%s)",
2217 args->external_host,
2218 args->format) == -1) {
2219 return 1;
2220 }
2221
2223 endpoint,
2224 NULL,
2225 NULL,
2226 0,
2227 NULL,
2228 args->app,
2229 args->data,
2230 NULL,
2231 0,
2232 variables,
2233 args->channel_id,
2234 NULL,
2235 NULL,
2236 args->format,
2237 response);
2238
2239 ast_free(endpoint);
2240
2241 if (!chan) {
2242 return 1;
2243 }
2244
2245 ast_channel_lock(chan);
2246 vars = ast_channel_varshead(chan);
2247 if (vars && !AST_LIST_EMPTY(vars)) {
2248 ast_json_object_set(response->message, "channelvars", ast_json_channel_vars(vars));
2249 }
2250 ast_channel_unlock(chan);
2251 ast_channel_unref(chan);
2252 return 0;
2253}

References args, ari_channels_handle_originate_with_id(), ast_asprintf, ast_channel_lock, ast_channel_unlock, ast_channel_unref, ast_channel_varshead(), ast_free, ast_json_channel_vars(), ast_json_object_set(), AST_LIST_EMPTY, 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 153 of file resource_channels.c.

156{
157 RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
158
159 ast_assert(response != NULL);
160
161 control = stasis_app_control_find_by_channel_id(channel_id);
162 if (control == NULL) {
163 /* Distinguish between 404 and 409 errors */
164 RAII_VAR(struct ast_channel *, chan, NULL, ao2_cleanup);
165 chan = ast_channel_get_by_name(channel_id);
166 if (chan == NULL) {
167 ast_ari_response_error(response, 404, "Not Found",
168 "Channel not found");
169 return NULL;
170 }
171
172 ast_ari_response_error(response, 409, "Conflict",
173 "Channel not in Stasis application");
174 return NULL;
175 }
176
177 ao2_ref(control, +1);
178 return control;
179}
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_progress(), 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_transfer_progress(), 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 1394 of file resource_channels.c.

1395{
1397
1398 res = ast_json_to_ast_variables(json_variables, variables);
1399 switch (res) {
1401 return 0;
1403 ast_ari_response_error(response, 400, "Bad Request",
1404 "Only string values in the 'variables' object allowed");
1405 break;
1408 break;
1409 }
1410 ast_log(AST_LOG_ERROR, "Unable to convert 'variables' in JSON body to channel variables\n");
1411
1412 return -1;
1413}
ast_json_to_ast_vars_code
Definition: json.h:1109
@ AST_JSON_TO_AST_VARS_CODE_INVALID_TYPE
Conversion failed because invalid value type supplied.
Definition: json.h:1116
@ AST_JSON_TO_AST_VARS_CODE_SUCCESS
Conversion successful.
Definition: json.h:1111
@ AST_JSON_TO_AST_VARS_CODE_OOM
Conversion failed because of allocation failure. (Out Of Memory)
Definition: json.h:1118
enum ast_json_to_ast_vars_code ast_json_to_ast_variables(struct ast_json *json_variables, struct ast_variable **variables)
Convert a ast_json list of key/value pair tuples into a ast_variable list.
Definition: json.c:818

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 1787 of file resource_channels.c.

1788{
1789 struct ast_datastore *datastore;
1790
1791 datastore = ast_channel_datastore_find(chan, &dialstring_info, NULL);
1792 if (!datastore) {
1793 return NULL;
1794 }
1795
1796 return datastore->data;
1797}
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:2369
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 1753 of file resource_channels.c.

1754{
1755 struct ast_datastore *datastore;
1756
1758 if (!datastore) {
1759 return -1;
1760 }
1761
1762 datastore->data = ast_strdup(dialstring);
1763 if (!datastore->data) {
1764 ast_datastore_free(datastore);
1765 return -1;
1766 }
1767
1768 ast_channel_lock(chan);
1769 if (ast_channel_datastore_add(chan, datastore)) {
1770 ast_channel_unlock(chan);
1771 ast_datastore_free(datastore);
1772 return -1;
1773 }
1774 ast_channel_unlock(chan);
1775
1776 return 0;
1777}
#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:2355
#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 1738 of file resource_channels.c.

Referenced by restore_dialstring(), and save_dialstring().