Asterisk - The Open Source Telephony Project GIT-master-6144b6b
Loading...
Searching...
No Matches
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.
 
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, struct ast_variable *report_event_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.
 
void ast_ari_channels_answer (struct ast_variable *headers, struct ast_ari_channels_answer_args *args, struct ast_ari_response *response)
 Answer a channel.
 
void ast_ari_channels_continue_in_dialplan (struct ast_variable *headers, struct ast_ari_channels_continue_in_dialplan_args *args, struct ast_ari_response *response)
 Exit application; continue execution in the dialplan.
 
void ast_ari_channels_create (struct ast_variable *headers, struct ast_ari_channels_create_args *args, struct ast_ari_response *response)
 Create channel.
 
void ast_ari_channels_dial (struct ast_variable *headers, struct ast_ari_channels_dial_args *args, struct ast_ari_response *response)
 Dial a created channel.
 
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.
 
void ast_ari_channels_get (struct ast_variable *headers, struct ast_ari_channels_get_args *args, struct ast_ari_response *response)
 Channel details.
 
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.
 
void ast_ari_channels_get_channel_vars (struct ast_variable *headers, struct ast_ari_channels_get_channel_vars_args *args, struct ast_ari_response *response)
 Get the value of multiple channel variables or functions.
 
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.
 
void ast_ari_channels_hold (struct ast_variable *headers, struct ast_ari_channels_hold_args *args, struct ast_ari_response *response)
 Hold a channel.
 
void ast_ari_channels_list (struct ast_variable *headers, struct ast_ari_channels_list_args *args, struct ast_ari_response *response)
 List all active channels in Asterisk.
 
void ast_ari_channels_move (struct ast_variable *headers, struct ast_ari_channels_move_args *args, struct ast_ari_response *response)
 Move the channel from one Stasis application to another.
 
void ast_ari_channels_mute (struct ast_variable *headers, struct ast_ari_channels_mute_args *args, struct ast_ari_response *response)
 Mute a channel.
 
void ast_ari_channels_originate (struct ast_variable *headers, struct ast_ari_channels_originate_args *args, struct ast_ari_response *response)
 Create a new channel (originate).
 
void ast_ari_channels_originate_with_id (struct ast_variable *headers, struct ast_ari_channels_originate_with_id_args *args, struct ast_ari_response *response)
 Create a new channel (originate with id).
 
void ast_ari_channels_play (struct ast_variable *headers, struct ast_ari_channels_play_args *args, struct ast_ari_response *response)
 Start playback of media.
 
void ast_ari_channels_play_with_id (struct ast_variable *headers, struct ast_ari_channels_play_with_id_args *args, struct ast_ari_response *response)
 Start playback of media and specify the playbackId.
 
void ast_ari_channels_progress (struct ast_variable *headers, struct ast_ari_channels_progress_args *args, struct ast_ari_response *response)
 Indicate progress on a channel.
 
void ast_ari_channels_record (struct ast_variable *headers, struct ast_ari_channels_record_args *args, struct ast_ari_response *response)
 Start a recording.
 
void ast_ari_channels_redirect (struct ast_variable *headers, struct ast_ari_channels_redirect_args *args, struct ast_ari_response *response)
 Redirect the channel to a different location.
 
void ast_ari_channels_ring (struct ast_variable *headers, struct ast_ari_channels_ring_args *args, struct ast_ari_response *response)
 Indicate ringing to a channel.
 
void ast_ari_channels_ring_stop (struct ast_variable *headers, struct ast_ari_channels_ring_stop_args *args, struct ast_ari_response *response)
 Stop ringing indication on a channel if locally generated.
 
void ast_ari_channels_rtpstatistics (struct ast_variable *headers, struct ast_ari_channels_rtpstatistics_args *args, struct ast_ari_response *response)
 RTP stats on a channel.
 
void ast_ari_channels_send_dtmf (struct ast_variable *headers, struct ast_ari_channels_send_dtmf_args *args, struct ast_ari_response *response)
 Send provided DTMF to a given channel.
 
void ast_ari_channels_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.
 
void ast_ari_channels_set_channel_vars (struct ast_variable *headers, struct ast_ari_channels_set_channel_vars_args *args, struct ast_ari_response *response)
 Set the values of multiple channel variables or functions.
 
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.
 
void ast_ari_channels_snoop_channel_with_id (struct ast_variable *headers, struct ast_ari_channels_snoop_channel_with_id_args *args, struct ast_ari_response *response)
 Start snooping.
 
void ast_ari_channels_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.
 
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.
 
void ast_ari_channels_stop_moh (struct ast_variable *headers, struct ast_ari_channels_stop_moh_args *args, struct ast_ari_response *response)
 Stop playing music on hold to a channel.
 
void ast_ari_channels_stop_silence (struct ast_variable *headers, struct ast_ari_channels_stop_silence_args *args, struct ast_ari_response *response)
 Stop playing silence to a channel.
 
void ast_ari_channels_transfer_progress (struct ast_variable *headers, struct ast_ari_channels_transfer_progress_args *args, struct ast_ari_response *response)
 Inform the channel about the progress of the attended/blind transfer.
 
void ast_ari_channels_unhold (struct ast_variable *headers, struct ast_ari_channels_unhold_args *args, struct ast_ari_response *response)
 Remove a channel from hold.
 
void ast_ari_channels_unmute (struct ast_variable *headers, struct ast_ari_channels_unmute_args *args, struct ast_ari_response *response)
 Unmute a channel.
 
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.
 
static int convert_reason_to_hangup_code (const char *reason)
 Return the corresponded hangup code of the given reason.
 
static int external_media_audiosocket_tcp (struct ast_ari_channels_external_media_args *args, struct ast_variable *variables, struct ast_variable *report_event_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_variable *report_event_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_variable *report_event_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.
 
static int json_to_ast_variables (struct ast_ari_response *response, struct ast_json *json_variables, struct ast_variable **variables, struct ast_variable **report_event_variables)
 
static char * restore_dialstring (struct ast_channel *chan)
 Retrieve the dialstring from the channel datastore.
 
static int save_dialstring (struct ast_channel *chan, const char *dialstring)
 Save dialstring onto a channel datastore.
 

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

2010{
2011 struct ari_channel_thread_data *chan_data = data;
2012 struct ast_app *stasis_app;
2013
2014 stasis_app = pbx_findapp("Stasis");
2015 if (!stasis_app) {
2016 ast_log(LOG_ERROR, "Stasis dialplan application is not registered");
2017 chan_data_destroy(chan_data);
2018 return NULL;
2019 }
2020
2021 pbx_exec(chan_data->chan, stasis_app, ast_str_buffer(chan_data->stasis_stuff));
2022
2023 chan_data_destroy(chan_data);
2024
2025 return NULL;
2026}
#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:483
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 *attribute_pure ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition strings.h:761
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,
struct ast_variable report_event_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 1115 of file resource_channels.c.

1131{
1132 char *dialtech;
1133 char *dialdevice = NULL;
1134 struct ast_dial *dial;
1135 char *caller_id = NULL;
1136 char *cid_num = NULL;
1137 char *cid_name = NULL;
1138 char *stuff;
1139 struct ast_channel *other = NULL;
1140 struct ast_channel *chan = NULL;
1142 struct ast_assigned_ids assignedids = {
1143 .uniqueid = args_channel_id,
1144 .uniqueid2 = args_other_channel_id,
1145 };
1146 struct ari_origination *origination;
1147 pthread_t thread;
1148 struct ast_format_cap *format_cap = NULL;
1149
1150 if ((assignedids.uniqueid && AST_MAX_PUBLIC_UNIQUEID < strlen(assignedids.uniqueid))
1151 || (assignedids.uniqueid2 && AST_MAX_PUBLIC_UNIQUEID < strlen(assignedids.uniqueid2))) {
1152 ast_ari_response_error(response, 400, "Bad Request",
1153 "Uniqueid length exceeds maximum of %d", AST_MAX_PUBLIC_UNIQUEID);
1154 return NULL;
1155 }
1156
1157 if (ast_strlen_zero(args_endpoint)) {
1158 ast_ari_response_error(response, 400, "Bad Request",
1159 "Endpoint must be specified");
1160 return NULL;
1161 }
1162
1163 if (!ast_strlen_zero(args_originator) && !ast_strlen_zero(args_formats)) {
1164 ast_ari_response_error(response, 400, "Bad Request",
1165 "Originator and formats can't both be specified");
1166 return NULL;
1167 }
1168
1169 dialtech = ast_strdupa(args_endpoint);
1170 if ((stuff = strchr(dialtech, '/'))) {
1171 *stuff++ = '\0';
1172 dialdevice = stuff;
1173 }
1174
1175 if (ast_strlen_zero(dialtech) || ast_strlen_zero(dialdevice)) {
1176 ast_ari_response_error(response, 400, "Bad Request",
1177 "Invalid endpoint specified");
1178 return NULL;
1179 }
1180
1181 if (!ast_strlen_zero(args_app)) {
1182 RAII_VAR(struct ast_str *, appdata, ast_str_create(64), ast_free);
1183
1184 if (!appdata) {
1186 return NULL;
1187 }
1188
1189 ast_str_set(&appdata, 0, "%s", args_app);
1190 if (!ast_strlen_zero(args_app_args)) {
1191 ast_str_append(&appdata, 0, ",%s", args_app_args);
1192 }
1193
1194 origination = ast_calloc(1, sizeof(*origination) + ast_str_size(appdata) + 1);
1195 if (!origination) {
1197 return NULL;
1198 }
1199
1200 strcpy(origination->appdata, ast_str_buffer(appdata));
1201 } else if (!ast_strlen_zero(args_extension)) {
1202 origination = ast_calloc(1, sizeof(*origination) + 1);
1203 if (!origination) {
1205 return NULL;
1206 }
1207
1208 ast_copy_string(origination->context, S_OR(args_context, "default"), sizeof(origination->context));
1209 ast_copy_string(origination->exten, args_extension, sizeof(origination->exten));
1210
1211 if (!ast_strlen_zero(args_label)) {
1212 /* A label was provided in the request, use that */
1213 int ipri = 1;
1214 if (sscanf(args_label, "%30d", &ipri) != 1) {
1215 ipri = ast_findlabel_extension(chan, origination->context, origination->exten, args_label, args_caller_id);
1216
1217 if (ipri == -1) {
1218 ast_log(AST_LOG_ERROR, "Requested label: %s can not be found in context: %s\n", args_label, args_context);
1219 ast_ari_response_error(response, 404, "Not Found", "Requested label can not be found");
1220 return NULL;
1221 }
1222 } else {
1223 ast_debug(3, "Numeric value provided for label, jumping to that priority\n");
1224 }
1225
1226 if (ipri == 0) {
1227 ast_log(AST_LOG_ERROR, "Invalid priority label '%s' specified for extension %s in context: %s\n",
1228 args_label, args_extension, args_context);
1229 ast_ari_response_error(response, 400, "Bad Request", "Requested priority is illegal");
1230 return NULL;
1231 }
1232
1233 /* Our priority was provided by a label */
1234 origination->priority = ipri;
1235 } else {
1236 /* No label provided, use provided priority */
1237 origination->priority = args_priority ? args_priority : 1;
1238 }
1239
1240 origination->appdata[0] = '\0';
1241 } else {
1242 ast_ari_response_error(response, 400, "Bad Request",
1243 "Application or extension must be specified");
1244 return NULL;
1245 }
1246
1247 dial = ast_dial_create();
1248 if (!dial) {
1250 ast_free(origination);
1251 return NULL;
1252 }
1253 ast_dial_set_user_data(dial, origination);
1254
1255 if (ast_dial_append(dial, dialtech, dialdevice, &assignedids)) {
1257 ast_dial_destroy(dial);
1258 ast_free(origination);
1259 return NULL;
1260 }
1261
1262 if (args_timeout > 0) {
1263 ast_dial_set_global_timeout(dial, args_timeout * 1000);
1264 } else if (args_timeout == -1) {
1266 } else {
1267 ast_dial_set_global_timeout(dial, 30000);
1268 }
1269
1270 if (!ast_strlen_zero(args_caller_id)) {
1271 caller_id = ast_strdupa(args_caller_id);
1272 ast_callerid_parse(caller_id, &cid_name, &cid_num);
1273
1274 if (ast_is_shrinkable_phonenumber(cid_num)) {
1275 ast_shrink_phone_number(cid_num);
1276 }
1277 }
1278
1279 if (!ast_strlen_zero(args_originator)) {
1280 other = ast_channel_get_by_name(args_originator);
1281 if (!other) {
1283 response, 400, "Bad Request",
1284 "Provided originator channel was not found");
1285 ast_dial_destroy(dial);
1286 ast_free(origination);
1287 return NULL;
1288 }
1289 }
1290
1291 if (!ast_strlen_zero(args_formats)) {
1292 char *format_name;
1293 char *formats_copy = ast_strdupa(args_formats);
1294
1297 ast_dial_destroy(dial);
1298 ast_free(origination);
1299 ast_channel_cleanup(other);
1300 return NULL;
1301 }
1302
1303 while ((format_name = ast_strip(strsep(&formats_copy, ",")))) {
1304 struct ast_format *fmt = ast_format_cache_get(format_name);
1305
1306 if (!fmt || ast_format_cap_append(format_cap, fmt, 0)) {
1307 if (!fmt) {
1309 response, 400, "Bad Request",
1310 "Provided format (%s) was not found", format_name);
1311 } else {
1313 }
1314 ast_dial_destroy(dial);
1315 ast_free(origination);
1316 ast_channel_cleanup(other);
1317 ao2_ref(format_cap, -1);
1318 ao2_cleanup(fmt);
1319 return NULL;
1320 }
1321 ao2_ref(fmt, -1);
1322 }
1323 }
1324
1325 if (ast_dial_prerun(dial, other, format_cap)) {
1327 ast_ari_response_error(response, 409, "Conflict",
1328 "Channel with given unique ID already exists");
1329 } else {
1331 }
1332 ast_dial_destroy(dial);
1333 ast_free(origination);
1334 ast_channel_cleanup(other);
1335 return NULL;
1336 }
1337
1338 ast_channel_cleanup(other);
1339 ao2_cleanup(format_cap);
1340
1341 chan = ast_dial_get_channel(dial, 0);
1342 if (!chan) {
1344 ast_dial_destroy(dial);
1345 ast_free(origination);
1346 return NULL;
1347 }
1348
1349 if (!ast_strlen_zero(cid_num) || !ast_strlen_zero(cid_name)) {
1351
1352 /*
1353 * It seems strange to set the CallerID on an outgoing call leg
1354 * to whom we are calling, but this function's callers are doing
1355 * various Originate methods. This call leg goes to the local
1356 * user. Once the called party answers, the dialplan needs to
1357 * be able to access the CallerID from the CALLERID function as
1358 * if the called party had placed this call.
1359 */
1360 ast_set_callerid(chan, cid_num, cid_name, cid_num);
1361
1363 if (!ast_strlen_zero(cid_num)) {
1364 connected.id.number.valid = 1;
1365 connected.id.number.str = (char *) cid_num;
1367 }
1368 if (!ast_strlen_zero(cid_name)) {
1369 connected.id.name.valid = 1;
1370 connected.id.name.str = (char *) cid_name;
1372 }
1374 }
1375
1376 if (variables) {
1377 ast_set_variables(chan, variables);
1378 }
1380
1381 if (!ast_strlen_zero(args_app)) {
1382 struct ast_channel *local_peer;
1383
1384 stasis_app_subscribe_channel(args_app, chan);
1385
1386 /* Subscribe to the Local channel peer also. */
1387 local_peer = ast_local_get_peer(chan);
1388 if (local_peer) {
1389 stasis_app_subscribe_channel(args_app, local_peer);
1390 ast_channel_unref(local_peer);
1391 }
1392 }
1393
1394 if (report_event_variables) {
1395 struct ast_variable *var;
1396
1397 for (var = report_event_variables; var; var = var->next) {
1398 if (ast_channel_set_ari_var_reportable(chan, var->name, 1)) {
1400 ast_dial_destroy(dial);
1401 ast_free(origination);
1402 return NULL;
1403 }
1404 }
1405 }
1407
1408 /* Before starting the async dial bump the ref in case the dial quickly goes away and takes
1409 * the reference with it
1410 */
1411 ast_channel_ref(chan);
1412
1415 ast_dial_destroy(dial);
1416 ast_free(origination);
1417 } else {
1419 }
1420
1421 return chan;
1422}
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
#define var
Definition ast_expr2f.c:605
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
static int connected
Definition cdr_pgsql.c:73
#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:11141
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:8484
@ AST_FLAG_ORIGINATED
Definition channel.h:1059
void ast_set_variables(struct ast_channel *chan, struct ast_variable *vars)
adds a list of channel variables to a channel
Definition channel.c:8291
struct ast_flags * ast_channel_flags(struct ast_channel *chan)
@ AST_CHANNEL_ERROR_ID_EXISTS
Definition channel.h:4936
#define ast_channel_ref(c)
Increase channel reference count.
Definition channel.h:3008
struct ast_party_connected_line * ast_channel_connected(struct ast_channel *chan)
const char * ast_channel_uniqueid(const struct ast_channel *chan)
int ast_channel_set_ari_var_reportable(struct ast_channel *chan, const char *variable, int report_events)
Set whether a channel variable should be included in REST events on the channel.
Definition channel.c:7906
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:7370
struct ast_channel * ast_channel_get_by_name(const char *search)
Find a channel by name or uniqueid.
Definition channel.c:1417
#define ast_channel_unref(c)
Decrease channel reference count.
Definition channel.h:3019
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:2032
#define ast_channel_cleanup(c)
Cleanup a channel reference.
Definition channel.h:3030
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:1277
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:1287
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:1261
int ast_dial_destroy(struct ast_dial *dial)
Destroys a dialing structure.
Definition dial.c:1094
#define ast_format_cache_get(name)
Retrieve a named format from the cache.
@ 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:2740
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.
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 attribute_pure 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
Structure for variables, used for configurations and for channel variables.
#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:981
#define ast_pthread_create_detached(a, b, c, d)
Definition utils.h:628
#define ast_set_flag(p, flag)
Definition utils.h:71

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_ref, ast_channel_set_ari_var_reportable(), ast_channel_set_connected_line(), ast_channel_snapshot_get_latest(), ast_channel_snapshot_to_json(), ast_channel_uniqueid(), 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, ast_variable::next, NULL, ari_origination::priority, RAII_VAR, S_OR, ast_channel::snapshot, stasis_app_subscribe_channel(), strsep(), thread, ast_assigned_ids::uniqueid, ast_assigned_ids::uniqueid2, and var.

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:361
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:912
@ 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:779

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

1891{
1892 enum stasis_app_snoop_direction spy, whisper;
1893 RAII_VAR(struct ast_channel *, chan, NULL, ast_channel_cleanup);
1894 RAII_VAR(struct ast_channel *, snoop, NULL, ast_channel_cleanup);
1895 RAII_VAR(struct ast_channel_snapshot *, snapshot, NULL, ao2_cleanup);
1896
1897 ast_assert(response != NULL);
1898
1899 if (ast_strlen_zero(args_spy) || !strcmp(args_spy, "none")) {
1901 } else if (!strcmp(args_spy, "both")) {
1903 } else if (!strcmp(args_spy, "out")) {
1905 } else if (!strcmp(args_spy, "in")) {
1907 } else {
1909 response, 400, "Bad Request",
1910 "Invalid direction specified for spy");
1911 return;
1912 }
1913
1914 if (ast_strlen_zero(args_whisper) || !strcmp(args_whisper, "none")) {
1916 } else if (!strcmp(args_whisper, "both")) {
1918 } else if (!strcmp(args_whisper, "out")) {
1920 } else if (!strcmp(args_whisper, "in")) {
1921 whisper = STASIS_SNOOP_DIRECTION_IN;
1922 } else {
1924 response, 400, "Bad Request",
1925 "Invalid direction specified for whisper");
1926 return;
1927 }
1928
1931 response, 400, "Bad Request",
1932 "Direction must be specified for at least spy or whisper");
1933 return;
1934 } else if (ast_strlen_zero(args_app)) {
1936 response, 400, "Bad Request",
1937 "Application name is required");
1938 return;
1939 }
1940
1941 chan = ast_channel_get_by_name(args_channel_id);
1942 if (chan == NULL) {
1944 response, 404, "Channel Not Found",
1945 "Provided channel was not found");
1946 return;
1947 }
1948
1949 snoop = stasis_app_control_snoop(chan, spy, whisper, args_app, args_app_args,
1950 args_snoop_id);
1951 if (snoop == NULL) {
1953 response, 500, "Internal error",
1954 "Snoop channel could not be created");
1955 return;
1956 }
1957
1960}
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 1065 of file resource_channels.c.

1066{
1067 struct ast_dial *dial = data;
1068 struct ari_origination *origination = ast_dial_get_user_data(dial);
1069 enum ast_dial_result res;
1070
1071 res = ast_dial_run(dial, NULL, 0);
1072 if (res != AST_DIAL_RESULT_ANSWERED) {
1073 goto end;
1074 }
1075
1076 if (!ast_strlen_zero(origination->appdata)) {
1077 struct ast_app *app = pbx_findapp("Stasis");
1078
1079 if (app) {
1080 ast_verb(4, "Launching Stasis(%s) on %s\n", origination->appdata,
1082 pbx_exec(ast_dial_answered(dial), app, origination->appdata);
1083 } else {
1084 ast_log(LOG_WARNING, "No such application 'Stasis'\n");
1085 }
1086 } else {
1087 struct ast_channel *answered = ast_dial_answered(dial);
1088
1089 if (!ast_strlen_zero(origination->context)) {
1090 ast_channel_context_set(answered, origination->context);
1091 }
1092
1093 if (!ast_strlen_zero(origination->exten)) {
1094 ast_channel_exten_set(answered, origination->exten);
1095 }
1096
1097 if (origination->priority > 0) {
1098 ast_channel_priority_set(answered, origination->priority);
1099 }
1100
1101 if (ast_pbx_run(answered)) {
1102 ast_log(LOG_ERROR, "Failed to start PBX on %s\n", ast_channel_name(answered));
1103 } else {
1104 /* PBX will have taken care of hanging up, so we steal the answered channel so dial doesn't do it */
1106 }
1107 }
1108
1109end:
1110 ast_dial_destroy(dial);
1111 ast_free(origination);
1112 return NULL;
1113}
static const char app[]
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:980
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:938
struct ast_channel * ast_dial_answered_steal(struct ast_dial *dial)
Steal the channel that answered.
Definition dial.c:992
void * ast_dial_get_user_data(struct ast_dial *dial)
Return the user data on a dial structure.
Definition dial.c:1282
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:3315

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

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(), 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 2089 of file resource_channels.c.

2092{
2093 RAII_VAR(struct ast_variable *, variables, NULL, ast_variables_destroy);
2094 RAII_VAR(struct ast_variable *, report_event_variables, NULL, ast_variables_destroy);
2095 struct ast_assigned_ids assignedids;
2096 struct ari_channel_thread_data *chan_data;
2097 struct ast_channel_snapshot *snapshot;
2098 pthread_t thread;
2099 char *dialtech;
2100 char *dialdevice = NULL;
2101 char *stuff;
2102 int cause;
2103 struct ast_format_cap *request_cap;
2104 struct ast_channel *originator = NULL;
2105
2106 /* Parse any query parameters out of the body parameter */
2107 if (args->variables) {
2108 struct ast_json *json_variables;
2109
2111 json_variables = ast_json_object_get(args->variables, "variables");
2112 if (json_variables &&
2113 json_to_ast_variables(response, json_variables, &variables, &report_event_variables)) {
2114 ast_log(LOG_ERROR, "Failed to parse variables from request body for channel creation\n");
2115 return;
2116 }
2117 }
2118
2119 assignedids.uniqueid = args->channel_id;
2120 assignedids.uniqueid2 = args->other_channel_id;
2121
2122 if (!ast_strlen_zero(args->originator) && !ast_strlen_zero(args->formats)) {
2123 ast_ari_response_error(response, 400, "Bad Request",
2124 "Originator and formats can't both be specified");
2125 return;
2126 }
2127
2128 if (ast_strlen_zero(args->endpoint)) {
2129 ast_ari_response_error(response, 400, "Bad Request",
2130 "Endpoint must be specified");
2131 return;
2132 }
2133
2134 chan_data = ast_calloc(1, sizeof(*chan_data));
2135 if (!chan_data) {
2137 return;
2138 }
2139
2140 chan_data->stasis_stuff = ast_str_create(32);
2141 if (!chan_data->stasis_stuff) {
2143 chan_data_destroy(chan_data);
2144 return;
2145 }
2146
2147 ast_str_append(&chan_data->stasis_stuff, 0, "%s", args->app);
2148 if (!ast_strlen_zero(args->app_args)) {
2149 ast_str_append(&chan_data->stasis_stuff, 0, ",%s", args->app_args);
2150 }
2151
2152 dialtech = ast_strdupa(args->endpoint);
2153 if ((stuff = strchr(dialtech, '/'))) {
2154 *stuff++ = '\0';
2155 dialdevice = stuff;
2156 }
2157
2158 if (ast_strlen_zero(dialtech) || ast_strlen_zero(dialdevice)) {
2159 ast_ari_response_error(response, 400, "Bad Request",
2160 "Invalid endpoint specified");
2161 chan_data_destroy(chan_data);
2162 return;
2163 }
2164
2165 if (!ast_strlen_zero(args->originator)) {
2166 originator = ast_channel_get_by_name(args->originator);
2167 }
2168
2169 if (originator) {
2170 request_cap = ao2_bump(ast_channel_nativeformats(originator));
2171 if (!ast_strlen_zero(args->app)) {
2172 stasis_app_subscribe_channel(args->app, originator);
2173 }
2174 } else if (!ast_strlen_zero(args->formats)) {
2175 char *format_name;
2176 char *formats_copy = ast_strdupa(args->formats);
2177
2178 if (!(request_cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
2180 chan_data_destroy(chan_data);
2181 return;
2182 }
2183
2184 while ((format_name = ast_strip(strsep(&formats_copy, ",")))) {
2185 struct ast_format *fmt = ast_format_cache_get(format_name);
2186
2187 if (!fmt || ast_format_cap_append(request_cap, fmt, 0)) {
2188 if (!fmt) {
2190 response, 400, "Bad Request",
2191 "Provided format (%s) was not found", format_name);
2192 } else {
2194 }
2195 ao2_ref(request_cap, -1);
2196 ao2_cleanup(fmt);
2197 chan_data_destroy(chan_data);
2198 return;
2199 }
2200 ao2_ref(fmt, -1);
2201 }
2202 } else {
2203 if (!(request_cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
2205 chan_data_destroy(chan_data);
2206 return;
2207 }
2208
2210 }
2211
2212 chan_data->chan = ast_request(dialtech, request_cap, &assignedids, originator, dialdevice, &cause);
2213 ao2_cleanup(request_cap);
2214
2215 if (!chan_data->chan) {
2217 ast_ari_response_error(response, 409, "Conflict",
2218 "Channel with given unique ID already exists");
2219 } else {
2221 }
2222 ast_channel_cleanup(originator);
2223 chan_data_destroy(chan_data);
2224 return;
2225 }
2226
2227 if (!ast_strlen_zero(args->app)) {
2228 stasis_app_subscribe_channel(args->app, chan_data->chan);
2229 }
2230
2231 if (variables) {
2232 ast_set_variables(chan_data->chan, variables);
2233 }
2234 if (report_event_variables) {
2235 struct ast_variable *var;
2236
2237 for (var = report_event_variables; var; var = var->next) {
2238 if (ast_channel_set_ari_var_reportable(chan_data->chan, var->name, 1)) {
2240 ast_channel_cleanup(originator);
2241 chan_data_destroy(chan_data);
2242 return;
2243 }
2244 }
2245 }
2246
2247 ast_channel_cleanup(originator);
2248
2249 if (save_dialstring(chan_data->chan, stuff)) {
2251 chan_data_destroy(chan_data);
2252 return;
2253 }
2254
2256
2259 chan_data_destroy(chan_data);
2260 } else {
2262 }
2263
2264 ao2_ref(snapshot, -1);
2265}
#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:6373
@ 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 void * ari_channel_thread(void *data)
Thread that owns stasis-created channel.
static int json_to_ast_variables(struct ast_ari_response *response, struct ast_json *json_variables, struct ast_variable **variables, struct ast_variable **report_event_variables)
int ast_ari_channels_create_parse_body(struct ast_json *body, struct ast_ari_channels_create_args *args)
Body parsing function for /channels/create.
char stuff[0]
Contents of file, name, and value in that order stuffed here.

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_set_ari_var_reportable(), 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_log, 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(), LOG_ERROR, NULL, RAII_VAR, save_dialstring(), stasis_app_subscribe_channel(), ari_channel_thread_data::stasis_stuff, strsep(), ast_variable::stuff, thread, ast_assigned_ids::uniqueid, ast_assigned_ids::uniqueid2, and var.

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

2270{
2271 RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
2272 RAII_VAR(struct ast_channel *, caller, NULL, ast_channel_cleanup);
2273 RAII_VAR(struct ast_channel *, callee, NULL, ast_channel_cleanup);
2274 char *dialstring;
2275
2276 control = find_control(response, args->channel_id);
2277 if (control == NULL) {
2278 /* Response filled in by find_control */
2279 return;
2280 }
2281
2282 if (!ast_strlen_zero(args->caller)) {
2283 caller = ast_channel_get_by_name(args->caller);
2284 }
2285
2286 callee = ast_channel_get_by_name(args->channel_id);
2287 if (!callee) {
2288 ast_ari_response_error(response, 404, "Not Found",
2289 "Callee not found");
2290 return;
2291 }
2292
2293 if (ast_channel_state(callee) != AST_STATE_DOWN
2294 && ast_channel_state(callee) != AST_STATE_RESERVED) {
2295 ast_ari_response_error(response, 409, "Conflict",
2296 "Channel is not in the 'Down' state");
2297 return;
2298 }
2299
2300 /* XXX This is straight up copied from main/dial.c. It's probably good
2301 * to separate this to some common method.
2302 */
2303 if (caller) {
2304 ast_channel_lock_both(caller, callee);
2305 } else {
2306 ast_channel_lock(callee);
2307 }
2308
2309 dialstring = restore_dialstring(callee);
2310 if (!dialstring) {
2311 ast_channel_unlock(callee);
2312 if (caller) {
2313 ast_channel_unlock(caller);
2314 }
2315 ast_ari_response_error(response, 409, "Conflict",
2316 "Dialing a channel not created by ARI");
2317 return;
2318 }
2319 /* Make a copy of the dialstring just in case some jerk tries to hang up the
2320 * channel before we can actually dial
2321 */
2322 dialstring = ast_strdupa(dialstring);
2323
2325 if (caller) {
2326 ast_channel_inherit_variables(caller, callee);
2327 ast_channel_datastore_inherit(caller, callee);
2329
2330 /* Copy over callerid information */
2332
2334
2336
2337 ast_channel_language_set(callee, ast_channel_language(caller));
2340 ast_channel_musicclass_set(callee, ast_channel_musicclass(caller));
2341
2344 ast_channel_unlock(caller);
2345 }
2346
2348 ast_channel_unlock(callee);
2349
2350 if (stasis_app_control_dial(control, dialstring, args->timeout)) {
2352 return;
2353 }
2354
2356}
@ AST_CHANNEL_REQUESTOR_BRIDGE_PEER
Definition channel.h:1525
const char * ast_channel_musicclass(const struct ast_channel *chan)
#define ast_channel_lock(chan)
Definition channel.h:2983
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:2990
int ast_channel_datastore_inherit(struct ast_channel *from, struct ast_channel *to)
Inherit datastores from a parent to a child.
Definition channel.c:2359
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:6453
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:6795
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:8469
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)
#define ast_channel_unlock(chan)
Definition channel.h:2984
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:2122
ast_channel_state
ast_channel states
@ AST_STATE_DOWN
@ AST_STATE_RESERVED
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.
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:1729
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 2574 of file resource_channels.c.

2576{
2577 RAII_VAR(struct ast_variable *, variables, NULL, ast_variables_destroy);
2578 RAII_VAR(struct ast_variable *, report_event_variables, NULL, ast_variables_destroy);
2579 char *external_host;
2580 char *host = NULL;
2581 char *port = NULL;
2582
2583 ast_assert(response != NULL);
2584
2585 /* Parse any query parameters out of the body parameter */
2586 if (args->variables) {
2587 struct ast_json *json_variables;
2588
2590 json_variables = ast_json_object_get(args->variables, "variables");
2591 if (json_variables
2592 && json_to_ast_variables(response, json_variables, &variables,
2593 &report_event_variables)) {
2594 return;
2595 }
2596 }
2597
2598 if (ast_strlen_zero(args->app)) {
2599 ast_ari_response_error(response, 400, "Bad Request", "app cannot be empty");
2600 return;
2601 }
2602
2603 if (ast_strlen_zero(args->transport)) {
2604 args->transport = "udp";
2605 }
2606
2607 if (ast_strlen_zero(args->encapsulation)) {
2608 args->encapsulation = "rtp";
2609 }
2610 if (ast_strings_equal(args->transport, "websocket")) {
2611 if (!ast_strings_equal(args->encapsulation, "none")) {
2612 ast_ari_response_error(response, 400, "Bad Request", "encapsulation must be 'none' for websocket transport");
2613 return;
2614 }
2615 }
2616
2617 if (ast_strings_equal(args->encapsulation, "rtp")) {
2618 if (!ast_strings_equal(args->transport, "udp")) {
2619 ast_ari_response_error(response, 400, "Bad Request", "transport must be 'udp' for rtp encapsulation");
2620 return;
2621 }
2622 }
2623
2624 if (ast_strings_equal(args->encapsulation, "audiosocket")) {
2625 if (!ast_strings_equal(args->transport, "tcp")) {
2626 ast_ari_response_error(response, 400, "Bad Request", "transport must be 'tcp' for audiosocket encapsulation");
2627 return;
2628 }
2629 }
2630
2631 if (ast_strlen_zero(args->connection_type)) {
2632 args->connection_type = "client";
2633 }
2634 if (!ast_strings_equal(args->transport, "websocket")) {
2635 if (ast_strings_equal(args->connection_type, "server")) {
2636 ast_ari_response_error(response, 400, "Bad Request", "'server' connection_type can only be used with the websocket transport");
2637 return;
2638 }
2639 }
2640
2641 if (ast_strlen_zero(args->external_host)) {
2642 if (ast_strings_equal(args->connection_type, "client")) {
2643 ast_ari_response_error(response, 400, "Bad Request", "external_host is required for all but websocket server connections");
2644 return;
2645 } else {
2646 /* server is only valid for websocket, enforced above */
2647 args->external_host = "INCOMING";
2648 }
2649 }
2650
2651 if (ast_strings_equal(args->transport, "websocket")) {
2652 if (ast_strings_equal(args->connection_type, "client")) {
2653 struct ast_websocket_client *ws_client =
2655 ao2_cleanup(ws_client);
2656 if (!ws_client) {
2657 ast_ari_response_error(response, 400, "Bad Request", "external_host must be a valid websocket_client connection id.");
2658 return;
2659 }
2660 }
2661 } else {
2662 external_host = ast_strdupa(args->external_host);
2663 if (!ast_sockaddr_split_hostport(external_host, &host, &port, PARSE_PORT_REQUIRE)) {
2664 ast_ari_response_error(response, 400, "Bad Request", "external_host must be <host>:<port> for all transports other than websocket");
2665 return;
2666 }
2667 }
2668
2669 if (ast_strlen_zero(args->format)) {
2670 ast_ari_response_error(response, 400, "Bad Request", "format cannot be empty");
2671 return;
2672 }
2673
2674 if (!ast_strlen_zero(args->direction)) {
2675 if (strcmp(args->direction, "both") && strcmp(args->direction, "in")
2676 && strcmp(args->direction, "out")) {
2678 response, 400, "Bad Request",
2679 "Invalid direction specified");
2680 return;
2681 }
2682 }
2683
2684 if (strcasecmp(args->encapsulation, "rtp") == 0 && strcasecmp(args->transport, "udp") == 0) {
2685 if (external_media_rtp_udp(args, variables, report_event_variables, response)) {
2687 response, 500, "Internal Server Error",
2688 "An internal error prevented this request from being handled");
2689 }
2690 } else if (strcasecmp(args->encapsulation, "audiosocket") == 0 && strcasecmp(args->transport, "tcp") == 0) {
2691 if (ast_strlen_zero(args->data)) {
2692 ast_ari_response_error(response, 400, "Bad Request", "data can not be empty");
2693 } else if (external_media_audiosocket_tcp(args, variables, report_event_variables, response)) {
2695 response, 500, "Internal Server Error",
2696 "An internal error prevented this request from being handled");
2697 }
2698 } else if (strcasecmp(args->encapsulation, "none") == 0 && strcasecmp(args->transport, "websocket") == 0) {
2699 if (external_media_websocket(args, variables, report_event_variables, response)) {
2701 response, 500, "Internal Server Error",
2702 "An internal error prevented this request from being handled");
2703 }
2704 } else {
2706 response, 501, "Not Implemented",
2707 "The encapsulation and/or transport is not supported");
2708 }
2709}
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_websocket(struct ast_ari_channels_external_media_args *args, struct ast_variable *variables, struct ast_variable *report_event_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_variable *report_event_variables, struct ast_ari_response *response)
static int external_media_audiosocket_tcp(struct ast_ari_channels_external_media_args *args, struct ast_variable *variables, struct ast_variable *report_event_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 1613 of file resource_channels.c.

1616{
1617 RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
1618 RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
1619 RAII_VAR(struct ast_str *, value, ast_str_create(32), ast_free);
1620 RAII_VAR(struct ast_channel *, channel, NULL, ast_channel_cleanup);
1621
1622 ast_assert(response != NULL);
1623
1624 if (!value) {
1626 return;
1627 }
1628
1629 if (ast_strlen_zero(args->variable)) {
1631 response, 400, "Bad Request",
1632 "Variable name is required");
1633 return;
1634 }
1635
1636 if (ast_strlen_zero(args->channel_id)) {
1638 response, 400, "Bad Request",
1639 "Channel ID is required");
1640 return;
1641 }
1642
1643 channel = ast_channel_get_by_name(args->channel_id);
1644 if (!channel) {
1646 response, 404, "Channel Not Found",
1647 "Provided channel was not found");
1648 return;
1649 }
1650
1651 /* You may be tempted to lock the channel you're about to read from. You
1652 * would be wrong. Some dialplan functions put the channel into
1653 * autoservice, which deadlocks if the channel is already locked.
1654 * ast_str_retrieve_variable() does its own locking, and the dialplan
1655 * functions need to as well. We should be fine without the lock.
1656 */
1657
1658 if (args->variable[strlen(args->variable) - 1] == ')') {
1659 if (ast_func_read2(channel, args->variable, &value, 0)) {
1661 response, 500, "Error With Function",
1662 "Unable to read provided function");
1663 return;
1664 }
1665 } else {
1666 if (!ast_str_retrieve_variable(&value, 0, channel, NULL, args->variable)) {
1668 response, 404, "Variable Not Found",
1669 "Provided variable was not found");
1670 return;
1671 }
1672 }
1673
1674 if (!(json = ast_json_pack("{s: s}", "value", S_OR(ast_str_buffer(value), "")))) {
1676 return;
1677 }
1678
1679 ast_ari_response_ok(response, ast_json_ref(json));
1680}
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_get_channel_vars()

void ast_ari_channels_get_channel_vars ( struct ast_variable headers,
struct ast_ari_channels_get_channel_vars_args args,
struct ast_ari_response response 
)

Get the value of multiple channel variables or functions.

Parameters
headersHTTP headers
argsSwagger parameters
[out]responseHTTP response

Definition at line 1682 of file resource_channels.c.

1685{
1686 int res;
1688 RAII_VAR(struct ast_json *, inner_json, ast_json_object_create(), ast_json_unref);
1689 RAII_VAR(struct ast_str *, value, ast_str_create(32), ast_free);
1690 RAII_VAR(struct ast_channel *, channel, NULL, ast_channel_cleanup);
1691
1692 ast_assert(response != NULL);
1693
1694 if (!json || !inner_json || !value) {
1696 return;
1697 }
1698
1699 if (args->variables_count == 0) {
1701 response, 400, "Bad Request",
1702 "At least one variable name is required");
1703 return;
1704 }
1705
1706 if (ast_strlen_zero(args->channel_id)) {
1708 response, 400, "Bad Request",
1709 "Channel ID is required");
1710 return;
1711 }
1712
1713 channel = ast_channel_get_by_name(args->channel_id);
1714 if (!channel) {
1716 response, 404, "Channel Not Found",
1717 "Provided channel was not found");
1718 return;
1719 }
1720
1721 for (int i = 0; i < args->variables_count; i++) {
1722 struct ast_json *json_str;
1723 char buf[strlen(args->variables[i]) + 1];
1724 char *variable;
1725
1726 strcpy(buf, args->variables[i]);
1727 variable = ast_strip(buf);
1728 if (ast_strlen_zero(variable)) {
1730 response, 400, "Bad Request",
1731 "Variable names are required");
1732 return;
1733 }
1734
1735 if (variable[strlen(variable) - 1] == ')') {
1736 if (ast_func_read2(channel, variable, &value, 0)) {
1738 response, 500, "Error With Function",
1739 "Unable to read provided function");
1740 return;
1741 }
1742 } else {
1743 if (!ast_str_retrieve_variable(&value, 0, channel, NULL, variable)) {
1745 response, 404, "Variable Not Found",
1746 "Provided variable was not found");
1747 return;
1748 }
1749 }
1750
1752 if (!json_str) {
1754 return;
1755 }
1756
1757 res = ast_json_object_set(inner_json, variable, json_str);
1758 if (res) {
1760 ast_json_unref(json_str);
1761 return;
1762 }
1763 }
1764
1765 res = ast_json_object_set(json, "variables", ast_json_ref(inner_json));
1766 if (res) {
1768 return;
1769 }
1770
1771 ast_ari_response_ok(response, ast_json_ref(json));
1772}
char buf[BUFSIZE]
Definition eagi_proxy.c:66
struct ast_json * ast_json_string_create(const char *value)
Construct a JSON string from value.
Definition json.c:278
struct ast_json * ast_json_object_create(void)
Create a new JSON object.
Definition json.c:399
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

References 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_object_create(), ast_json_object_set(), ast_json_ref(), ast_json_string_create(), ast_json_unref(), ast_str_buffer(), ast_str_create, ast_str_retrieve_variable(), ast_strip(), ast_strlen_zero(), buf, NULL, RAII_VAR, and value.

Referenced by ast_ari_channels_get_channel_vars_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 struct ast_rtp_glue *glue;
935 struct ast_rtp_instance *rtp = NULL;
936 const struct ast_channel_tech *tech;
937
938 chan = ast_channel_get_by_name(args->channel_id);
939 if (chan == NULL) {
941 response, 404, "Not Found",
942 "Channel not found");
943 return;
944 }
945
946 if (!ast_strlen_zero(args->reason) && !ast_strlen_zero(args->reason_code)) {
947 ast_ari_response_error(response, 400, "Bad Request",
948 "The reason and reason_code can't both be specified");
949 return;
950 }
951
952 if (!ast_strlen_zero(args->reason_code)) {
953 /* reason_code allows any hangup code */
954 if (sscanf(args->reason_code, "%30d", &cause) != 1) {
956 response, 400, "Invalid Reason Code",
957 "Invalid reason for hangup reason code provided");
958 return;
959 }
960 } else if (!ast_strlen_zero(args->reason)) {
961 /* reason allows only listed hangup reason */
962 cause = convert_reason_to_hangup_code(args->reason);
963 if (cause == -1) {
965 response, 400, "Invalid Reason",
966 "Invalid reason for hangup reason provided");
967 return;
968 }
969 } else {
970 /* not specified. set default hangup */
971 cause = AST_CAUSE_NORMAL;
972 }
973
974 ast_channel_hangupcause_set(chan, cause);
975
976 /*
977 * Only hold the channel lock long enough to get the rtp instance.
978 * glue->get_rtp_info() will bump the refcount on it.
979 */
980 ast_channel_lock(chan);
981 tech = ast_channel_tech(chan);
982 glue = ast_rtp_instance_get_glue(tech->type);
983 if (glue) {
984 glue->get_rtp_info(chan, &rtp);
985 }
986 ast_channel_unlock(chan);
987 /*
988 * If this channel is in a bridge, ast_rtp_instance_set_stats_vars() will
989 * attempt to lock the bridge peer as well as this channel. This can cause
990 * a lock inversion if we already have this channel locked and another
991 * thread tries to set bridge variables on the peer because it will have
992 * locked the peer first, then this channel. For this reason, we must
993 * NOT have the channel locked when we call ast_rtp_instance_set_stats_vars().
994 * This should be safe since glue->get_rtp_info() will have bumped the
995 * refcount on the rtp instance so it can't go away while the channel
996 * is unlocked.
997 */
998 if (rtp) {
1000 ao2_ref(rtp, -1);
1001 }
1002
1004
1006}
#define AST_CAUSE_NORMAL
Definition causes.h:151
int ast_softhangup(struct ast_channel *chan, int cause)
Softly hangup up a channel.
Definition channel.c:2462
@ AST_SOFTHANGUP_EXPLICIT
Definition channel.h:1168
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.
void ast_rtp_instance_set_stats_vars(struct ast_channel *chan, struct ast_rtp_instance *instance)
Set standard statistics from an RTP instance on a channel.
struct ast_rtp_glue * ast_rtp_instance_get_glue(const char *type)
Get the RTP glue that binds a channel to the RTP engine.
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, ao2_ref, args, ast_ari_response_error(), ast_ari_response_no_content(), AST_CAUSE_NORMAL, ast_channel_get_by_name(), ast_channel_hangupcause_set(), ast_channel_lock, ast_channel_unlock, ast_rtp_instance_get_glue(), ast_rtp_instance_set_stats_vars(), ast_softhangup(), AST_SOFTHANGUP_EXPLICIT, ast_strlen_zero(), convert_reason_to_hangup_code(), ast_rtp_glue::get_rtp_info, NULL, RAII_VAR, and ast_channel_tech::type.

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:800

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

1011{
1012 RAII_VAR(struct ao2_container *, snapshots, NULL, ao2_cleanup);
1013 RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
1014 struct ao2_iterator i;
1015 void *obj;
1017
1018 snapshots = ast_channel_cache_all();
1019
1020 json = ast_json_array_create();
1021 if (!json) {
1023 return;
1024 }
1025
1026 i = ao2_iterator_init(snapshots, 0);
1027 while ((obj = ao2_iterator_next(&i))) {
1028 struct ast_channel_snapshot *snapshot = obj;
1029 int r;
1030
1031 if (sanitize && sanitize->channel_snapshot
1032 && sanitize->channel_snapshot(snapshot)) {
1033 ao2_ref(snapshot, -1);
1034 continue;
1035 }
1036
1038 json, ast_channel_snapshot_to_json(snapshot, NULL));
1039 if (r != 0) {
1042 ao2_ref(snapshot, -1);
1043 return;
1044 }
1045 ao2_ref(snapshot, -1);
1046 }
1048
1049 ast_ari_response_ok(response, ast_json_ref(json));
1050}
#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.
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:4851
#define AST_MUTE_DIRECTION_WRITE
Definition channel.h:4852
direction
ast_frame_type
Frame types.
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 1570 of file resource_channels.c.

1573{
1574 struct ast_variable *variables = NULL;
1575 struct ast_variable *report_event_variables = NULL;
1576 struct ast_channel *chan;
1577
1578 /* Parse any query parameters out of the body parameter */
1579 if (args->variables) {
1580 struct ast_json *json_variables;
1581
1583 json_variables = ast_json_object_get(args->variables, "variables");
1584 if (json_variables
1585 && json_to_ast_variables(response, json_variables, &variables,
1586 &report_event_variables)) {
1587 return;
1588 }
1589 }
1590
1592 args->endpoint,
1593 args->extension,
1594 args->context,
1595 args->priority,
1596 args->label,
1597 args->app,
1598 args->app_args,
1599 args->caller_id,
1600 args->timeout,
1601 variables,
1602 report_event_variables,
1603 args->channel_id,
1604 args->other_channel_id,
1605 args->originator,
1606 args->formats,
1607 response);
1608 ast_channel_cleanup(chan);
1609 ast_variables_destroy(report_event_variables);
1610 ast_variables_destroy(variables);
1611}
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, struct ast_variable *report_event_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 1527 of file resource_channels.c.

1530{
1531 struct ast_variable *variables = NULL;
1532 struct ast_variable *report_event_variables = NULL;
1533 struct ast_channel *chan;
1534
1535 /* Parse any query parameters out of the body parameter */
1536 if (args->variables) {
1537 struct ast_json *json_variables;
1538
1540 json_variables = ast_json_object_get(args->variables, "variables");
1541 if (json_variables
1542 && json_to_ast_variables(response, json_variables, &variables,
1543 &report_event_variables)) {
1544 return;
1545 }
1546 }
1547
1549 args->endpoint,
1550 args->extension,
1551 args->context,
1552 args->priority,
1553 args->label,
1554 args->app,
1555 args->app_args,
1556 args->caller_id,
1557 args->timeout,
1558 variables,
1559 report_event_variables,
1560 args->channel_id,
1561 args->other_channel_id,
1562 args->originator,
1563 args->formats,
1564 response);
1565 ast_channel_cleanup(chan);
1566 ast_variables_destroy(report_event_variables);
1567 ast_variables_destroy(variables);
1568}
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.
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:721
const struct ast_flags ast_uri_http
Definition utils.c:717

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

2361{
2362 RAII_VAR(struct ast_channel *, chan, NULL, ast_channel_cleanup);
2363 RAII_VAR(struct ast_rtp_instance *, rtp, NULL, ao2_cleanup);
2364 struct ast_json *j_res;
2365 const struct ast_channel_tech *tech;
2366 struct ast_rtp_glue *glue;
2367
2368 chan = ast_channel_get_by_name(args->channel_id);
2369 if (!chan) {
2370 ast_ari_response_error(response, 404, "Not Found",
2371 "Channel not found");
2372 return;
2373 }
2374
2375 ast_channel_lock(chan);
2376 tech = ast_channel_tech(chan);
2377 if (!tech) {
2378 ast_channel_unlock(chan);
2379 ast_ari_response_error(response, 404, "Not Found",
2380 "Channel's tech not found");
2381 return;
2382 }
2383
2384 glue = ast_rtp_instance_get_glue(tech->type);
2385 if (!glue) {
2386 ast_channel_unlock(chan);
2387 ast_ari_response_error(response, 403, "Forbidden",
2388 "Unsupported channel type");
2389 return;
2390 }
2391
2392 glue->get_rtp_info(chan, &rtp);
2393 if (!rtp) {
2394 ast_channel_unlock(chan);
2395 ast_ari_response_error(response, 404, "Not Found",
2396 "RTP info not found");
2397 return;
2398 }
2399
2401 if (!j_res) {
2402 ast_channel_unlock(chan);
2403 ast_ari_response_error(response, 404, "Not Found",
2404 "Statistics not found");
2405 return;
2406 }
2407
2408 ast_channel_unlock(chan);
2409 ast_ari_response_ok(response, j_res);
2410
2411 return;
2412}
struct ast_json * ast_rtp_instance_get_stats_all_json(struct ast_rtp_instance *instance)
Retrieve statistics about an RTP instance in json format.

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

1777{
1778 RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
1779
1780 ast_assert(response != NULL);
1781
1782 if (ast_strlen_zero(args->variable)) {
1784 response, 400, "Bad Request",
1785 "Variable name is required");
1786 return;
1787 }
1788
1789 control = find_control(response, args->channel_id);
1790 if (control == NULL) {
1791 /* response filled in by find_control */
1792 return;
1793 }
1794
1795 if (stasis_app_control_set_channel_var_reportable(control, args->variable, args->value,
1796 args->report_events)) {
1798 response, 400, "Bad Request",
1799 "Failed to execute function");
1800 return;
1801 }
1802
1804}
int stasis_app_control_set_channel_var_reportable(struct stasis_app_control *control, const char *variable, const char *value, int report_events)
Set a variable on the channel associated with this control to value with option of including in event...
Definition control.c:763

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

Referenced by ast_ari_channels_set_channel_var_cb().

◆ ast_ari_channels_set_channel_vars()

void ast_ari_channels_set_channel_vars ( struct ast_variable headers,
struct ast_ari_channels_set_channel_vars_args args,
struct ast_ari_response response 
)

Set the values of multiple channel variables or functions.

Parameters
headersHTTP headers
argsSwagger parameters
[out]responseHTTP response

Definition at line 1806 of file resource_channels.c.

1809{
1810 struct ast_json *json_variables;
1811 struct ast_variable *var;
1812 RAII_VAR(struct ast_variable *, variables, NULL, ast_variables_destroy);
1813 RAII_VAR(struct ast_variable *, report_event_variables, NULL, ast_variables_destroy);
1814 RAII_VAR(struct ast_channel *, channel, NULL, ast_channel_cleanup);
1815 RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
1816
1817 ast_assert(response != NULL);
1818
1819 if (!args->variables) {
1821 response, 400, "Bad Request",
1822 "The 'variables' field is required");
1823 return;
1824 }
1825
1826 channel = ast_channel_get_by_name(args->channel_id);
1827 if (!channel) {
1829 response, 404, "Channel Not Found",
1830 "Provided channel was not found");
1831 return;
1832 }
1833
1834 control = find_control(response, args->channel_id);
1835 if (control == NULL) {
1836 /* response filled in by find_control */
1837 return;
1838 }
1839
1840 json_variables = ast_json_object_get(args->variables, "variables");
1841 if (!json_variables || ast_json_typeof(json_variables) != AST_JSON_OBJECT) {
1843 response, 400, "Bad Request",
1844 "The 'variables' field must be a JSON object");
1845 return;
1846 }
1847
1848 if (json_to_ast_variables(response, json_variables, &variables,
1849 &report_event_variables)) {
1850 return;
1851 }
1852
1853 for (var = variables; var; var = var->next) {
1854 int report_events = 0;
1855 struct ast_variable *report_var;
1856 char buf[strlen(var->name) + 1];
1857 char *variable;
1858 strcpy(buf, var->name);
1859 /* Strip whitespace from the variable name */
1860 variable = ast_strip(buf);
1861
1862 /* See if the variable is in the report event list */
1863 for (report_var = report_event_variables; report_var;
1864 report_var = report_var->next) {
1865 if (!strcmp(report_var->name, var->name)) {
1866 report_events = 1;
1867 break;
1868 }
1869 }
1870
1872 var->value, report_events)) {
1874 response, 400, "Bad Request",
1875 "Failed to execute function");
1876 return;
1877 }
1878 }
1879
1881}
enum ast_json_type ast_json_typeof(const struct ast_json *value)
Get the type of value.
Definition json.c:78
@ AST_JSON_OBJECT
Definition json.h:164
struct ast_variable * next

References ao2_cleanup, args, ast_ari_response_error(), ast_ari_response_no_content(), ast_assert, ast_channel_cleanup, ast_channel_get_by_name(), AST_JSON_OBJECT, ast_json_object_get(), ast_json_typeof(), ast_strip(), ast_variables_destroy(), buf, find_control(), json_to_ast_variables(), ast_variable::name, ast_variable::next, NULL, RAII_VAR, stasis_app_control_set_channel_var_reportable(), and var.

Referenced by ast_ari_channels_set_channel_vars_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 1962 of file resource_channels.c.

1965{
1967 args->channel_id,
1968 args->spy,
1969 args->whisper,
1970 args->app,
1971 args->app_args,
1972 args->snoop_id,
1973 response);
1974}
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 1976 of file resource_channels.c.

1979{
1981 args->channel_id,
1982 args->spy,
1983 args->whisper,
1984 args->app,
1985 args->app_args,
1986 args->snoop_id,
1987 response);
1988}

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:832

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:884

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:850

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:907

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

2712{
2714 RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
2715 RAII_VAR(struct ast_channel *, chan, NULL, ast_channel_cleanup);
2716
2717 control = find_control(response, args->channel_id);
2718 if (control == NULL) {
2719 /* Response filled in by find_control */
2720 return;
2721 }
2722
2723 chan = ast_channel_get_by_name(args->channel_id);
2724 if (!chan) {
2725 ast_ari_response_error(response, 404, "Not Found",
2726 "Callee not found");
2727 return;
2728 }
2729
2730 if (ast_strlen_zero(args->states)) {
2731 ast_ari_response_error(response, 400, "Bad Request", "states must not be empty");
2732 return;
2733 }
2734
2735 if (strcasecmp(args->states, "channel_progress") == 0) {
2737 } else if (strcasecmp(args->states, "channel_answered") == 0) {
2739 } else if (strcasecmp(args->states, "channel_unavailable") == 0) {
2741 } else if (strcasecmp(args->states, "channel_declined") == 0) {
2743 } else {
2744 ast_ari_response_error(response, 400, "Bad Request", "Invalid states value");
2745 return;
2746 }
2747
2750}
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:4676
@ 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:813

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

1996{
1997 ast_free(chan_data->stasis_stuff);
1998 ast_hangup(chan_data->chan);
1999 ast_free(chan_data);
2000}
void ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition channel.c:2540

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
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_variable report_event_variables,
struct ast_ari_response response 
)
static

Definition at line 2463 of file resource_channels.c.

2467{
2468 char *endpoint;
2469 struct ast_channel *chan;
2470 struct varshead *vars;
2471
2472 if (ast_asprintf(&endpoint, "AudioSocket/%s/%s",
2473 args->external_host, args->data) == -1) {
2474 return 1;
2475 }
2476
2478 endpoint,
2479 NULL,
2480 NULL,
2481 0,
2482 NULL,
2483 args->app,
2484 args->data,
2485 NULL,
2486 0,
2487 variables,
2488 report_event_variables,
2489 args->channel_id,
2490 NULL,
2491 NULL,
2492 args->format,
2493 response);
2494
2495 ast_free(endpoint);
2496
2497 if (!chan) {
2498 return 1;
2499 }
2500
2501 ast_channel_lock(chan);
2502 vars = ast_channel_varshead(chan);
2503 if (vars && !AST_LIST_EMPTY(vars)) {
2504 ast_json_object_set(response->message, "channelvars", ast_json_channel_vars(vars));
2505 }
2506 ast_channel_unlock(chan);
2507 ast_channel_unref(chan);
2508 return 0;
2509}
struct varshead * ast_channel_varshead(struct ast_channel *chan)
struct ast_json * ast_json_channel_vars(struct varshead *channelvars)
Construct a JSON object from a ast_var_t list.
Definition json.c:941
#define AST_LIST_EMPTY(head)
Checks whether the specified list contains any entries.
struct ast_json * message
Definition ari.h:103

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

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

Definition at line 2414 of file resource_channels.c.

2418{
2419 char *endpoint;
2420 struct ast_channel *chan;
2421 struct varshead *vars;
2422
2423 if (ast_asprintf(&endpoint, "UnicastRTP/%s/c(%s)",
2424 args->external_host,
2425 args->format) == -1) {
2426 return 1;
2427 }
2428
2430 endpoint,
2431 NULL,
2432 NULL,
2433 0,
2434 NULL,
2435 args->app,
2436 args->data,
2437 NULL,
2438 0,
2439 variables,
2440 report_event_variables,
2441 args->channel_id,
2442 NULL,
2443 NULL,
2444 args->format,
2445 response);
2446
2447 ast_free(endpoint);
2448
2449 if (!chan) {
2450 return 1;
2451 }
2452
2453 ast_channel_lock(chan);
2454 vars = ast_channel_varshead(chan);
2455 if (vars && !AST_LIST_EMPTY(vars)) {
2456 ast_json_object_set(response->message, "channelvars", ast_json_channel_vars(vars));
2457 }
2458 ast_channel_unlock(chan);
2459 ast_channel_unref(chan);
2460 return 0;
2461}

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_variable report_event_variables,
struct ast_ari_response response 
)
static

Definition at line 2511 of file resource_channels.c.

2515{
2516 char *endpoint;
2517 struct ast_channel *chan;
2518 struct varshead *vars;
2519 char direction[16] = "";
2520
2521 /* If direction is set here, it WILL override any m() line in transport data
2522 * since it is appended to the end of the string.
2523 */
2524 if (args->direction) {
2525 snprintf(direction, sizeof(direction), "d(%s)", args->direction);
2526 }
2527
2528 if (ast_asprintf(&endpoint, "WebSocket/%s%s%s%s%s",
2529 args->external_host,
2530 S_COR(args->transport_data, "/", ""),
2531 S_OR(args->transport_data, ""),
2532 S_COR(!args->transport_data && args->direction, "/", ""),
2533 direction) == -1) {
2534 return 1;
2535 }
2536
2538 endpoint,
2539 NULL,
2540 NULL,
2541 0,
2542 NULL,
2543 args->app,
2544 args->data,
2545 NULL,
2546 0,
2547 variables,
2548 report_event_variables,
2549 args->channel_id,
2550 NULL,
2551 NULL,
2552 args->format,
2553 response);
2554
2555 ast_free(endpoint);
2556
2557 if (!chan) {
2558 return 1;
2559 }
2560
2561 ast_channel_lock(chan);
2562 vars = ast_channel_varshead(chan);
2563 if (vars && !AST_LIST_EMPTY(vars)) {
2564 ast_json_object_set(response->message, "channelvars", ast_json_channel_vars(vars));
2565 }
2566 ast_channel_unlock(chan);
2567 ast_channel_unref(chan);
2568 return 0;
2569}
#define S_COR(a, b, c)
returns the equivalent of logic or for strings, with an additional boolean check: second one if not e...
Definition strings.h:87

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, NULL, S_COR, and S_OR.

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_set_channel_vars(), 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,
struct ast_variable **  report_event_variables 
)
static

Definition at line 1436 of file resource_channels.c.

1438{
1439 struct ast_json_iter *it_json_var;
1440 struct ast_variable *var_tail = NULL;
1441 struct ast_variable *report_var_tail = NULL;
1442
1443 *variables = NULL;
1444 *report_event_variables = NULL;
1445
1446 for (it_json_var = ast_json_object_iter(json_variables); it_json_var;
1447 it_json_var = ast_json_object_iter_next(json_variables, it_json_var)) {
1448 struct ast_variable *new_var;
1449 const char *key = ast_json_object_iter_key(it_json_var);
1450 const char *value = NULL;
1451 struct ast_json *json_value = ast_json_object_iter_value(it_json_var);
1452 int report_events = 0;
1453
1454 if (ast_strlen_zero(key)) {
1455 continue;
1456 }
1457
1458 if (ast_json_typeof(json_value) == AST_JSON_STRING) {
1459 value = ast_json_string_get(json_value);
1460 } else if (ast_json_typeof(json_value) == AST_JSON_OBJECT) {
1461 struct ast_json *value_field = ast_json_object_get(json_value, "value");
1462 struct ast_json *report_field = ast_json_object_get(json_value, "report_events");
1463 ast_log(LOG_DEBUG, "Processing variable '%s' with report_events: %s\n", key,
1464 report_field ? (ast_json_is_true(report_field) ? "true" : "false") : "not set");
1465
1466 if (!value_field || ast_json_typeof(value_field) != AST_JSON_STRING) {
1467 ast_ari_response_error(response, 400, "Bad Request",
1468 "Each object value in 'variables' must include string field 'value'");
1469 goto error;
1470 }
1471
1472 value = ast_json_string_get(value_field);
1473 ast_log(LOG_DEBUG, "Variable '%s' has value '%s'\n", key, value);
1474
1475 if (report_field) {
1476 enum ast_json_type report_type = ast_json_typeof(report_field);
1477
1478 if (report_type != AST_JSON_TRUE && report_type != AST_JSON_FALSE) {
1479 ast_ari_response_error(response, 400, "Bad Request",
1480 "Field 'report_events' in 'variables' entries must be boolean");
1481 goto error;
1482 }
1483
1484 report_events = ast_json_is_true(report_field);
1485 }
1486 } else {
1487 ast_ari_response_error(response, 400, "Bad Request",
1488 "Each value in 'variables' must be a string or an object with 'value' and optional 'report_events'");
1489 goto error;
1490 }
1491
1492 if (!value) {
1493 continue;
1494 }
1495
1496 new_var = ast_variable_new(key, value, "");
1497 if (!new_var) {
1499 goto error;
1500 }
1501
1502 var_tail = ast_variable_list_append_hint(variables, var_tail, new_var);
1503
1504 if (report_events) {
1505 struct ast_variable *report_var = ast_variable_new(key, "1", "");
1506
1507 if (!report_var) {
1509 goto error;
1510 }
1511
1512 report_var_tail = ast_variable_list_append_hint(report_event_variables,
1513 report_var_tail, report_var);
1514 }
1515 }
1516
1517 return 0;
1518
1519error:
1520 ast_variables_destroy(*variables);
1521 *variables = NULL;
1522 ast_variables_destroy(*report_event_variables);
1523 *report_event_variables = NULL;
1524 return -1;
1525}
#define ast_variable_new(name, value, filename)
struct ast_variable * ast_variable_list_append_hint(struct ast_variable **head, struct ast_variable *search_hint, struct ast_variable *new_var)
Appends a variable list to the end of another list.
#define LOG_DEBUG
struct ast_json * ast_json_object_iter_value(struct ast_json_iter *iter)
Get the value from an iterator.
Definition json.c:455
struct ast_json_iter * ast_json_object_iter_next(struct ast_json *object, struct ast_json_iter *iter)
Get the next iterator.
Definition json.c:447
struct ast_json_iter * ast_json_object_iter(struct ast_json *object)
Get an iterator pointing to the first field in a JSON object.
Definition json.c:439
ast_json_type
Valid types of a JSON element.
Definition json.h:163
@ AST_JSON_STRING
Definition json.h:166
@ AST_JSON_FALSE
Definition json.h:170
@ AST_JSON_TRUE
Definition json.h:169
const char * ast_json_string_get(const struct ast_json *string)
Get the value of a JSON string.
Definition json.c:283
const char * ast_json_object_iter_key(struct ast_json_iter *iter)
Get the key from an iterator.
Definition json.c:451
int ast_json_is_true(const struct ast_json *value)
Check if value is JSON true.
Definition json.c:263
Iterator for JSON object key/values.
int error(const char *format,...)

References ast_ari_response_alloc_failed(), ast_ari_response_error(), AST_JSON_FALSE, ast_json_is_true(), AST_JSON_OBJECT, ast_json_object_get(), ast_json_object_iter(), ast_json_object_iter_key(), ast_json_object_iter_next(), ast_json_object_iter_value(), AST_JSON_STRING, ast_json_string_get(), AST_JSON_TRUE, ast_json_typeof(), ast_log, ast_strlen_zero(), ast_variable_list_append_hint(), ast_variable_new, ast_variables_destroy(), error(), LOG_DEBUG, NULL, and value.

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

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

2078{
2079 struct ast_datastore *datastore;
2080
2081 datastore = ast_channel_datastore_find(chan, &dialstring_info, NULL);
2082 if (!datastore) {
2083 return NULL;
2084 }
2085
2086 return datastore->data;
2087}
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:2390
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 2043 of file resource_channels.c.

2044{
2045 struct ast_datastore *datastore;
2046
2048 if (!datastore) {
2049 return -1;
2050 }
2051
2052 datastore->data = ast_strdup(dialstring);
2053 if (!datastore->data) {
2054 ast_datastore_free(datastore);
2055 return -1;
2056 }
2057
2058 ast_channel_lock(chan);
2059 if (ast_channel_datastore_add(chan, datastore)) {
2060 ast_channel_unlock(chan);
2061 ast_datastore_free(datastore);
2062 return -1;
2063 }
2064 ast_channel_unlock(chan);
2065
2066 return 0;
2067}
#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:2376
#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 2028 of file resource_channels.c.

2028 {
2029 .type = "ARI Dialstring",
2030 .destroy = ast_free_ptr,
2031};

Referenced by restore_dialstring(), and save_dialstring().