Asterisk - The Open Source Telephony Project GIT-master-4c84066
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, 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_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_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_ari_response *response)
 
static int external_media_rtp_udp (struct ast_ari_channels_external_media_args *args, struct ast_variable *variables, struct ast_ari_response *response)
 
static int external_media_websocket (struct ast_ari_channels_external_media_args *args, struct ast_variable *variables, struct ast_ari_response *response)
 
static struct stasis_app_controlfind_control (struct ast_ari_response *response, const char *channel_id)
 Finds the control object for a channel, filling the response with an error, if appropriate.
 
static int json_to_ast_variables (struct ast_ari_response *response, struct ast_json *json_variables, struct ast_variable **variables)
 
static char * restore_dialstring (struct ast_channel *chan)
 Retrieve the dialstring from the channel datastore.
 
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 1748 of file resource_channels.c.

1749{
1750 struct ari_channel_thread_data *chan_data = data;
1751 struct ast_app *stasis_app;
1752
1753 stasis_app = pbx_findapp("Stasis");
1754 if (!stasis_app) {
1755 ast_log(LOG_ERROR, "Stasis dialplan application is not registered");
1756 chan_data_destroy(chan_data);
1757 return NULL;
1758 }
1759
1760 pbx_exec(chan_data->chan, stasis_app, ast_str_buffer(chan_data->stasis_stuff));
1761
1762 chan_data_destroy(chan_data);
1763
1764 return NULL;
1765}
#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,
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.

1130{
1131 char *dialtech;
1132 char *dialdevice = NULL;
1133 struct ast_dial *dial;
1134 char *caller_id = NULL;
1135 char *cid_num = NULL;
1136 char *cid_name = NULL;
1137 char *stuff;
1138 struct ast_channel *other = NULL;
1139 struct ast_channel *chan = NULL;
1141 struct ast_assigned_ids assignedids = {
1142 .uniqueid = args_channel_id,
1143 .uniqueid2 = args_other_channel_id,
1144 };
1145 struct ari_origination *origination;
1146 pthread_t thread;
1147 struct ast_format_cap *format_cap = NULL;
1148
1149 if ((assignedids.uniqueid && AST_MAX_PUBLIC_UNIQUEID < strlen(assignedids.uniqueid))
1150 || (assignedids.uniqueid2 && AST_MAX_PUBLIC_UNIQUEID < strlen(assignedids.uniqueid2))) {
1151 ast_ari_response_error(response, 400, "Bad Request",
1152 "Uniqueid length exceeds maximum of %d", AST_MAX_PUBLIC_UNIQUEID);
1153 return NULL;
1154 }
1155
1156 if (ast_strlen_zero(args_endpoint)) {
1157 ast_ari_response_error(response, 400, "Bad Request",
1158 "Endpoint must be specified");
1159 return NULL;
1160 }
1161
1162 if (!ast_strlen_zero(args_originator) && !ast_strlen_zero(args_formats)) {
1163 ast_ari_response_error(response, 400, "Bad Request",
1164 "Originator and formats can't both be specified");
1165 return NULL;
1166 }
1167
1168 dialtech = ast_strdupa(args_endpoint);
1169 if ((stuff = strchr(dialtech, '/'))) {
1170 *stuff++ = '\0';
1171 dialdevice = stuff;
1172 }
1173
1174 if (ast_strlen_zero(dialtech) || ast_strlen_zero(dialdevice)) {
1175 ast_ari_response_error(response, 400, "Bad Request",
1176 "Invalid endpoint specified");
1177 return NULL;
1178 }
1179
1180 if (!ast_strlen_zero(args_app)) {
1181 RAII_VAR(struct ast_str *, appdata, ast_str_create(64), ast_free);
1182
1183 if (!appdata) {
1185 return NULL;
1186 }
1187
1188 ast_str_set(&appdata, 0, "%s", args_app);
1189 if (!ast_strlen_zero(args_app_args)) {
1190 ast_str_append(&appdata, 0, ",%s", args_app_args);
1191 }
1192
1193 origination = ast_calloc(1, sizeof(*origination) + ast_str_size(appdata) + 1);
1194 if (!origination) {
1196 return NULL;
1197 }
1198
1199 strcpy(origination->appdata, ast_str_buffer(appdata));
1200 } else if (!ast_strlen_zero(args_extension)) {
1201 origination = ast_calloc(1, sizeof(*origination) + 1);
1202 if (!origination) {
1204 return NULL;
1205 }
1206
1207 ast_copy_string(origination->context, S_OR(args_context, "default"), sizeof(origination->context));
1208 ast_copy_string(origination->exten, args_extension, sizeof(origination->exten));
1209
1210 if (!ast_strlen_zero(args_label)) {
1211 /* A label was provided in the request, use that */
1212 int ipri = 1;
1213 if (sscanf(args_label, "%30d", &ipri) != 1) {
1214 ipri = ast_findlabel_extension(chan, origination->context, origination->exten, args_label, args_caller_id);
1215
1216 if (ipri == -1) {
1217 ast_log(AST_LOG_ERROR, "Requested label: %s can not be found in context: %s\n", args_label, args_context);
1218 ast_ari_response_error(response, 404, "Not Found", "Requested label can not be found");
1219 return NULL;
1220 }
1221 } else {
1222 ast_debug(3, "Numeric value provided for label, jumping to that priority\n");
1223 }
1224
1225 if (ipri == 0) {
1226 ast_log(AST_LOG_ERROR, "Invalid priority label '%s' specified for extension %s in context: %s\n",
1227 args_label, args_extension, args_context);
1228 ast_ari_response_error(response, 400, "Bad Request", "Requested priority is illegal");
1229 return NULL;
1230 }
1231
1232 /* Our priority was provided by a label */
1233 origination->priority = ipri;
1234 } else {
1235 /* No label provided, use provided priority */
1236 origination->priority = args_priority ? args_priority : 1;
1237 }
1238
1239 origination->appdata[0] = '\0';
1240 } else {
1241 ast_ari_response_error(response, 400, "Bad Request",
1242 "Application or extension must be specified");
1243 return NULL;
1244 }
1245
1246 dial = ast_dial_create();
1247 if (!dial) {
1249 ast_free(origination);
1250 return NULL;
1251 }
1252 ast_dial_set_user_data(dial, origination);
1253
1254 if (ast_dial_append(dial, dialtech, dialdevice, &assignedids)) {
1256 ast_dial_destroy(dial);
1257 ast_free(origination);
1258 return NULL;
1259 }
1260
1261 if (args_timeout > 0) {
1262 ast_dial_set_global_timeout(dial, args_timeout * 1000);
1263 } else if (args_timeout == -1) {
1265 } else {
1266 ast_dial_set_global_timeout(dial, 30000);
1267 }
1268
1269 if (!ast_strlen_zero(args_caller_id)) {
1270 caller_id = ast_strdupa(args_caller_id);
1271 ast_callerid_parse(caller_id, &cid_name, &cid_num);
1272
1273 if (ast_is_shrinkable_phonenumber(cid_num)) {
1274 ast_shrink_phone_number(cid_num);
1275 }
1276 }
1277
1278 if (!ast_strlen_zero(args_originator)) {
1279 other = ast_channel_get_by_name(args_originator);
1280 if (!other) {
1282 response, 400, "Bad Request",
1283 "Provided originator channel was not found");
1284 ast_dial_destroy(dial);
1285 ast_free(origination);
1286 return NULL;
1287 }
1288 }
1289
1290 if (!ast_strlen_zero(args_formats)) {
1291 char *format_name;
1292 char *formats_copy = ast_strdupa(args_formats);
1293
1296 ast_dial_destroy(dial);
1297 ast_free(origination);
1298 ast_channel_cleanup(other);
1299 return NULL;
1300 }
1301
1302 while ((format_name = ast_strip(strsep(&formats_copy, ",")))) {
1303 struct ast_format *fmt = ast_format_cache_get(format_name);
1304
1305 if (!fmt || ast_format_cap_append(format_cap, fmt, 0)) {
1306 if (!fmt) {
1308 response, 400, "Bad Request",
1309 "Provided format (%s) was not found", format_name);
1310 } else {
1312 }
1313 ast_dial_destroy(dial);
1314 ast_free(origination);
1315 ast_channel_cleanup(other);
1316 ao2_ref(format_cap, -1);
1317 ao2_cleanup(fmt);
1318 return NULL;
1319 }
1320 ao2_ref(fmt, -1);
1321 }
1322 }
1323
1324 if (ast_dial_prerun(dial, other, format_cap)) {
1326 ast_ari_response_error(response, 409, "Conflict",
1327 "Channel with given unique ID already exists");
1328 } else {
1330 }
1331 ast_dial_destroy(dial);
1332 ast_free(origination);
1333 ast_channel_cleanup(other);
1334 return NULL;
1335 }
1336
1337 ast_channel_cleanup(other);
1338 ao2_cleanup(format_cap);
1339
1340 chan = ast_dial_get_channel(dial, 0);
1341 if (!chan) {
1343 ast_dial_destroy(dial);
1344 ast_free(origination);
1345 return NULL;
1346 }
1347
1348 if (!ast_strlen_zero(cid_num) || !ast_strlen_zero(cid_name)) {
1350
1351 /*
1352 * It seems strange to set the CallerID on an outgoing call leg
1353 * to whom we are calling, but this function's callers are doing
1354 * various Originate methods. This call leg goes to the local
1355 * user. Once the called party answers, the dialplan needs to
1356 * be able to access the CallerID from the CALLERID function as
1357 * if the called party had placed this call.
1358 */
1359 ast_set_callerid(chan, cid_num, cid_name, cid_num);
1360
1362 if (!ast_strlen_zero(cid_num)) {
1363 connected.id.number.valid = 1;
1364 connected.id.number.str = (char *) cid_num;
1366 }
1367 if (!ast_strlen_zero(cid_name)) {
1368 connected.id.name.valid = 1;
1369 connected.id.name.str = (char *) cid_name;
1371 }
1373 }
1374
1375 if (variables) {
1376 ast_set_variables(chan, variables);
1377 }
1379
1380 if (!ast_strlen_zero(args_app)) {
1381 struct ast_channel *local_peer;
1382
1383 stasis_app_subscribe_channel(args_app, chan);
1384
1385 /* Subscribe to the Local channel peer also. */
1386 local_peer = ast_local_get_peer(chan);
1387 if (local_peer) {
1388 stasis_app_subscribe_channel(args_app, local_peer);
1389 ast_channel_unref(local_peer);
1390 }
1391 }
1392
1394
1395 /* Before starting the async dial bump the ref in case the dial quickly goes away and takes
1396 * the reference with it
1397 */
1398 ast_channel_ref(chan);
1399
1402 ast_dial_destroy(dial);
1403 ast_free(origination);
1404 } else {
1406 }
1407
1408 return chan;
1409}
pthread_t thread
Definition app_sla.c:335
void ast_ari_response_error(struct ast_ari_response *response, int response_code, const char *response_text, const char *message_fmt,...)
Fill in an error ast_ari_response.
Definition res_ari.c:212
void ast_ari_response_ok(struct ast_ari_response *response, struct ast_json *message)
Fill in an OK (200) ast_ari_response.
Definition res_ari.c:229
void ast_ari_response_alloc_failed(struct ast_ari_response *response)
Fill in response with a 500 message for allocation failures.
Definition res_ari.c:251
char * strsep(char **str, const char *delims)
#define ast_free(a)
Definition astmm.h:180
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition astmm.h:298
#define ast_calloc(num, len)
A wrapper for calloc()
Definition astmm.h:202
#define ao2_cleanup(obj)
Definition astobj2.h:1934
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition astobj2.h:459
int ast_callerid_parse(char *instr, char **name, char **location)
Destructively parse inbuf into name and location (or number)
Definition callerid.c:1162
void ast_shrink_phone_number(char *n)
Shrink a phone number in place to just digits (more accurately it just removes ()'s,...
Definition callerid.c:1101
int ast_is_shrinkable_phonenumber(const char *exten)
Check if a string consists only of digits and + # ( ) - . (meaning it can be cleaned with ast_shrink_...
Definition callerid.c:1157
#define AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED
Definition callerid.h:437
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:11033
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:8376
void ast_set_variables(struct ast_channel *chan, struct ast_variable *vars)
adds a list of channel variables to a channel
Definition channel.c:8183
struct ast_flags * ast_channel_flags(struct ast_channel *chan)
@ AST_CHANNEL_ERROR_ID_EXISTS
Definition channel.h:4916
#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)
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
@ AST_FLAG_ORIGINATED
Definition channel.h:1059
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:4216
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
#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_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, NULL, ari_origination::priority, RAII_VAR, S_OR, ast_channel::snapshot, stasis_app_subscribe_channel(), strsep(), thread, ast_assigned_ids::uniqueid, and ast_assigned_ids::uniqueid2.

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

◆ ari_channels_handle_play()

static void ari_channels_handle_play ( const char *  args_channel_id,
const char **  args_media,
size_t  args_media_count,
const char *  args_lang,
int  args_offsetms,
int  args_skipms,
const char *  args_playback_id,
struct ast_ari_response response 
)
static

Definition at line 657 of file resource_channels.c.

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

1630{
1631 enum stasis_app_snoop_direction spy, whisper;
1632 RAII_VAR(struct ast_channel *, chan, NULL, ast_channel_cleanup);
1633 RAII_VAR(struct ast_channel *, snoop, NULL, ast_channel_cleanup);
1634 RAII_VAR(struct ast_channel_snapshot *, snapshot, NULL, ao2_cleanup);
1635
1636 ast_assert(response != NULL);
1637
1638 if (ast_strlen_zero(args_spy) || !strcmp(args_spy, "none")) {
1640 } else if (!strcmp(args_spy, "both")) {
1642 } else if (!strcmp(args_spy, "out")) {
1644 } else if (!strcmp(args_spy, "in")) {
1646 } else {
1648 response, 400, "Bad Request",
1649 "Invalid direction specified for spy");
1650 return;
1651 }
1652
1653 if (ast_strlen_zero(args_whisper) || !strcmp(args_whisper, "none")) {
1655 } else if (!strcmp(args_whisper, "both")) {
1657 } else if (!strcmp(args_whisper, "out")) {
1659 } else if (!strcmp(args_whisper, "in")) {
1660 whisper = STASIS_SNOOP_DIRECTION_IN;
1661 } else {
1663 response, 400, "Bad Request",
1664 "Invalid direction specified for whisper");
1665 return;
1666 }
1667
1670 response, 400, "Bad Request",
1671 "Direction must be specified for at least spy or whisper");
1672 return;
1673 } else if (ast_strlen_zero(args_app)) {
1675 response, 400, "Bad Request",
1676 "Application name is required");
1677 return;
1678 }
1679
1680 chan = ast_channel_get_by_name(args_channel_id);
1681 if (chan == NULL) {
1683 response, 404, "Channel Not Found",
1684 "Provided channel was not found");
1685 return;
1686 }
1687
1688 snoop = stasis_app_control_snoop(chan, spy, whisper, args_app, args_app_args,
1689 args_snoop_id);
1690 if (snoop == NULL) {
1692 response, 500, "Internal error",
1693 "Snoop channel could not be created");
1694 return;
1695 }
1696
1699}
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:4791

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

1831{
1832 RAII_VAR(struct ast_variable *, variables, NULL, ast_variables_destroy);
1833 struct ast_assigned_ids assignedids;
1834 struct ari_channel_thread_data *chan_data;
1835 struct ast_channel_snapshot *snapshot;
1836 pthread_t thread;
1837 char *dialtech;
1838 char *dialdevice = NULL;
1839 char *stuff;
1840 int cause;
1841 struct ast_format_cap *request_cap;
1842 struct ast_channel *originator = NULL;
1843
1844 /* Parse any query parameters out of the body parameter */
1845 if (args->variables) {
1846 struct ast_json *json_variables;
1847
1849 json_variables = ast_json_object_get(args->variables, "variables");
1850 if (json_variables
1851 && json_to_ast_variables(response, json_variables, &variables)) {
1852 return;
1853 }
1854 }
1855
1856 assignedids.uniqueid = args->channel_id;
1857 assignedids.uniqueid2 = args->other_channel_id;
1858
1859 if (!ast_strlen_zero(args->originator) && !ast_strlen_zero(args->formats)) {
1860 ast_ari_response_error(response, 400, "Bad Request",
1861 "Originator and formats can't both be specified");
1862 return;
1863 }
1864
1865 if (ast_strlen_zero(args->endpoint)) {
1866 ast_ari_response_error(response, 400, "Bad Request",
1867 "Endpoint must be specified");
1868 return;
1869 }
1870
1871 chan_data = ast_calloc(1, sizeof(*chan_data));
1872 if (!chan_data) {
1874 return;
1875 }
1876
1877 chan_data->stasis_stuff = ast_str_create(32);
1878 if (!chan_data->stasis_stuff) {
1880 chan_data_destroy(chan_data);
1881 return;
1882 }
1883
1884 ast_str_append(&chan_data->stasis_stuff, 0, "%s", args->app);
1885 if (!ast_strlen_zero(args->app_args)) {
1886 ast_str_append(&chan_data->stasis_stuff, 0, ",%s", args->app_args);
1887 }
1888
1889 dialtech = ast_strdupa(args->endpoint);
1890 if ((stuff = strchr(dialtech, '/'))) {
1891 *stuff++ = '\0';
1892 dialdevice = stuff;
1893 }
1894
1895 if (ast_strlen_zero(dialtech) || ast_strlen_zero(dialdevice)) {
1896 ast_ari_response_error(response, 400, "Bad Request",
1897 "Invalid endpoint specified");
1898 chan_data_destroy(chan_data);
1899 return;
1900 }
1901
1902 if (!ast_strlen_zero(args->originator)) {
1903 originator = ast_channel_get_by_name(args->originator);
1904 }
1905
1906 if (originator) {
1907 request_cap = ao2_bump(ast_channel_nativeformats(originator));
1908 if (!ast_strlen_zero(args->app)) {
1909 stasis_app_subscribe_channel(args->app, originator);
1910 }
1911 } else if (!ast_strlen_zero(args->formats)) {
1912 char *format_name;
1913 char *formats_copy = ast_strdupa(args->formats);
1914
1915 if (!(request_cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
1917 chan_data_destroy(chan_data);
1918 return;
1919 }
1920
1921 while ((format_name = ast_strip(strsep(&formats_copy, ",")))) {
1922 struct ast_format *fmt = ast_format_cache_get(format_name);
1923
1924 if (!fmt || ast_format_cap_append(request_cap, fmt, 0)) {
1925 if (!fmt) {
1927 response, 400, "Bad Request",
1928 "Provided format (%s) was not found", format_name);
1929 } else {
1931 }
1932 ao2_ref(request_cap, -1);
1933 ao2_cleanup(fmt);
1934 chan_data_destroy(chan_data);
1935 return;
1936 }
1937 ao2_ref(fmt, -1);
1938 }
1939 } else {
1940 if (!(request_cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
1942 chan_data_destroy(chan_data);
1943 return;
1944 }
1945
1947 }
1948
1949 chan_data->chan = ast_request(dialtech, request_cap, &assignedids, originator, dialdevice, &cause);
1950 ao2_cleanup(request_cap);
1951
1952 if (!chan_data->chan) {
1954 ast_ari_response_error(response, 409, "Conflict",
1955 "Channel with given unique ID already exists");
1956 } else {
1958 }
1959 ast_channel_cleanup(originator);
1960 chan_data_destroy(chan_data);
1961 return;
1962 }
1963
1964 if (!ast_strlen_zero(args->app)) {
1965 stasis_app_subscribe_channel(args->app, chan_data->chan);
1966 }
1967
1968 if (variables) {
1969 ast_set_variables(chan_data->chan, variables);
1970 }
1971
1972 ast_channel_cleanup(originator);
1973
1974 if (save_dialstring(chan_data->chan, stuff)) {
1976 chan_data_destroy(chan_data);
1977 return;
1978 }
1979
1981
1984 chan_data_destroy(chan_data);
1985 } else {
1987 }
1988
1989 ao2_ref(snapshot, -1);
1990}
#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 int json_to_ast_variables(struct ast_ari_response *response, struct ast_json *json_variables, struct ast_variable **variables)
static void * ari_channel_thread(void *data)
Thread that owns stasis-created channel.
int ast_ari_channels_create_parse_body(struct ast_json *body, struct ast_ari_channels_create_args *args)
Body parsing function for /channels/create.
Structure for variables, used for configurations and for channel variables.

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

Referenced by ast_ari_channels_create_cb().

◆ ast_ari_channels_dial()

void ast_ari_channels_dial ( struct ast_variable headers,
struct ast_ari_channels_dial_args args,
struct ast_ari_response response 
)

Dial a created channel.

Parameters
headersHTTP headers
argsSwagger parameters
[out]responseHTTP response

Definition at line 1992 of file resource_channels.c.

1995{
1996 RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
1997 RAII_VAR(struct ast_channel *, caller, NULL, ast_channel_cleanup);
1998 RAII_VAR(struct ast_channel *, callee, NULL, ast_channel_cleanup);
1999 char *dialstring;
2000
2001 control = find_control(response, args->channel_id);
2002 if (control == NULL) {
2003 /* Response filled in by find_control */
2004 return;
2005 }
2006
2007 if (!ast_strlen_zero(args->caller)) {
2008 caller = ast_channel_get_by_name(args->caller);
2009 }
2010
2011 callee = ast_channel_get_by_name(args->channel_id);
2012 if (!callee) {
2013 ast_ari_response_error(response, 404, "Not Found",
2014 "Callee not found");
2015 return;
2016 }
2017
2018 if (ast_channel_state(callee) != AST_STATE_DOWN
2019 && ast_channel_state(callee) != AST_STATE_RESERVED) {
2020 ast_ari_response_error(response, 409, "Conflict",
2021 "Channel is not in the 'Down' state");
2022 return;
2023 }
2024
2025 /* XXX This is straight up copied from main/dial.c. It's probably good
2026 * to separate this to some common method.
2027 */
2028 if (caller) {
2029 ast_channel_lock_both(caller, callee);
2030 } else {
2031 ast_channel_lock(callee);
2032 }
2033
2034 dialstring = restore_dialstring(callee);
2035 if (!dialstring) {
2036 ast_channel_unlock(callee);
2037 if (caller) {
2038 ast_channel_unlock(caller);
2039 }
2040 ast_ari_response_error(response, 409, "Conflict",
2041 "Dialing a channel not created by ARI");
2042 return;
2043 }
2044 /* Make a copy of the dialstring just in case some jerk tries to hang up the
2045 * channel before we can actually dial
2046 */
2047 dialstring = ast_strdupa(dialstring);
2048
2050 if (caller) {
2051 ast_channel_inherit_variables(caller, callee);
2052 ast_channel_datastore_inherit(caller, callee);
2054
2055 /* Copy over callerid information */
2057
2059
2061
2062 ast_channel_language_set(callee, ast_channel_language(caller));
2065 ast_channel_musicclass_set(callee, ast_channel_musicclass(caller));
2066
2069 ast_channel_unlock(caller);
2070 }
2071
2073 ast_channel_unlock(callee);
2074
2075 if (stasis_app_control_dial(control, dialstring, args->timeout)) {
2077 return;
2078 }
2079
2081}
@ 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:8361
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:1718
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 2293 of file resource_channels.c.

2295{
2296 RAII_VAR(struct ast_variable *, variables, NULL, ast_variables_destroy);
2297 char *external_host;
2298 char *host = NULL;
2299 char *port = NULL;
2300
2301 ast_assert(response != NULL);
2302
2303 /* Parse any query parameters out of the body parameter */
2304 if (args->variables) {
2305 struct ast_json *json_variables;
2306
2308 json_variables = ast_json_object_get(args->variables, "variables");
2309 if (json_variables
2310 && json_to_ast_variables(response, json_variables, &variables)) {
2311 return;
2312 }
2313 }
2314
2315 if (ast_strlen_zero(args->app)) {
2316 ast_ari_response_error(response, 400, "Bad Request", "app cannot be empty");
2317 return;
2318 }
2319
2320 if (ast_strlen_zero(args->transport)) {
2321 args->transport = "udp";
2322 }
2323
2324 if (ast_strlen_zero(args->encapsulation)) {
2325 args->encapsulation = "rtp";
2326 }
2327 if (ast_strings_equal(args->transport, "websocket")) {
2328 if (!ast_strings_equal(args->encapsulation, "none")) {
2329 ast_ari_response_error(response, 400, "Bad Request", "encapsulation must be 'none' for websocket transport");
2330 return;
2331 }
2332 }
2333
2334 if (ast_strings_equal(args->encapsulation, "rtp")) {
2335 if (!ast_strings_equal(args->transport, "udp")) {
2336 ast_ari_response_error(response, 400, "Bad Request", "transport must be 'udp' for rtp encapsulation");
2337 return;
2338 }
2339 }
2340
2341 if (ast_strings_equal(args->encapsulation, "audiosocket")) {
2342 if (!ast_strings_equal(args->transport, "tcp")) {
2343 ast_ari_response_error(response, 400, "Bad Request", "transport must be 'tcp' for audiosocket encapsulation");
2344 return;
2345 }
2346 }
2347
2348 if (ast_strlen_zero(args->connection_type)) {
2349 args->connection_type = "client";
2350 }
2351 if (!ast_strings_equal(args->transport, "websocket")) {
2352 if (ast_strings_equal(args->connection_type, "server")) {
2353 ast_ari_response_error(response, 400, "Bad Request", "'server' connection_type can only be used with the websocket transport");
2354 return;
2355 }
2356 }
2357
2358 if (ast_strlen_zero(args->external_host)) {
2359 if (ast_strings_equal(args->connection_type, "client")) {
2360 ast_ari_response_error(response, 400, "Bad Request", "external_host is required for all but websocket server connections");
2361 return;
2362 } else {
2363 /* server is only valid for websocket, enforced above */
2364 args->external_host = "INCOMING";
2365 }
2366 }
2367
2368 if (ast_strings_equal(args->transport, "websocket")) {
2369 if (ast_strings_equal(args->connection_type, "client")) {
2370 struct ast_websocket_client *ws_client =
2372 ao2_cleanup(ws_client);
2373 if (!ws_client) {
2374 ast_ari_response_error(response, 400, "Bad Request", "external_host must be a valid websocket_client connection id.");
2375 return;
2376 }
2377 }
2378 } else {
2379 external_host = ast_strdupa(args->external_host);
2380 if (!ast_sockaddr_split_hostport(external_host, &host, &port, PARSE_PORT_REQUIRE)) {
2381 ast_ari_response_error(response, 400, "Bad Request", "external_host must be <host>:<port> for all transports other than websocket");
2382 return;
2383 }
2384 }
2385
2386 if (ast_strlen_zero(args->format)) {
2387 ast_ari_response_error(response, 400, "Bad Request", "format cannot be empty");
2388 return;
2389 }
2390
2391 if (!ast_strlen_zero(args->direction)) {
2392 if (strcmp(args->direction, "both") && strcmp(args->direction, "in")
2393 && strcmp(args->direction, "out")) {
2395 response, 400, "Bad Request",
2396 "Invalid direction specified");
2397 return;
2398 }
2399 }
2400
2401 if (strcasecmp(args->encapsulation, "rtp") == 0 && strcasecmp(args->transport, "udp") == 0) {
2402 if (external_media_rtp_udp(args, variables, response)) {
2404 response, 500, "Internal Server Error",
2405 "An internal error prevented this request from being handled");
2406 }
2407 } else if (strcasecmp(args->encapsulation, "audiosocket") == 0 && strcasecmp(args->transport, "tcp") == 0) {
2408 if (ast_strlen_zero(args->data)) {
2409 ast_ari_response_error(response, 400, "Bad Request", "data can not be empty");
2410 } else if (external_media_audiosocket_tcp(args, variables, response)) {
2412 response, 500, "Internal Server Error",
2413 "An internal error prevented this request from being handled");
2414 }
2415 } else if (strcasecmp(args->encapsulation, "none") == 0 && strcasecmp(args->transport, "websocket") == 0) {
2416 if (external_media_websocket(args, variables, response)) {
2418 response, 500, "Internal Server Error",
2419 "An internal error prevented this request from being handled");
2420 }
2421 } else {
2423 response, 501, "Not Implemented",
2424 "The encapsulation and/or transport is not supported");
2425 }
2426}
int ast_sockaddr_split_hostport(char *str, char **host, char **port, int flags)
Splits a string into its host and port components.
Definition netsock2.c:164
static int external_media_audiosocket_tcp(struct ast_ari_channels_external_media_args *args, struct ast_variable *variables, struct ast_ari_response *response)
static int external_media_websocket(struct ast_ari_channels_external_media_args *args, struct ast_variable *variables, struct ast_ari_response *response)
static int external_media_rtp_udp(struct ast_ari_channels_external_media_args *args, struct ast_variable *variables, struct ast_ari_response *response)
int ast_ari_channels_external_media_parse_body(struct ast_json *body, struct ast_ari_channels_external_media_args *args)
Body parsing function for /channels/externalMedia.
int ast_strings_equal(const char *str1, const char *str2)
Compare strings for equality checking for NULL.
Definition strings.c:238
struct ast_websocket_client * ast_websocket_client_retrieve_by_id(const char *id)
Retrieve a websocket client object by ID.

References ao2_cleanup, args, ast_ari_channels_external_media_parse_body(), ast_ari_response_error(), ast_assert, ast_json_object_get(), ast_sockaddr_split_hostport(), ast_strdupa, ast_strings_equal(), ast_strlen_zero(), ast_variables_destroy(), ast_websocket_client_retrieve_by_id(), external_media_audiosocket_tcp(), external_media_rtp_udp(), external_media_websocket(), json_to_ast_variables(), NULL, PARSE_PORT_REQUIRE, and RAII_VAR.

Referenced by ast_ari_channels_external_media_cb().

◆ ast_ari_channels_get()

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

Channel details.

Parameters
headersHTTP headers
argsSwagger parameters
[out]responseHTTP response

Definition at line 909 of file resource_channels.c.

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

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

Referenced by ast_ari_channels_get_cb().

◆ ast_ari_channels_get_channel_var()

void ast_ari_channels_get_channel_var ( struct ast_variable headers,
struct ast_ari_channels_get_channel_var_args args,
struct ast_ari_response response 
)

Get the value of a channel variable or function.

Parameters
headersHTTP headers
argsSwagger parameters
[out]responseHTTP response

Definition at line 1522 of file resource_channels.c.

1525{
1526 RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
1527 RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
1528 RAII_VAR(struct ast_str *, value, ast_str_create(32), ast_free);
1529 RAII_VAR(struct ast_channel *, channel, NULL, ast_channel_cleanup);
1530
1531 ast_assert(response != NULL);
1532
1533 if (!value) {
1535 return;
1536 }
1537
1538 if (ast_strlen_zero(args->variable)) {
1540 response, 400, "Bad Request",
1541 "Variable name is required");
1542 return;
1543 }
1544
1545 if (ast_strlen_zero(args->channel_id)) {
1547 response, 400, "Bad Request",
1548 "Channel ID is required");
1549 return;
1550 }
1551
1552 channel = ast_channel_get_by_name(args->channel_id);
1553 if (!channel) {
1555 response, 404, "Channel Not Found",
1556 "Provided channel was not found");
1557 return;
1558 }
1559
1560 /* You may be tempted to lock the channel you're about to read from. You
1561 * would be wrong. Some dialplan functions put the channel into
1562 * autoservice, which deadlocks if the channel is already locked.
1563 * ast_str_retrieve_variable() does its own locking, and the dialplan
1564 * functions need to as well. We should be fine without the lock.
1565 */
1566
1567 if (args->variable[strlen(args->variable) - 1] == ')') {
1568 if (ast_func_read2(channel, args->variable, &value, 0)) {
1570 response, 500, "Error With Function",
1571 "Unable to read provided function");
1572 return;
1573 }
1574 } else {
1575 if (!ast_str_retrieve_variable(&value, 0, channel, NULL, args->variable)) {
1577 response, 404, "Variable Not Found",
1578 "Provided variable was not found");
1579 return;
1580 }
1581 }
1582
1583 if (!(json = ast_json_pack("{s: s}", "value", S_OR(ast_str_buffer(value), "")))) {
1585 return;
1586 }
1587
1588 ast_ari_response_ok(response, ast_json_ref(json));
1589}
void ast_json_unref(struct ast_json *value)
Decrease refcount on value. If refcount reaches zero, value is freed.
Definition json.c:73
struct ast_json * ast_json_pack(char const *format,...)
Helper for creating complex JSON values.
Definition json.c:612
struct ast_json * ast_json_ref(struct ast_json *value)
Increase refcount on value.
Definition json.c:67
int ast_func_read2(struct ast_channel *chan, const char *function, struct ast_str **str, ssize_t maxlen)
executes a read operation on a function
const char * ast_str_retrieve_variable(struct ast_str **buf, ssize_t maxlen, struct ast_channel *chan, struct varshead *headp, const char *var)
int value
Definition syslog.c:37

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

Referenced by ast_ari_channels_get_channel_var_cb().

◆ ast_ari_channels_hangup()

void ast_ari_channels_hangup ( struct ast_variable headers,
struct ast_ari_channels_hangup_args args,
struct ast_ari_response response 
)

Delete (i.e. hangup) a channel.

Parameters
headersHTTP headers
argsSwagger parameters
[out]responseHTTP response

Definition at line 928 of file resource_channels.c.

931{
932 RAII_VAR(struct ast_channel *, chan, NULL, ao2_cleanup);
933 int cause;
934 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
@ AST_SOFTHANGUP_EXPLICIT
Definition channel.h:1168
int ast_softhangup(struct ast_channel *chan, int cause)
Softly hangup up a channel.
Definition channel.c:2462
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:789

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

Referenced by ast_ari_channels_hold_cb().

◆ ast_ari_channels_list()

void ast_ari_channels_list ( struct ast_variable headers,
struct ast_ari_channels_list_args args,
struct ast_ari_response response 
)

List all active channels in Asterisk.

Parameters
headersHTTP headers
argsSwagger parameters
[out]responseHTTP response

Definition at line 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:4831
#define AST_MUTE_DIRECTION_WRITE
Definition channel.h:4832
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 1483 of file resource_channels.c.

1486{
1487 struct ast_variable *variables = NULL;
1488 struct ast_channel *chan;
1489
1490 /* Parse any query parameters out of the body parameter */
1491 if (args->variables) {
1492 struct ast_json *json_variables;
1493
1495 json_variables = ast_json_object_get(args->variables, "variables");
1496 if (json_variables
1497 && json_to_ast_variables(response, json_variables, &variables)) {
1498 return;
1499 }
1500 }
1501
1503 args->endpoint,
1504 args->extension,
1505 args->context,
1506 args->priority,
1507 args->label,
1508 args->app,
1509 args->app_args,
1510 args->caller_id,
1511 args->timeout,
1512 variables,
1513 args->channel_id,
1514 args->other_channel_id,
1515 args->originator,
1516 args->formats,
1517 response);
1518 ast_channel_cleanup(chan);
1519 ast_variables_destroy(variables);
1520}
static struct ast_channel * ari_channels_handle_originate_with_id(const char *args_endpoint, const char *args_extension, const char *args_context, long args_priority, const char *args_label, const char *args_app, const char *args_app_args, const char *args_caller_id, int args_timeout, struct ast_variable *variables, const char *args_channel_id, const char *args_other_channel_id, const char *args_originator, const char *args_formats, struct ast_ari_response *response)
int ast_ari_channels_originate_parse_body(struct ast_json *body, struct ast_ari_channels_originate_args *args)
Body parsing function for /channels.

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

Referenced by ast_ari_channels_originate_cb().

◆ ast_ari_channels_originate_with_id()

void ast_ari_channels_originate_with_id ( struct ast_variable headers,
struct ast_ari_channels_originate_with_id_args args,
struct ast_ari_response response 
)

Create a new channel (originate with id).

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

Parameters
headersHTTP headers
argsSwagger parameters
[out]responseHTTP response

Definition at line 1444 of file resource_channels.c.

1447{
1448 struct ast_variable *variables = NULL;
1449 struct ast_channel *chan;
1450
1451 /* Parse any query parameters out of the body parameter */
1452 if (args->variables) {
1453 struct ast_json *json_variables;
1454
1456 json_variables = ast_json_object_get(args->variables, "variables");
1457 if (json_variables
1458 && json_to_ast_variables(response, json_variables, &variables)) {
1459 return;
1460 }
1461 }
1462
1464 args->endpoint,
1465 args->extension,
1466 args->context,
1467 args->priority,
1468 args->label,
1469 args->app,
1470 args->app_args,
1471 args->caller_id,
1472 args->timeout,
1473 variables,
1474 args->channel_id,
1475 args->other_channel_id,
1476 args->originator,
1477 args->formats,
1478 response);
1479 ast_channel_cleanup(chan);
1480 ast_variables_destroy(variables);
1481}
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 2083 of file resource_channels.c.

2086{
2087 RAII_VAR(struct ast_channel *, chan, NULL, ast_channel_cleanup);
2088 RAII_VAR(struct ast_rtp_instance *, rtp, NULL, ao2_cleanup);
2089 struct ast_json *j_res;
2090 const struct ast_channel_tech *tech;
2091 struct ast_rtp_glue *glue;
2092
2093 chan = ast_channel_get_by_name(args->channel_id);
2094 if (!chan) {
2095 ast_ari_response_error(response, 404, "Not Found",
2096 "Channel not found");
2097 return;
2098 }
2099
2100 ast_channel_lock(chan);
2101 tech = ast_channel_tech(chan);
2102 if (!tech) {
2103 ast_channel_unlock(chan);
2104 ast_ari_response_error(response, 404, "Not Found",
2105 "Channel's tech not found");
2106 return;
2107 }
2108
2109 glue = ast_rtp_instance_get_glue(tech->type);
2110 if (!glue) {
2111 ast_channel_unlock(chan);
2112 ast_ari_response_error(response, 403, "Forbidden",
2113 "Unsupported channel type");
2114 return;
2115 }
2116
2117 glue->get_rtp_info(chan, &rtp);
2118 if (!rtp) {
2119 ast_channel_unlock(chan);
2120 ast_ari_response_error(response, 404, "Not Found",
2121 "RTP info not found");
2122 return;
2123 }
2124
2126 if (!j_res) {
2127 ast_channel_unlock(chan);
2128 ast_ari_response_error(response, 404, "Not Found",
2129 "Statistics not found");
2130 return;
2131 }
2132
2133 ast_channel_unlock(chan);
2134 ast_ari_response_ok(response, j_res);
2135
2136 return;
2137}
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 1591 of file resource_channels.c.

1594{
1595 RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
1596
1597 ast_assert(response != NULL);
1598
1599 if (ast_strlen_zero(args->variable)) {
1601 response, 400, "Bad Request",
1602 "Variable name is required");
1603 return;
1604 }
1605
1606 control = find_control(response, args->channel_id);
1607 if (control == NULL) {
1608 /* response filled in by find_control */
1609 return;
1610 }
1611
1612 if (stasis_app_control_set_channel_var(control, args->variable, args->value)) {
1614 response, 400, "Bad Request",
1615 "Failed to execute function");
1616 return;
1617 }
1618
1620}
int stasis_app_control_set_channel_var(struct stasis_app_control *control, const char *variable, const char *value)
Set a variable on the channel associated with this control to value.
Definition control.c:752

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

Referenced by ast_ari_channels_set_channel_var_cb().

◆ ast_ari_channels_snoop_channel()

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

Start snooping.

Snoop (spy/whisper) on a specific channel.

Parameters
headersHTTP headers
argsSwagger parameters
[out]responseHTTP response

Definition at line 1701 of file resource_channels.c.

1704{
1706 args->channel_id,
1707 args->spy,
1708 args->whisper,
1709 args->app,
1710 args->app_args,
1711 args->snoop_id,
1712 response);
1713}
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 1715 of file resource_channels.c.

1718{
1720 args->channel_id,
1721 args->spy,
1722 args->whisper,
1723 args->app,
1724 args->app_args,
1725 args->snoop_id,
1726 response);
1727}

References args, and ari_channels_handle_snoop_channel().

Referenced by ast_ari_channels_snoop_channel_with_id_cb().

◆ ast_ari_channels_start_moh()

void ast_ari_channels_start_moh ( struct ast_variable headers,
struct ast_ari_channels_start_moh_args args,
struct ast_ari_response response 
)

Play music on hold to a channel.

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

Parameters
headersHTTP headers
argsSwagger parameters
[out]responseHTTP response

Definition at line 577 of file resource_channels.c.

580{
581 RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
582
583 control = find_control(response, args->channel_id);
584 if (control == NULL) {
585 /* Response filled in by find_control */
586 return;
587 }
588
589 if (channel_state_invalid(control, response)) {
590 return;
591 }
592
593 stasis_app_control_moh_start(control, args->moh_class);
595}
void stasis_app_control_moh_start(struct stasis_app_control *control, const char *moh_class)
Play music on hold to a channel (does not affect hold status)
Definition control.c:821

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

Referenced by ast_ari_channels_start_moh_cb().

◆ ast_ari_channels_start_silence()

void ast_ari_channels_start_silence ( struct ast_variable headers,
struct ast_ari_channels_start_silence_args args,
struct ast_ari_response response 
)

Play silence to a channel.

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

Parameters
headersHTTP headers
argsSwagger parameters
[out]responseHTTP response

Definition at line 617 of file resource_channels.c.

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

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

Referenced by ast_ari_channels_start_silence_cb().

◆ ast_ari_channels_stop_moh()

void ast_ari_channels_stop_moh ( struct ast_variable headers,
struct ast_ari_channels_stop_moh_args args,
struct ast_ari_response response 
)

Stop playing music on hold to a channel.

Parameters
headersHTTP headers
argsSwagger parameters
[out]responseHTTP response

Definition at line 597 of file resource_channels.c.

600{
601 RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
602
603 control = find_control(response, args->channel_id);
604 if (control == NULL) {
605 /* Response filled in by find_control */
606 return;
607 }
608
609 if (channel_state_invalid(control, response)) {
610 return;
611 }
612
615}
void stasis_app_control_moh_stop(struct stasis_app_control *control)
Stop playing music on hold to a channel (does not affect hold status)
Definition control.c:839

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

Referenced by ast_ari_channels_stop_moh_cb().

◆ ast_ari_channels_stop_silence()

void ast_ari_channels_stop_silence ( struct ast_variable headers,
struct ast_ari_channels_stop_silence_args args,
struct ast_ari_response response 
)

Stop playing silence to a channel.

Parameters
headersHTTP headers
argsSwagger parameters
[out]responseHTTP response

Definition at line 637 of file resource_channels.c.

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

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

Referenced by ast_ari_channels_stop_silence_cb().

◆ ast_ari_channels_transfer_progress()

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

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

Parameters
headersHTTP headers
argsSwagger parameters
[out]responseHTTP response

Definition at line 2428 of file resource_channels.c.

2429{
2431 RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
2432 RAII_VAR(struct ast_channel *, chan, NULL, ast_channel_cleanup);
2433
2434 control = find_control(response, args->channel_id);
2435 if (control == NULL) {
2436 /* Response filled in by find_control */
2437 return;
2438 }
2439
2440 chan = ast_channel_get_by_name(args->channel_id);
2441 if (!chan) {
2442 ast_ari_response_error(response, 404, "Not Found",
2443 "Callee not found");
2444 return;
2445 }
2446
2447 if (ast_strlen_zero(args->states)) {
2448 ast_ari_response_error(response, 400, "Bad Request", "states must not be empty");
2449 return;
2450 }
2451
2452 if (strcasecmp(args->states, "channel_progress") == 0) {
2454 } else if (strcasecmp(args->states, "channel_answered") == 0) {
2456 } else if (strcasecmp(args->states, "channel_unavailable") == 0) {
2458 } else if (strcasecmp(args->states, "channel_declined") == 0) {
2460 } else {
2461 ast_ari_response_error(response, 400, "Bad Request", "Invalid states value");
2462 return;
2463 }
2464
2467}
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:802

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

Referenced by ast_ari_channels_unhold_cb().

◆ ast_ari_channels_unmute()

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

Unmute a channel.

Parameters
headersHTTP headers
argsSwagger parameters
[out]responseHTTP response

Definition at line 466 of file resource_channels.c.

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

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

Referenced by ast_ari_channels_unmute_cb().

◆ chan_data_destroy()

static void chan_data_destroy ( struct ari_channel_thread_data chan_data)
static

Definition at line 1734 of file resource_channels.c.

1735{
1736 ast_free(chan_data->stasis_stuff);
1737 ast_hangup(chan_data->chan);
1738 ast_free(chan_data);
1739}
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_ari_response response 
)
static

Definition at line 2186 of file resource_channels.c.

2189{
2190 char *endpoint;
2191 struct ast_channel *chan;
2192 struct varshead *vars;
2193
2194 if (ast_asprintf(&endpoint, "AudioSocket/%s/%s",
2195 args->external_host, args->data) == -1) {
2196 return 1;
2197 }
2198
2200 endpoint,
2201 NULL,
2202 NULL,
2203 0,
2204 NULL,
2205 args->app,
2206 args->data,
2207 NULL,
2208 0,
2209 variables,
2210 args->channel_id,
2211 NULL,
2212 NULL,
2213 args->format,
2214 response);
2215
2216 ast_free(endpoint);
2217
2218 if (!chan) {
2219 return 1;
2220 }
2221
2222 ast_channel_lock(chan);
2223 vars = ast_channel_varshead(chan);
2224 if (vars && !AST_LIST_EMPTY(vars)) {
2225 ast_json_object_set(response->message, "channelvars", ast_json_channel_vars(vars));
2226 }
2227 ast_channel_unlock(chan);
2228 ast_channel_unref(chan);
2229 return 0;
2230}
struct varshead * ast_channel_varshead(struct ast_channel *chan)
int ast_json_object_set(struct ast_json *object, const char *key, struct ast_json *value)
Set a field in a JSON object.
Definition json.c:414
struct ast_json * ast_json_channel_vars(struct varshead *channelvars)
Construct a JSON object from a ast_var_t list.
Definition json.c:941
#define AST_LIST_EMPTY(head)
Checks whether the specified list contains any entries.
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_ari_response response 
)
static

Definition at line 2139 of file resource_channels.c.

2142{
2143 char *endpoint;
2144 struct ast_channel *chan;
2145 struct varshead *vars;
2146
2147 if (ast_asprintf(&endpoint, "UnicastRTP/%s/c(%s)",
2148 args->external_host,
2149 args->format) == -1) {
2150 return 1;
2151 }
2152
2154 endpoint,
2155 NULL,
2156 NULL,
2157 0,
2158 NULL,
2159 args->app,
2160 args->data,
2161 NULL,
2162 0,
2163 variables,
2164 args->channel_id,
2165 NULL,
2166 NULL,
2167 args->format,
2168 response);
2169
2170 ast_free(endpoint);
2171
2172 if (!chan) {
2173 return 1;
2174 }
2175
2176 ast_channel_lock(chan);
2177 vars = ast_channel_varshead(chan);
2178 if (vars && !AST_LIST_EMPTY(vars)) {
2179 ast_json_object_set(response->message, "channelvars", ast_json_channel_vars(vars));
2180 }
2181 ast_channel_unlock(chan);
2182 ast_channel_unref(chan);
2183 return 0;
2184}

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

Referenced by ast_ari_channels_external_media().

◆ external_media_websocket()

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

Definition at line 2232 of file resource_channels.c.

2235{
2236 char *endpoint;
2237 struct ast_channel *chan;
2238 struct varshead *vars;
2239 char direction[16] = "";
2240
2241 /* If direction is set here, it WILL override any m() line in transport data
2242 * since it is appended to the end of the string.
2243 */
2244 if (args->direction) {
2245 snprintf(direction, sizeof(direction), "d(%s)", args->direction);
2246 }
2247
2248 if (ast_asprintf(&endpoint, "WebSocket/%s%s%s%s%s",
2249 args->external_host,
2250 S_COR(args->transport_data, "/", ""),
2251 S_OR(args->transport_data, ""),
2252 S_COR(!args->transport_data && args->direction, "/", ""),
2253 direction) == -1) {
2254 return 1;
2255 }
2256
2258 endpoint,
2259 NULL,
2260 NULL,
2261 0,
2262 NULL,
2263 args->app,
2264 args->data,
2265 NULL,
2266 0,
2267 variables,
2268 args->channel_id,
2269 NULL,
2270 NULL,
2271 args->format,
2272 response);
2273
2274 ast_free(endpoint);
2275
2276 if (!chan) {
2277 return 1;
2278 }
2279
2280 ast_channel_lock(chan);
2281 vars = ast_channel_varshead(chan);
2282 if (vars && !AST_LIST_EMPTY(vars)) {
2283 ast_json_object_set(response->message, "channelvars", ast_json_channel_vars(vars));
2284 }
2285 ast_channel_unlock(chan);
2286 ast_channel_unref(chan);
2287 return 0;
2288}
#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_start_moh(), ast_ari_channels_start_silence(), ast_ari_channels_stop_moh(), ast_ari_channels_stop_silence(), ast_ari_channels_transfer_progress(), ast_ari_channels_unhold(), and ast_ari_channels_unmute().

◆ json_to_ast_variables()

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

Definition at line 1423 of file resource_channels.c.

1424{
1426
1427 res = ast_json_to_ast_variables(json_variables, variables);
1428 switch (res) {
1430 return 0;
1432 ast_ari_response_error(response, 400, "Bad Request",
1433 "Only string values in the 'variables' object allowed");
1434 break;
1437 break;
1438 }
1439 ast_log(AST_LOG_ERROR, "Unable to convert 'variables' in JSON body to channel variables\n");
1440
1441 return -1;
1442}
ast_json_to_ast_vars_code
Definition json.h:1109
@ AST_JSON_TO_AST_VARS_CODE_INVALID_TYPE
Conversion failed because invalid value type supplied.
Definition json.h:1116
@ AST_JSON_TO_AST_VARS_CODE_SUCCESS
Conversion successful.
Definition json.h:1111
@ AST_JSON_TO_AST_VARS_CODE_OOM
Conversion failed because of allocation failure. (Out Of Memory)
Definition json.h:1118
enum ast_json_to_ast_vars_code ast_json_to_ast_variables(struct ast_json *json_variables, struct ast_variable **variables)
Convert a ast_json list of key/value pair tuples into a ast_variable list.
Definition json.c:818

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

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

◆ restore_dialstring()

static char * restore_dialstring ( struct ast_channel chan)
static

Retrieve the dialstring from the channel datastore.

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

Definition at line 1816 of file resource_channels.c.

1817{
1818 struct ast_datastore *datastore;
1819
1820 datastore = ast_channel_datastore_find(chan, &dialstring_info, NULL);
1821 if (!datastore) {
1822 return NULL;
1823 }
1824
1825 return datastore->data;
1826}
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 1782 of file resource_channels.c.

1783{
1784 struct ast_datastore *datastore;
1785
1787 if (!datastore) {
1788 return -1;
1789 }
1790
1791 datastore->data = ast_strdup(dialstring);
1792 if (!datastore->data) {
1793 ast_datastore_free(datastore);
1794 return -1;
1795 }
1796
1797 ast_channel_lock(chan);
1798 if (ast_channel_datastore_add(chan, datastore)) {
1799 ast_channel_unlock(chan);
1800 ast_datastore_free(datastore);
1801 return -1;
1802 }
1803 ast_channel_unlock(chan);
1804
1805 return 0;
1806}
#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 1767 of file resource_channels.c.

1767 {
1768 .type = "ARI Dialstring",
1769 .destroy = ast_free_ptr,
1770};

Referenced by restore_dialstring(), and save_dialstring().