Asterisk - The Open Source Telephony Project GIT-master-8ef3e4f
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros Modules Pages
Data Structures | Functions | Variables
resource_channels.c File Reference

Implementation for ARI stubs. More...

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

Go to the source code of this file.

Data Structures

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

Functions

static void * ari_channel_thread (void *data)
 Thread that owns stasis-created channel. More...
 
static struct ast_channelari_channels_handle_originate_with_id (const char *args_endpoint, const char *args_extension, const char *args_context, long args_priority, const char *args_label, const char *args_app, const char *args_app_args, const char *args_caller_id, int args_timeout, struct ast_variable *variables, const char *args_channel_id, const char *args_other_channel_id, const char *args_originator, const char *args_formats, struct ast_ari_response *response)
 
static void ari_channels_handle_play (const char *args_channel_id, const char **args_media, size_t args_media_count, const char *args_lang, int args_offsetms, int args_skipms, const char *args_playback_id, struct ast_ari_response *response)
 
static void ari_channels_handle_snoop_channel (const char *args_channel_id, const char *args_spy, const char *args_whisper, const char *args_app, const char *args_app_args, const char *args_snoop_id, struct ast_ari_response *response)
 
static void * ari_originate_dial (void *data)
 Thread which dials and executes upon answer. More...
 
void ast_ari_channels_answer (struct ast_variable *headers, struct ast_ari_channels_answer_args *args, struct ast_ari_response *response)
 Answer a channel. More...
 
void ast_ari_channels_continue_in_dialplan (struct ast_variable *headers, struct ast_ari_channels_continue_in_dialplan_args *args, struct ast_ari_response *response)
 Exit application; continue execution in the dialplan. More...
 
void ast_ari_channels_create (struct ast_variable *headers, struct ast_ari_channels_create_args *args, struct ast_ari_response *response)
 Create channel. More...
 
void ast_ari_channels_dial (struct ast_variable *headers, struct ast_ari_channels_dial_args *args, struct ast_ari_response *response)
 Dial a created channel. More...
 
void ast_ari_channels_external_media (struct ast_variable *headers, struct ast_ari_channels_external_media_args *args, struct ast_ari_response *response)
 Start an External Media session. More...
 
void ast_ari_channels_get (struct ast_variable *headers, struct ast_ari_channels_get_args *args, struct ast_ari_response *response)
 Channel details. More...
 
void ast_ari_channels_get_channel_var (struct ast_variable *headers, struct ast_ari_channels_get_channel_var_args *args, struct ast_ari_response *response)
 Get the value of a channel variable or function. More...
 
void ast_ari_channels_hangup (struct ast_variable *headers, struct ast_ari_channels_hangup_args *args, struct ast_ari_response *response)
 Delete (i.e. hangup) a channel. More...
 
void ast_ari_channels_hold (struct ast_variable *headers, struct ast_ari_channels_hold_args *args, struct ast_ari_response *response)
 Hold a channel. More...
 
void ast_ari_channels_list (struct ast_variable *headers, struct ast_ari_channels_list_args *args, struct ast_ari_response *response)
 List all active channels in Asterisk. More...
 
void ast_ari_channels_move (struct ast_variable *headers, struct ast_ari_channels_move_args *args, struct ast_ari_response *response)
 Move the channel from one Stasis application to another. More...
 
void ast_ari_channels_mute (struct ast_variable *headers, struct ast_ari_channels_mute_args *args, struct ast_ari_response *response)
 Mute a channel. More...
 
void ast_ari_channels_originate (struct ast_variable *headers, struct ast_ari_channels_originate_args *args, struct ast_ari_response *response)
 Create a new channel (originate). More...
 
void ast_ari_channels_originate_with_id (struct ast_variable *headers, struct ast_ari_channels_originate_with_id_args *args, struct ast_ari_response *response)
 Create a new channel (originate with id). More...
 
void ast_ari_channels_play (struct ast_variable *headers, struct ast_ari_channels_play_args *args, struct ast_ari_response *response)
 Start playback of media. More...
 
void ast_ari_channels_play_with_id (struct ast_variable *headers, struct ast_ari_channels_play_with_id_args *args, struct ast_ari_response *response)
 Start playback of media and specify the playbackId. More...
 
void ast_ari_channels_record (struct ast_variable *headers, struct ast_ari_channels_record_args *args, struct ast_ari_response *response)
 Start a recording. More...
 
void ast_ari_channels_redirect (struct ast_variable *headers, struct ast_ari_channels_redirect_args *args, struct ast_ari_response *response)
 Redirect the channel to a different location. More...
 
void ast_ari_channels_ring (struct ast_variable *headers, struct ast_ari_channels_ring_args *args, struct ast_ari_response *response)
 Indicate ringing to a channel. More...
 
void ast_ari_channels_ring_stop (struct ast_variable *headers, struct ast_ari_channels_ring_stop_args *args, struct ast_ari_response *response)
 Stop ringing indication on a channel if locally generated. More...
 
void ast_ari_channels_rtpstatistics (struct ast_variable *headers, struct ast_ari_channels_rtpstatistics_args *args, struct ast_ari_response *response)
 RTP stats on a channel. More...
 
void ast_ari_channels_send_dtmf (struct ast_variable *headers, struct ast_ari_channels_send_dtmf_args *args, struct ast_ari_response *response)
 Send provided DTMF to a given channel. More...
 
void ast_ari_channels_set_channel_var (struct ast_variable *headers, struct ast_ari_channels_set_channel_var_args *args, struct ast_ari_response *response)
 Set the value of a channel variable or function. More...
 
void ast_ari_channels_snoop_channel (struct ast_variable *headers, struct ast_ari_channels_snoop_channel_args *args, struct ast_ari_response *response)
 Start snooping. More...
 
void ast_ari_channels_snoop_channel_with_id (struct ast_variable *headers, struct ast_ari_channels_snoop_channel_with_id_args *args, struct ast_ari_response *response)
 Start snooping. More...
 
void ast_ari_channels_start_moh (struct ast_variable *headers, struct ast_ari_channels_start_moh_args *args, struct ast_ari_response *response)
 Play music on hold to a channel. More...
 
void ast_ari_channels_start_silence (struct ast_variable *headers, struct ast_ari_channels_start_silence_args *args, struct ast_ari_response *response)
 Play silence to a channel. More...
 
void ast_ari_channels_stop_moh (struct ast_variable *headers, struct ast_ari_channels_stop_moh_args *args, struct ast_ari_response *response)
 Stop playing music on hold to a channel. More...
 
void ast_ari_channels_stop_silence (struct ast_variable *headers, struct ast_ari_channels_stop_silence_args *args, struct ast_ari_response *response)
 Stop playing silence to a channel. More...
 
void ast_ari_channels_transfer_progress (struct ast_variable *headers, struct ast_ari_channels_transfer_progress_args *args, struct ast_ari_response *response)
 Inform the channel about the progress of the attended/blind transfer. More...
 
void ast_ari_channels_unhold (struct ast_variable *headers, struct ast_ari_channels_unhold_args *args, struct ast_ari_response *response)
 Remove a channel from hold. More...
 
void ast_ari_channels_unmute (struct ast_variable *headers, struct ast_ari_channels_unmute_args *args, struct ast_ari_response *response)
 Unmute a channel. More...
 
static void chan_data_destroy (struct ari_channel_thread_data *chan_data)
 
static int channel_state_invalid (struct stasis_app_control *control, struct ast_ari_response *response)
 Ensure channel is in a state that allows operation to be performed. More...
 
static int convert_reason_to_hangup_code (const char *reason)
 Return the corresponded hangup code of the given reason. More...
 
static int external_media_audiosocket_tcp (struct ast_ari_channels_external_media_args *args, struct ast_variable *variables, struct ast_ari_response *response)
 
static int external_media_rtp_udp (struct ast_ari_channels_external_media_args *args, struct ast_variable *variables, struct ast_ari_response *response)
 
static int external_media_websocket (struct ast_ari_channels_external_media_args *args, struct ast_variable *variables, struct ast_ari_response *response)
 
static struct stasis_app_controlfind_control (struct ast_ari_response *response, const char *channel_id)
 Finds the control object for a channel, filling the response with an error, if appropriate. More...
 
static int json_to_ast_variables (struct ast_ari_response *response, struct ast_json *json_variables, struct ast_variable **variables)
 
static char * restore_dialstring (struct ast_channel *chan)
 Retrieve the dialstring from the channel datastore. More...
 
static int save_dialstring (struct ast_channel *chan, const char *dialstring)
 Save dialstring onto a channel datastore. More...
 

Variables

struct ast_datastore_info dialstring_info
 

Detailed Description

Implementation for ARI stubs.

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

Definition in file resource_channels.c.

Function Documentation

◆ ari_channel_thread()

static void * ari_channel_thread ( void *  data)
static

Thread that owns stasis-created channel.

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

Definition at line 1699 of file resource_channels.c.

1700{
1701 struct ari_channel_thread_data *chan_data = data;
1702 struct ast_app *stasis_app;
1703
1704 stasis_app = pbx_findapp("Stasis");
1705 if (!stasis_app) {
1706 ast_log(LOG_ERROR, "Stasis dialplan application is not registered");
1707 chan_data_destroy(chan_data);
1708 return NULL;
1709 }
1710
1711 pbx_exec(chan_data->chan, stasis_app, ast_str_buffer(chan_data->stasis_stuff));
1712
1713 chan_data_destroy(chan_data);
1714
1715 return NULL;
1716}
#define ast_log
Definition: astobj2.c:42
#define LOG_ERROR
int pbx_exec(struct ast_channel *c, struct ast_app *app, const char *data)
Execute an application.
Definition: pbx_app.c:471
struct ast_app * pbx_findapp(const char *app)
Look up an application.
Definition: ael_main.c:165
#define NULL
Definition: resample.c:96
static void chan_data_destroy(struct ari_channel_thread_data *chan_data)
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:761
struct ast_str * stasis_stuff
struct ast_channel * chan
ast_app: A registered application
Definition: pbx_app.c:45

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

Referenced by ast_ari_channels_create().

◆ ari_channels_handle_originate_with_id()

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

Definition at line 1064 of file resource_channels.c.

1079{
1080 char *dialtech;
1081 char *dialdevice = NULL;
1082 struct ast_dial *dial;
1083 char *caller_id = NULL;
1084 char *cid_num = NULL;
1085 char *cid_name = NULL;
1086 char *stuff;
1087 struct ast_channel *other = NULL;
1088 struct ast_channel *chan = NULL;
1090 struct ast_assigned_ids assignedids = {
1091 .uniqueid = args_channel_id,
1092 .uniqueid2 = args_other_channel_id,
1093 };
1094 struct ari_origination *origination;
1095 pthread_t thread;
1096 struct ast_format_cap *format_cap = NULL;
1097
1098 if ((assignedids.uniqueid && AST_MAX_PUBLIC_UNIQUEID < strlen(assignedids.uniqueid))
1099 || (assignedids.uniqueid2 && AST_MAX_PUBLIC_UNIQUEID < strlen(assignedids.uniqueid2))) {
1100 ast_ari_response_error(response, 400, "Bad Request",
1101 "Uniqueid length exceeds maximum of %d", AST_MAX_PUBLIC_UNIQUEID);
1102 return NULL;
1103 }
1104
1105 if (ast_strlen_zero(args_endpoint)) {
1106 ast_ari_response_error(response, 400, "Bad Request",
1107 "Endpoint must be specified");
1108 return NULL;
1109 }
1110
1111 if (!ast_strlen_zero(args_originator) && !ast_strlen_zero(args_formats)) {
1112 ast_ari_response_error(response, 400, "Bad Request",
1113 "Originator and formats can't both be specified");
1114 return NULL;
1115 }
1116
1117 dialtech = ast_strdupa(args_endpoint);
1118 if ((stuff = strchr(dialtech, '/'))) {
1119 *stuff++ = '\0';
1120 dialdevice = stuff;
1121 }
1122
1123 if (ast_strlen_zero(dialtech) || ast_strlen_zero(dialdevice)) {
1124 ast_ari_response_error(response, 400, "Bad Request",
1125 "Invalid endpoint specified");
1126 return NULL;
1127 }
1128
1129 if (!ast_strlen_zero(args_app)) {
1130 RAII_VAR(struct ast_str *, appdata, ast_str_create(64), ast_free);
1131
1132 if (!appdata) {
1134 return NULL;
1135 }
1136
1137 ast_str_set(&appdata, 0, "%s", args_app);
1138 if (!ast_strlen_zero(args_app_args)) {
1139 ast_str_append(&appdata, 0, ",%s", args_app_args);
1140 }
1141
1142 origination = ast_calloc(1, sizeof(*origination) + ast_str_size(appdata) + 1);
1143 if (!origination) {
1145 return NULL;
1146 }
1147
1148 strcpy(origination->appdata, ast_str_buffer(appdata));
1149 } else if (!ast_strlen_zero(args_extension)) {
1150 origination = ast_calloc(1, sizeof(*origination) + 1);
1151 if (!origination) {
1153 return NULL;
1154 }
1155
1156 ast_copy_string(origination->context, S_OR(args_context, "default"), sizeof(origination->context));
1157 ast_copy_string(origination->exten, args_extension, sizeof(origination->exten));
1158
1159 if (!ast_strlen_zero(args_label)) {
1160 /* A label was provided in the request, use that */
1161 int ipri = 1;
1162 if (sscanf(args_label, "%30d", &ipri) != 1) {
1163 ipri = ast_findlabel_extension(chan, origination->context, origination->exten, args_label, args_caller_id);
1164
1165 if (ipri == -1) {
1166 ast_log(AST_LOG_ERROR, "Requested label: %s can not be found in context: %s\n", args_label, args_context);
1167 ast_ari_response_error(response, 404, "Not Found", "Requested label can not be found");
1168 return NULL;
1169 }
1170 } else {
1171 ast_debug(3, "Numeric value provided for label, jumping to that priority\n");
1172 }
1173
1174 if (ipri == 0) {
1175 ast_log(AST_LOG_ERROR, "Invalid priority label '%s' specified for extension %s in context: %s\n",
1176 args_label, args_extension, args_context);
1177 ast_ari_response_error(response, 400, "Bad Request", "Requested priority is illegal");
1178 return NULL;
1179 }
1180
1181 /* Our priority was provided by a label */
1182 origination->priority = ipri;
1183 } else {
1184 /* No label provided, use provided priority */
1185 origination->priority = args_priority ? args_priority : 1;
1186 }
1187
1188 origination->appdata[0] = '\0';
1189 } else {
1190 ast_ari_response_error(response, 400, "Bad Request",
1191 "Application or extension must be specified");
1192 return NULL;
1193 }
1194
1195 dial = ast_dial_create();
1196 if (!dial) {
1198 ast_free(origination);
1199 return NULL;
1200 }
1201 ast_dial_set_user_data(dial, origination);
1202
1203 if (ast_dial_append(dial, dialtech, dialdevice, &assignedids)) {
1205 ast_dial_destroy(dial);
1206 ast_free(origination);
1207 return NULL;
1208 }
1209
1210 if (args_timeout > 0) {
1211 ast_dial_set_global_timeout(dial, args_timeout * 1000);
1212 } else if (args_timeout == -1) {
1214 } else {
1215 ast_dial_set_global_timeout(dial, 30000);
1216 }
1217
1218 if (!ast_strlen_zero(args_caller_id)) {
1219 caller_id = ast_strdupa(args_caller_id);
1220 ast_callerid_parse(caller_id, &cid_name, &cid_num);
1221
1222 if (ast_is_shrinkable_phonenumber(cid_num)) {
1223 ast_shrink_phone_number(cid_num);
1224 }
1225 }
1226
1227 if (!ast_strlen_zero(args_originator)) {
1228 other = ast_channel_get_by_name(args_originator);
1229 if (!other) {
1231 response, 400, "Bad Request",
1232 "Provided originator channel was not found");
1233 ast_dial_destroy(dial);
1234 ast_free(origination);
1235 return NULL;
1236 }
1237 }
1238
1239 if (!ast_strlen_zero(args_formats)) {
1240 char *format_name;
1241 char *formats_copy = ast_strdupa(args_formats);
1242
1245 ast_dial_destroy(dial);
1246 ast_free(origination);
1247 ast_channel_cleanup(other);
1248 return NULL;
1249 }
1250
1251 while ((format_name = ast_strip(strsep(&formats_copy, ",")))) {
1252 struct ast_format *fmt = ast_format_cache_get(format_name);
1253
1254 if (!fmt || ast_format_cap_append(format_cap, fmt, 0)) {
1255 if (!fmt) {
1257 response, 400, "Bad Request",
1258 "Provided format (%s) was not found", format_name);
1259 } else {
1261 }
1262 ast_dial_destroy(dial);
1263 ast_free(origination);
1264 ast_channel_cleanup(other);
1265 ao2_ref(format_cap, -1);
1266 ao2_cleanup(fmt);
1267 return NULL;
1268 }
1269 ao2_ref(fmt, -1);
1270 }
1271 }
1272
1273 if (ast_dial_prerun(dial, other, format_cap)) {
1275 ast_ari_response_error(response, 409, "Conflict",
1276 "Channel with given unique ID already exists");
1277 } else {
1279 }
1280 ast_dial_destroy(dial);
1281 ast_free(origination);
1282 ast_channel_cleanup(other);
1283 return NULL;
1284 }
1285
1286 ast_channel_cleanup(other);
1287 ao2_cleanup(format_cap);
1288
1289 chan = ast_dial_get_channel(dial, 0);
1290 if (!chan) {
1292 ast_dial_destroy(dial);
1293 ast_free(origination);
1294 return NULL;
1295 }
1296
1297 if (!ast_strlen_zero(cid_num) || !ast_strlen_zero(cid_name)) {
1299
1300 /*
1301 * It seems strange to set the CallerID on an outgoing call leg
1302 * to whom we are calling, but this function's callers are doing
1303 * various Originate methods. This call leg goes to the local
1304 * user. Once the called party answers, the dialplan needs to
1305 * be able to access the CallerID from the CALLERID function as
1306 * if the called party had placed this call.
1307 */
1308 ast_set_callerid(chan, cid_num, cid_name, cid_num);
1309
1311 if (!ast_strlen_zero(cid_num)) {
1312 connected.id.number.valid = 1;
1313 connected.id.number.str = (char *) cid_num;
1315 }
1316 if (!ast_strlen_zero(cid_name)) {
1317 connected.id.name.valid = 1;
1318 connected.id.name.str = (char *) cid_name;
1320 }
1322 }
1323
1324 ast_channel_lock(chan);
1325 if (variables) {
1326 ast_set_variables(chan, variables);
1327 }
1329
1330 if (!ast_strlen_zero(args_app)) {
1331 struct ast_channel *local_peer;
1332
1333 stasis_app_subscribe_channel(args_app, chan);
1334
1335 /* Subscribe to the Local channel peer also. */
1336 local_peer = ast_local_get_peer(chan);
1337 if (local_peer) {
1338 stasis_app_subscribe_channel(args_app, local_peer);
1339 ast_channel_unref(local_peer);
1340 }
1341 }
1342
1344 ast_channel_unlock(chan);
1345
1346 /* Before starting the async dial bump the ref in case the dial quickly goes away and takes
1347 * the reference with it
1348 */
1349 ast_channel_ref(chan);
1350
1353 ast_dial_destroy(dial);
1354 ast_free(origination);
1355 } else {
1357 }
1358
1359 return chan;
1360}
pthread_t thread
Definition: app_sla.c:335
void ast_ari_response_error(struct ast_ari_response *response, int response_code, const char *response_text, const char *message_fmt,...)
Fill in an error ast_ari_response.
Definition: res_ari.c:212
void ast_ari_response_ok(struct ast_ari_response *response, struct ast_json *message)
Fill in an OK (200) ast_ari_response.
Definition: res_ari.c:229
void ast_ari_response_alloc_failed(struct ast_ari_response *response)
Fill in response with a 500 message for allocation failures.
Definition: res_ari.c:251
char * strsep(char **str, const char *delims)
#define ast_free(a)
Definition: astmm.h:180
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:298
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
#define ao2_cleanup(obj)
Definition: astobj2.h:1934
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
int ast_callerid_parse(char *instr, char **name, char **location)
Destructively parse inbuf into name and location (or number)
Definition: callerid.c:1162
void ast_shrink_phone_number(char *n)
Shrink a phone number in place to just digits (more accurately it just removes ()'s,...
Definition: callerid.c:1101
int ast_is_shrinkable_phonenumber(const char *exten)
Check if a string consists only of digits and + # ( ) - . (meaning it can be cleaned with ast_shrink_...
Definition: callerid.c:1157
#define AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED
Definition: callerid.h:437
#define AST_MAX_PUBLIC_UNIQUEID
Definition: channel.h:147
enum ast_channel_error ast_channel_errno(void)
Get error code for latest channel operation.
Definition: channel.c:10962
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:8309
#define ast_channel_lock(chan)
Definition: channel.h:2972
void ast_set_variables(struct ast_channel *chan, struct ast_variable *vars)
adds a list of channel variables to a channel
Definition: channel.c:8116
struct ast_flags * ast_channel_flags(struct ast_channel *chan)
@ AST_CHANNEL_ERROR_ID_EXISTS
Definition: channel.h:4875
#define ast_channel_ref(c)
Increase channel reference count.
Definition: channel.h:2997
struct ast_party_connected_line * ast_channel_connected(struct ast_channel *chan)
@ AST_FLAG_ORIGINATED
Definition: channel.h:1059
const char * ast_channel_uniqueid(const struct ast_channel *chan)
void ast_set_callerid(struct ast_channel *chan, const char *cid_num, const char *cid_name, const char *cid_ani)
Set caller ID number, name and ANI and generate AMI event.
Definition: channel.c:7303
struct ast_channel * ast_channel_get_by_name(const char *search)
Find a channel by name or uniqueid.
Definition: channel.c:1397
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:3008
void ast_party_connected_line_set_init(struct ast_party_connected_line *init, const struct ast_party_connected_line *guide)
Initialize the given connected line structure using the given guide for a set update operation.
Definition: channel.c:2012
#define ast_channel_cleanup(c)
Cleanup a channel reference.
Definition: channel.h:3019
#define ast_channel_unlock(chan)
Definition: channel.h:2973
struct ast_channel * ast_local_get_peer(struct ast_channel *ast)
Get the other local channel in the pair.
Definition: core_local.c:288
int ast_dial_append(struct ast_dial *dial, const char *tech, const char *device, const struct ast_assigned_ids *assignedids)
Append a channel.
Definition: dial.c:280
struct ast_dial * ast_dial_create(void)
New dialing structure.
Definition: dial.c:223
void ast_dial_set_user_data(struct ast_dial *dial, void *user_data)
Set user data on a dial structure.
Definition: dial.c:1274
int ast_dial_prerun(struct ast_dial *dial, struct ast_channel *chan, struct ast_format_cap *cap)
Request all appended channels, but do not dial.
Definition: dial.c:431
void ast_dial_set_global_timeout(struct ast_dial *dial, int timeout)
Set the maximum time (globally) allowed for trying to ring phones.
Definition: dial.c:1284
struct ast_channel * ast_dial_get_channel(struct ast_dial *dial, int num)
Get the dialing channel, if prerun has been executed.
Definition: dial.c:1258
int ast_dial_destroy(struct ast_dial *dial)
Destroys a dialing structure.
Definition: dial.c:1091
char connected
Definition: eagi_proxy.c:82
#define ast_format_cache_get(name)
Retrieve a named format from the cache.
Definition: format_cache.h:278
@ AST_FORMAT_CAP_FLAG_DEFAULT
Definition: format_cap.h:38
#define ast_format_cap_append(cap, format, framing)
Add format capability to capabilities structure.
Definition: format_cap.h:99
#define ast_format_cap_alloc(flags)
Allocate a new ast_format_cap structure.
Definition: format_cap.h:49
struct ast_channel_snapshot * ast_channel_snapshot_get_latest(const char *uniqueid)
Obtain the latest ast_channel_snapshot from the Stasis Message Bus API cache. This is an ao2 object,...
#define AST_LOG_ERROR
#define ast_debug(level,...)
Log a DEBUG message.
int ast_findlabel_extension(struct ast_channel *c, const char *context, const char *exten, const char *label, const char *callerid)
Find the priority of an extension that has the specified label.
Definition: pbx.c:4195
static void * ari_originate_dial(void *data)
Thread which dials and executes upon answer.
enum stasis_app_subscribe_res stasis_app_subscribe_channel(const char *app_name, struct ast_channel *chan)
Directly subscribe an application to a channel.
Definition: res_stasis.c:2063
struct ast_json * ast_channel_snapshot_to_json(const struct ast_channel_snapshot *snapshot, const struct stasis_message_sanitizer *sanitize)
Build a JSON object from a ast_channel_snapshot.
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
Definition: strings.h:1139
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one.
Definition: strings.h:80
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
Definition: strings.h:659
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
Definition: strings.h:1113
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:425
char * ast_strip(char *s)
Strip leading/trailing whitespace from a string.
Definition: strings.h:223
size_t ast_str_size(const struct ast_str *buf)
Returns the current maximum length (without reallocation) of the current buffer.
Definition: strings.h:742
Structure used for origination.
char appdata[0]
Application data to pass to Stasis application.
char exten[AST_MAX_EXTENSION]
Dialplan extension.
char context[AST_MAX_CONTEXT]
Dialplan context.
int priority
Dialplan priority.
Structure to pass both assignedid values to channel drivers.
Definition: channel.h:606
const char * uniqueid2
Definition: channel.h:608
const char * uniqueid
Definition: channel.h:607
Structure representing a snapshot of channel state.
Main Channel structure associated with a channel.
struct ast_channel_snapshot * snapshot
Main dialing structure. Contains global options, channels being dialed, and more!
Definition: dial.c:48
Format capabilities structure, holds formats + preference order + etc.
Definition: format_cap.c:54
Definition of a media format.
Definition: format.c:43
Connected Line/Party information.
Definition: channel.h:458
Support for dynamic strings.
Definition: strings.h:623
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:947
#define ast_pthread_create_detached(a, b, c, d)
Definition: utils.h:594
#define ast_set_flag(p, flag)
Definition: utils.h:70

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

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

◆ ari_channels_handle_play()

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

Definition at line 637 of file resource_channels.c.

646{
647 RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
648 RAII_VAR(struct ast_channel_snapshot *, snapshot, NULL, ao2_cleanup);
649 RAII_VAR(struct stasis_app_playback *, playback, NULL, ao2_cleanup);
650 RAII_VAR(char *, playback_url, NULL, ast_free);
651 struct ast_json *json;
652 const char *language;
653
654 ast_assert(response != NULL);
655
656 control = find_control(response, args_channel_id);
657 if (control == NULL) {
658 /* Response filled in by find_control */
659 return;
660 }
661
662 if (channel_state_invalid(control, response)) {
663 return;
664 }
665
666 snapshot = stasis_app_control_get_snapshot(control);
667 if (!snapshot) {
669 response, 404, "Not Found",
670 "Channel not found");
671 return;
672 }
673
674 if (args_skipms < 0) {
676 response, 400, "Bad Request",
677 "skipms cannot be negative");
678 return;
679 }
680
681 if (args_offsetms < 0) {
683 response, 400, "Bad Request",
684 "offsetms cannot be negative");
685 return;
686 }
687
688 language = S_OR(args_lang, snapshot->base->language);
689
690 playback = stasis_app_control_play_uri(control, args_media, args_media_count, language,
691 args_channel_id, STASIS_PLAYBACK_TARGET_CHANNEL, args_skipms, args_offsetms, args_playback_id);
692 if (!playback) {
694 response, 500, "Internal Server Error",
695 "Failed to queue media for playback");
696 return;
697 }
698
699 if (ast_asprintf(&playback_url, "/playbacks/%s",
700 stasis_app_playback_get_id(playback)) == -1) {
701 playback_url = NULL;
703 response, 500, "Internal Server Error",
704 "Out of memory");
705 return;
706 }
707
708 json = stasis_app_playback_to_json(playback);
709 if (!json) {
711 response, 500, "Internal Server Error",
712 "Out of memory");
713 return;
714 }
715
716 ast_ari_response_created(response, playback_url, json);
717}
void ast_ari_response_created(struct ast_ari_response *response, const char *url, struct ast_json *message)
Fill in a Created (201) ast_ari_response.
Definition: res_ari.c:258
#define ast_asprintf(ret, fmt,...)
A wrapper for asprintf()
Definition: astmm.h:267
static char language[MAX_LANGUAGE]
Definition: chan_iax2.c:348
static int channel_state_invalid(struct stasis_app_control *control, struct ast_ari_response *response)
Ensure channel is in a state that allows operation to be performed.
static struct stasis_app_control * find_control(struct ast_ari_response *response, const char *channel_id)
Finds the control object for a channel, filling the response with an error, if appropriate.
struct ast_channel_snapshot * stasis_app_control_get_snapshot(const struct stasis_app_control *control)
Returns the most recent snapshot for the associated channel.
Definition: control.c:886
@ 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:745

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

1581{
1582 enum stasis_app_snoop_direction spy, whisper;
1583 RAII_VAR(struct ast_channel *, chan, NULL, ast_channel_cleanup);
1584 RAII_VAR(struct ast_channel *, snoop, NULL, ast_channel_cleanup);
1585 RAII_VAR(struct ast_channel_snapshot *, snapshot, NULL, ao2_cleanup);
1586
1587 ast_assert(response != NULL);
1588
1589 if (ast_strlen_zero(args_spy) || !strcmp(args_spy, "none")) {
1591 } else if (!strcmp(args_spy, "both")) {
1593 } else if (!strcmp(args_spy, "out")) {
1595 } else if (!strcmp(args_spy, "in")) {
1597 } else {
1599 response, 400, "Bad Request",
1600 "Invalid direction specified for spy");
1601 return;
1602 }
1603
1604 if (ast_strlen_zero(args_whisper) || !strcmp(args_whisper, "none")) {
1606 } else if (!strcmp(args_whisper, "both")) {
1608 } else if (!strcmp(args_whisper, "out")) {
1610 } else if (!strcmp(args_whisper, "in")) {
1611 whisper = STASIS_SNOOP_DIRECTION_IN;
1612 } else {
1614 response, 400, "Bad Request",
1615 "Invalid direction specified for whisper");
1616 return;
1617 }
1618
1621 response, 400, "Bad Request",
1622 "Direction must be specified for at least spy or whisper");
1623 return;
1624 } else if (ast_strlen_zero(args_app)) {
1626 response, 400, "Bad Request",
1627 "Application name is required");
1628 return;
1629 }
1630
1631 chan = ast_channel_get_by_name(args_channel_id);
1632 if (chan == NULL) {
1634 response, 404, "Channel Not Found",
1635 "Provided channel was not found");
1636 return;
1637 }
1638
1639 snoop = stasis_app_control_snoop(chan, spy, whisper, args_app, args_app_args,
1640 args_snoop_id);
1641 if (snoop == NULL) {
1643 response, 500, "Internal error",
1644 "Snoop channel could not be created");
1645 return;
1646 }
1647
1650}
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 1014 of file resource_channels.c.

1015{
1016 struct ast_dial *dial = data;
1017 struct ari_origination *origination = ast_dial_get_user_data(dial);
1018 enum ast_dial_result res;
1019
1020 res = ast_dial_run(dial, NULL, 0);
1021 if (res != AST_DIAL_RESULT_ANSWERED) {
1022 goto end;
1023 }
1024
1025 if (!ast_strlen_zero(origination->appdata)) {
1026 struct ast_app *app = pbx_findapp("Stasis");
1027
1028 if (app) {
1029 ast_verb(4, "Launching Stasis(%s) on %s\n", origination->appdata,
1031 pbx_exec(ast_dial_answered(dial), app, origination->appdata);
1032 } else {
1033 ast_log(LOG_WARNING, "No such application 'Stasis'\n");
1034 }
1035 } else {
1036 struct ast_channel *answered = ast_dial_answered(dial);
1037
1038 if (!ast_strlen_zero(origination->context)) {
1039 ast_channel_context_set(answered, origination->context);
1040 }
1041
1042 if (!ast_strlen_zero(origination->exten)) {
1043 ast_channel_exten_set(answered, origination->exten);
1044 }
1045
1046 if (origination->priority > 0) {
1047 ast_channel_priority_set(answered, origination->priority);
1048 }
1049
1050 if (ast_pbx_run(answered)) {
1051 ast_log(LOG_ERROR, "Failed to start PBX on %s\n", ast_channel_name(answered));
1052 } else {
1053 /* PBX will have taken care of hanging up, so we steal the answered channel so dial doesn't do it */
1055 }
1056 }
1057
1058end:
1059 ast_dial_destroy(dial);
1060 ast_free(origination);
1061 return NULL;
1062}
static const char app[]
Definition: app_adsiprog.c:56
void ast_channel_exten_set(struct ast_channel *chan, const char *value)
const char * ast_channel_name(const struct ast_channel *chan)
void ast_channel_context_set(struct ast_channel *chan, const char *value)
void ast_channel_priority_set(struct ast_channel *chan, int value)
ast_dial_result
List of return codes for dial run API calls.
Definition: dial.h:54
@ AST_DIAL_RESULT_ANSWERED
Definition: dial.h:61
struct ast_channel * ast_dial_answered(struct ast_dial *dial)
Return channel that answered.
Definition: dial.c:977
enum ast_dial_result ast_dial_run(struct ast_dial *dial, struct ast_channel *chan, int async)
Execute dialing synchronously or asynchronously.
Definition: dial.c:935
struct ast_channel * ast_dial_answered_steal(struct ast_dial *dial)
Steal the channel that answered.
Definition: dial.c:989
void * ast_dial_get_user_data(struct ast_dial *dial)
Return the user data on a dial structure.
Definition: dial.c:1279
char * end
Definition: eagi_proxy.c:73
#define ast_verb(level,...)
#define LOG_WARNING
enum ast_pbx_result ast_pbx_run(struct ast_channel *c)
Execute the PBX in the current thread.
Definition: pbx.c:4770

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

Referenced by ari_channels_handle_originate_with_id().

◆ ast_ari_channels_answer()

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

Answer a channel.

Parameters
headersHTTP headers
argsSwagger parameters
[out]responseHTTP response

Definition at line 339 of file resource_channels.c.

342{
343 RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
344
345 control = find_control(response, args->channel_id);
346 if (control == NULL) {
347 return;
348 }
349
350 if (channel_state_invalid(control, response)) {
351 return;
352 }
353
354 if (stasis_app_control_answer(control) != 0) {
356 response, 500, "Internal Server Error",
357 "Failed to answer channel");
358 return;
359 }
360
362}
void ast_ari_response_no_content(struct ast_ari_response *response)
Fill in a No Content (204) ast_ari_response.
Definition: res_ari.c:237
int stasis_app_control_answer(struct stasis_app_control *control)
Answer the channel associated with this control.
const char * args

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

Referenced by ast_ari_channels_answer_cb().

◆ ast_ari_channels_continue_in_dialplan()

void ast_ari_channels_continue_in_dialplan ( struct ast_variable headers,
struct ast_ari_channels_continue_in_dialplan_args args,
struct ast_ari_response response 
)

Exit application; continue execution in the dialplan.

Parameters
headersHTTP headers
argsSwagger parameters
[out]responseHTTP response

Definition at line 181 of file resource_channels.c.

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

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

Referenced by ast_ari_channels_continue_in_dialplan_cb().

◆ ast_ari_channels_create()

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

Create channel.

Parameters
headersHTTP headers
argsSwagger parameters
[out]responseHTTP response

Definition at line 1779 of file resource_channels.c.

1782{
1783 RAII_VAR(struct ast_variable *, variables, NULL, ast_variables_destroy);
1784 struct ast_assigned_ids assignedids;
1785 struct ari_channel_thread_data *chan_data;
1786 struct ast_channel_snapshot *snapshot;
1787 pthread_t thread;
1788 char *dialtech;
1789 char *dialdevice = NULL;
1790 char *stuff;
1791 int cause;
1792 struct ast_format_cap *request_cap;
1793 struct ast_channel *originator;
1794
1795 /* Parse any query parameters out of the body parameter */
1796 if (args->variables) {
1797 struct ast_json *json_variables;
1798
1800 json_variables = ast_json_object_get(args->variables, "variables");
1801 if (json_variables
1802 && json_to_ast_variables(response, json_variables, &variables)) {
1803 return;
1804 }
1805 }
1806
1807 assignedids.uniqueid = args->channel_id;
1808 assignedids.uniqueid2 = args->other_channel_id;
1809
1810 if (!ast_strlen_zero(args->originator) && !ast_strlen_zero(args->formats)) {
1811 ast_ari_response_error(response, 400, "Bad Request",
1812 "Originator and formats can't both be specified");
1813 return;
1814 }
1815
1816 if (ast_strlen_zero(args->endpoint)) {
1817 ast_ari_response_error(response, 400, "Bad Request",
1818 "Endpoint must be specified");
1819 return;
1820 }
1821
1822 chan_data = ast_calloc(1, sizeof(*chan_data));
1823 if (!chan_data) {
1825 return;
1826 }
1827
1828 chan_data->stasis_stuff = ast_str_create(32);
1829 if (!chan_data->stasis_stuff) {
1831 chan_data_destroy(chan_data);
1832 return;
1833 }
1834
1835 ast_str_append(&chan_data->stasis_stuff, 0, "%s", args->app);
1836 if (!ast_strlen_zero(args->app_args)) {
1837 ast_str_append(&chan_data->stasis_stuff, 0, ",%s", args->app_args);
1838 }
1839
1840 dialtech = ast_strdupa(args->endpoint);
1841 if ((stuff = strchr(dialtech, '/'))) {
1842 *stuff++ = '\0';
1843 dialdevice = stuff;
1844 }
1845
1846 if (ast_strlen_zero(dialtech) || ast_strlen_zero(dialdevice)) {
1847 ast_ari_response_error(response, 400, "Bad Request",
1848 "Invalid endpoint specified");
1849 chan_data_destroy(chan_data);
1850 return;
1851 }
1852
1853 originator = ast_channel_get_by_name(args->originator);
1854 if (originator) {
1855 request_cap = ao2_bump(ast_channel_nativeformats(originator));
1856 if (!ast_strlen_zero(args->app)) {
1857 stasis_app_subscribe_channel(args->app, originator);
1858 }
1859 } else if (!ast_strlen_zero(args->formats)) {
1860 char *format_name;
1861 char *formats_copy = ast_strdupa(args->formats);
1862
1863 if (!(request_cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
1865 chan_data_destroy(chan_data);
1866 return;
1867 }
1868
1869 while ((format_name = ast_strip(strsep(&formats_copy, ",")))) {
1870 struct ast_format *fmt = ast_format_cache_get(format_name);
1871
1872 if (!fmt || ast_format_cap_append(request_cap, fmt, 0)) {
1873 if (!fmt) {
1875 response, 400, "Bad Request",
1876 "Provided format (%s) was not found", format_name);
1877 } else {
1879 }
1880 ao2_ref(request_cap, -1);
1881 ao2_cleanup(fmt);
1882 chan_data_destroy(chan_data);
1883 return;
1884 }
1885 ao2_ref(fmt, -1);
1886 }
1887 } else {
1888 if (!(request_cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
1890 chan_data_destroy(chan_data);
1891 return;
1892 }
1893
1895 }
1896
1897 chan_data->chan = ast_request(dialtech, request_cap, &assignedids, originator, dialdevice, &cause);
1898 ao2_cleanup(request_cap);
1899
1900 if (!chan_data->chan) {
1902 ast_ari_response_error(response, 409, "Conflict",
1903 "Channel with given unique ID already exists");
1904 } else {
1906 }
1907 ast_channel_cleanup(originator);
1908 chan_data_destroy(chan_data);
1909 return;
1910 }
1911
1912 if (!ast_strlen_zero(args->app)) {
1913 stasis_app_subscribe_channel(args->app, chan_data->chan);
1914 }
1915
1916 if (variables) {
1917 ast_set_variables(chan_data->chan, variables);
1918 }
1919
1920 ast_channel_cleanup(originator);
1921
1922 if (save_dialstring(chan_data->chan, stuff)) {
1924 chan_data_destroy(chan_data);
1925 return;
1926 }
1927
1929
1932 chan_data_destroy(chan_data);
1933 } else {
1935 }
1936
1937 ao2_ref(snapshot, -1);
1938}
#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:6309
@ 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:1262
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 1940 of file resource_channels.c.

1943{
1944 RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
1945 RAII_VAR(struct ast_channel *, caller, NULL, ast_channel_cleanup);
1946 RAII_VAR(struct ast_channel *, callee, NULL, ast_channel_cleanup);
1947 char *dialstring;
1948
1949 control = find_control(response, args->channel_id);
1950 if (control == NULL) {
1951 /* Response filled in by find_control */
1952 return;
1953 }
1954
1955 caller = ast_channel_get_by_name(args->caller);
1956
1957 callee = ast_channel_get_by_name(args->channel_id);
1958 if (!callee) {
1959 ast_ari_response_error(response, 404, "Not Found",
1960 "Callee not found");
1961 return;
1962 }
1963
1964 if (ast_channel_state(callee) != AST_STATE_DOWN
1965 && ast_channel_state(callee) != AST_STATE_RESERVED) {
1966 ast_ari_response_error(response, 409, "Conflict",
1967 "Channel is not in the 'Down' state");
1968 return;
1969 }
1970
1971 /* XXX This is straight up copied from main/dial.c. It's probably good
1972 * to separate this to some common method.
1973 */
1974 if (caller) {
1975 ast_channel_lock_both(caller, callee);
1976 } else {
1977 ast_channel_lock(callee);
1978 }
1979
1980 dialstring = restore_dialstring(callee);
1981 if (!dialstring) {
1982 ast_channel_unlock(callee);
1983 if (caller) {
1984 ast_channel_unlock(caller);
1985 }
1986 ast_ari_response_error(response, 409, "Conflict",
1987 "Dialing a channel not created by ARI");
1988 return;
1989 }
1990 /* Make a copy of the dialstring just in case some jerk tries to hang up the
1991 * channel before we can actually dial
1992 */
1993 dialstring = ast_strdupa(dialstring);
1994
1996 if (caller) {
1997 ast_channel_inherit_variables(caller, callee);
1998 ast_channel_datastore_inherit(caller, callee);
2000
2001 /* Copy over callerid information */
2003
2005
2007
2008 ast_channel_language_set(callee, ast_channel_language(caller));
2011 ast_channel_musicclass_set(callee, ast_channel_musicclass(caller));
2012
2015 ast_channel_unlock(caller);
2016 }
2017
2019 ast_channel_unlock(callee);
2020
2021 if (stasis_app_control_dial(control, dialstring, args->timeout)) {
2023 return;
2024 }
2025
2027}
@ AST_CHANNEL_REQUESTOR_BRIDGE_PEER
Definition: channel.h:1525
const char * ast_channel_musicclass(const struct ast_channel *chan)
struct ast_party_redirecting * ast_channel_redirecting(struct ast_channel *chan)
unsigned short ast_channel_transfercapability(const struct ast_channel *chan)
#define ast_channel_lock_both(chan1, chan2)
Lock two channels.
Definition: channel.h:2979
int ast_channel_datastore_inherit(struct ast_channel *from, struct ast_channel *to)
Inherit datastores from a parent to a child.
Definition: channel.c:2337
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:6389
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:6731
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:8294
struct ast_party_caller * ast_channel_caller(struct ast_channel *chan)
void ast_channel_transfercapability_set(struct ast_channel *chan, unsigned short value)
void ast_channel_adsicpe_set(struct ast_channel *chan, enum ast_channel_adsicpe value)
void ast_party_redirecting_copy(struct ast_party_redirecting *dest, const struct ast_party_redirecting *src)
Copy the source redirecting information to the destination redirecting.
Definition: channel.c:2102
ast_channel_state
ast_channel states
Definition: channelstate.h:35
@ AST_STATE_DOWN
Definition: channelstate.h:36
@ AST_STATE_RESERVED
Definition: channelstate.h:37
void ast_channel_stage_snapshot_done(struct ast_channel *chan)
Clear flag to indicate channel snapshot is being staged, and publish snapshot.
void ast_channel_stage_snapshot(struct ast_channel *chan)
Set flag to indicate channel snapshot is being staged.
int ast_max_forwards_decrement(struct ast_channel *chan)
Decrement the max forwards count for a particular channel.
Definition: max_forwards.c:135
static char * restore_dialstring(struct ast_channel *chan)
Retrieve the dialstring from the channel datastore.
int stasis_app_control_dial(struct stasis_app_control *control, const char *dialstring, unsigned int timeout)
Dial a channel.
Definition: control.c:1696
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 2233 of file resource_channels.c.

2235{
2236 RAII_VAR(struct ast_variable *, variables, NULL, ast_variables_destroy);
2237 char *external_host;
2238 char *host = NULL;
2239 char *port = NULL;
2240
2241 ast_assert(response != NULL);
2242
2243 /* Parse any query parameters out of the body parameter */
2244 if (args->variables) {
2245 struct ast_json *json_variables;
2246
2248 json_variables = ast_json_object_get(args->variables, "variables");
2249 if (json_variables
2250 && json_to_ast_variables(response, json_variables, &variables)) {
2251 return;
2252 }
2253 }
2254
2255 if (ast_strlen_zero(args->app)) {
2256 ast_ari_response_error(response, 400, "Bad Request", "app cannot be empty");
2257 return;
2258 }
2259
2260 if (ast_strlen_zero(args->transport)) {
2261 args->transport = "udp";
2262 }
2263
2264 if (ast_strlen_zero(args->encapsulation)) {
2265 args->encapsulation = "rtp";
2266 }
2267 if (ast_strings_equal(args->transport, "websocket")) {
2268 if (!ast_strings_equal(args->encapsulation, "none")) {
2269 ast_ari_response_error(response, 400, "Bad Request", "encapsulation must be 'none' for websocket transport");
2270 return;
2271 }
2272 }
2273
2274 if (ast_strings_equal(args->encapsulation, "rtp")) {
2275 if (!ast_strings_equal(args->transport, "udp")) {
2276 ast_ari_response_error(response, 400, "Bad Request", "transport must be 'udp' for rtp encapsulation");
2277 return;
2278 }
2279 }
2280
2281 if (ast_strings_equal(args->encapsulation, "audiosocket")) {
2282 if (!ast_strings_equal(args->transport, "tcp")) {
2283 ast_ari_response_error(response, 400, "Bad Request", "transport must be 'tcp' for audiosocket encapsulation");
2284 return;
2285 }
2286 }
2287
2288 if (ast_strlen_zero(args->connection_type)) {
2289 args->connection_type = "client";
2290 }
2291 if (!ast_strings_equal(args->transport, "websocket")) {
2292 if (ast_strings_equal(args->connection_type, "server")) {
2293 ast_ari_response_error(response, 400, "Bad Request", "'server' connection_type can only be used with the websocket transport");
2294 return;
2295 }
2296 }
2297
2298 if (ast_strlen_zero(args->external_host)) {
2299 if (ast_strings_equal(args->connection_type, "client")) {
2300 ast_ari_response_error(response, 400, "Bad Request", "external_host is required for all but websocket server connections");
2301 return;
2302 } else {
2303 /* server is only valid for websocket, enforced above */
2304 args->external_host = "INCOMING";
2305 }
2306 }
2307
2308 if (ast_strings_equal(args->transport, "websocket")) {
2309 if (ast_strings_equal(args->connection_type, "client")) {
2310 struct ast_websocket_client *ws_client =
2312 ao2_cleanup(ws_client);
2313 if (!ws_client) {
2314 ast_ari_response_error(response, 400, "Bad Request", "external_host must be a valid websocket_client connection id.");
2315 return;
2316 }
2317 }
2318 } else {
2319 external_host = ast_strdupa(args->external_host);
2320 if (!ast_sockaddr_split_hostport(external_host, &host, &port, PARSE_PORT_REQUIRE)) {
2321 ast_ari_response_error(response, 400, "Bad Request", "external_host must be <host>:<port> for all transports other than websocket");
2322 return;
2323 }
2324 }
2325
2326 if (ast_strlen_zero(args->format)) {
2327 ast_ari_response_error(response, 400, "Bad Request", "format cannot be empty");
2328 return;
2329 }
2330
2331 if (ast_strlen_zero(args->direction)) {
2332 args->direction = "both";
2333 }
2334
2335 if (strcasecmp(args->encapsulation, "rtp") == 0 && strcasecmp(args->transport, "udp") == 0) {
2336 if (external_media_rtp_udp(args, variables, response)) {
2338 response, 500, "Internal Server Error",
2339 "An internal error prevented this request from being handled");
2340 }
2341 } else if (strcasecmp(args->encapsulation, "audiosocket") == 0 && strcasecmp(args->transport, "tcp") == 0) {
2342 if (external_media_audiosocket_tcp(args, variables, response)) {
2344 response, 500, "Internal Server Error",
2345 "An internal error prevented this request from being handled");
2346 }
2347 } else if (strcasecmp(args->encapsulation, "none") == 0 && strcasecmp(args->transport, "websocket") == 0) {
2348 if (external_media_websocket(args, variables, response)) {
2350 response, 500, "Internal Server Error",
2351 "An internal error prevented this request from being handled");
2352 }
2353 } else {
2355 response, 501, "Not Implemented",
2356 "The encapsulation and/or transport is not supported");
2357 }
2358}
@ PARSE_PORT_REQUIRE
int ast_sockaddr_split_hostport(char *str, char **host, char **port, int flags)
Splits a string into its host and port components.
Definition: netsock2.c:164
static int external_media_audiosocket_tcp(struct ast_ari_channels_external_media_args *args, struct ast_variable *variables, struct ast_ari_response *response)
static int external_media_websocket(struct ast_ari_channels_external_media_args *args, struct ast_variable *variables, struct ast_ari_response *response)
static int external_media_rtp_udp(struct ast_ari_channels_external_media_args *args, struct ast_variable *variables, struct ast_ari_response *response)
int ast_ari_channels_external_media_parse_body(struct ast_json *body, struct ast_ari_channels_external_media_args *args)
Body parsing function for /channels/externalMedia.
int ast_strings_equal(const char *str1, const char *str2)
Compare strings for equality checking for NULL.
Definition: strings.c:238
struct ast_websocket_client * ast_websocket_client_retrieve_by_id(const char *id)
Retrieve a websocket client object by ID.

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

Referenced by ast_ari_channels_external_media_cb().

◆ ast_ari_channels_get()

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

Channel details.

Parameters
headersHTTP headers
argsSwagger parameters
[out]responseHTTP response

Definition at line 889 of file resource_channels.c.

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

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

1476{
1477 RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
1478 RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
1479 RAII_VAR(struct ast_str *, value, ast_str_create(32), ast_free);
1480 RAII_VAR(struct ast_channel *, channel, NULL, ast_channel_cleanup);
1481
1482 ast_assert(response != NULL);
1483
1484 if (!value) {
1486 return;
1487 }
1488
1489 if (ast_strlen_zero(args->variable)) {
1491 response, 400, "Bad Request",
1492 "Variable name is required");
1493 return;
1494 }
1495
1496 if (ast_strlen_zero(args->channel_id)) {
1498 response, 400, "Bad Request",
1499 "Channel ID is required");
1500 return;
1501 }
1502
1503 channel = ast_channel_get_by_name(args->channel_id);
1504 if (!channel) {
1506 response, 404, "Channel Not Found",
1507 "Provided channel was not found");
1508 return;
1509 }
1510
1511 /* You may be tempted to lock the channel you're about to read from. You
1512 * would be wrong. Some dialplan functions put the channel into
1513 * autoservice, which deadlocks if the channel is already locked.
1514 * ast_str_retrieve_variable() does its own locking, and the dialplan
1515 * functions need to as well. We should be fine without the lock.
1516 */
1517
1518 if (args->variable[strlen(args->variable) - 1] == ')') {
1519 if (ast_func_read2(channel, args->variable, &value, 0)) {
1521 response, 500, "Error With Function",
1522 "Unable to read provided function");
1523 return;
1524 }
1525 } else {
1526 if (!ast_str_retrieve_variable(&value, 0, channel, NULL, args->variable)) {
1528 response, 404, "Variable Not Found",
1529 "Provided variable was not found");
1530 return;
1531 }
1532 }
1533
1534 if (!(json = ast_json_pack("{s: s}", "value", S_OR(ast_str_buffer(value), "")))) {
1536 return;
1537 }
1538
1539 ast_ari_response_ok(response, ast_json_ref(json));
1540}
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 908 of file resource_channels.c.

911{
912 RAII_VAR(struct ast_channel *, chan, NULL, ao2_cleanup);
913 int cause;
914
915 chan = ast_channel_get_by_name(args->channel_id);
916 if (chan == NULL) {
918 response, 404, "Not Found",
919 "Channel not found");
920 return;
921 }
922
923 if (!ast_strlen_zero(args->reason) && !ast_strlen_zero(args->reason_code)) {
924 ast_ari_response_error(response, 400, "Bad Request",
925 "The reason and reason_code can't both be specified");
926 return;
927 }
928
929 if (!ast_strlen_zero(args->reason_code)) {
930 /* reason_code allows any hangup code */
931 if (sscanf(args->reason_code, "%30d", &cause) != 1) {
933 response, 400, "Invalid Reason Code",
934 "Invalid reason for hangup reason code provided");
935 return;
936 }
937 } else if (!ast_strlen_zero(args->reason)) {
938 /* reason allows only listed hangup reason */
939 cause = convert_reason_to_hangup_code(args->reason);
940 if (cause == -1) {
942 response, 400, "Invalid Reason",
943 "Invalid reason for hangup reason provided");
944 return;
945 }
946 } else {
947 /* not specified. set default hangup */
948 cause = AST_CAUSE_NORMAL;
949 }
950
951 ast_channel_hangupcause_set(chan, cause);
953
955}
#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:2440
void ast_channel_hangupcause_set(struct ast_channel *chan, int value)
static int convert_reason_to_hangup_code(const char *reason)
Return the corresponded hangup code of the given reason.

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

Referenced by ast_ari_channels_hangup_cb().

◆ ast_ari_channels_hold()

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

Hold a channel.

Parameters
headersHTTP headers
argsSwagger parameters
[out]responseHTTP response

Definition at line 515 of file resource_channels.c.

518{
519 RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
520
521 control = find_control(response, args->channel_id);
522 if (control == NULL) {
523 /* Response filled in by find_control */
524 return;
525 }
526
527 if (channel_state_invalid(control, response)) {
528 return;
529 }
530
532
534}
void stasis_app_control_hold(struct stasis_app_control *control)
Place the channel associated with the control on hold.
Definition: control.c:774

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

960{
961 RAII_VAR(struct ao2_container *, snapshots, NULL, ao2_cleanup);
962 RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
963 struct ao2_iterator i;
964 void *obj;
966
967 snapshots = ast_channel_cache_all();
968
969 json = ast_json_array_create();
970 if (!json) {
972 return;
973 }
974
975 i = ao2_iterator_init(snapshots, 0);
976 while ((obj = ao2_iterator_next(&i))) {
977 struct ast_channel_snapshot *snapshot = obj;
978 int r;
979
980 if (sanitize && sanitize->channel_snapshot
981 && sanitize->channel_snapshot(snapshot)) {
982 ao2_ref(snapshot, -1);
983 continue;
984 }
985
987 json, ast_channel_snapshot_to_json(snapshot, NULL));
988 if (r != 0) {
991 ao2_ref(snapshot, -1);
992 return;
993 }
994 ao2_ref(snapshot, -1);
995 }
997
998 ast_ari_response_ok(response, ast_json_ref(json));
999}
#define ao2_iterator_next(iter)
Definition: astobj2.h:1911
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
struct ao2_container * ast_channel_cache_all(void)
int ast_json_array_append(struct ast_json *array, struct ast_json *value)
Append to an array.
Definition: json.c:378
struct ast_json * ast_json_array_create(void)
Create a empty JSON array.
Definition: json.c:362
struct stasis_message_sanitizer * stasis_app_get_sanitizer(void)
Get the Stasis message sanitizer for app_stasis applications.
Definition: res_stasis.c:2343
Generic container type.
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1821
Structure containing callbacks for Stasis message sanitization.
Definition: stasis.h:200
int(* channel_snapshot)(const struct ast_channel_snapshot *snapshot)
Callback which determines whether a channel should be sanitized from a message based on the channel's...
Definition: stasis.h:221

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

Referenced by ast_ari_channels_list_cb().

◆ ast_ari_channels_move()

void ast_ari_channels_move ( struct ast_variable headers,
struct ast_ari_channels_move_args args,
struct ast_ari_response response 
)

Move the channel from one Stasis application to another.

Parameters
headersHTTP headers
argsSwagger parameters
[out]responseHTTP response

Definition at line 257 of file resource_channels.c.

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

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

Referenced by ast_ari_channels_move_cb().

◆ ast_ari_channels_mute()

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

Mute a channel.

Parameters
headersHTTP headers
argsSwagger parameters
[out]responseHTTP response

Definition at line 404 of file resource_channels.c.

407{
408 RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
409 unsigned int direction = 0;
410 enum ast_frame_type frametype = AST_FRAME_VOICE;
411
412 control = find_control(response, args->channel_id);
413 if (control == NULL) {
414 return;
415 }
416
417 if (channel_state_invalid(control, response)) {
418 return;
419 }
420
421 if (ast_strlen_zero(args->direction)) {
423 response, 400, "Bad Request",
424 "Direction is required");
425 return;
426 }
427
428 if (!strcmp(args->direction, "in")) {
430 } else if (!strcmp(args->direction, "out")) {
432 } else if (!strcmp(args->direction, "both")) {
434 } else {
436 response, 400, "Bad Request",
437 "Invalid direction specified");
438 return;
439 }
440
441 stasis_app_control_mute(control, direction, frametype);
442
444}
#define AST_MUTE_DIRECTION_READ
Definition: channel.h:4790
#define AST_MUTE_DIRECTION_WRITE
Definition: channel.h:4791
direction
ast_frame_type
Frame types.
@ AST_FRAME_VOICE
int stasis_app_control_mute(struct stasis_app_control *control, unsigned int direction, enum ast_frame_type frametype)
Mute the channel associated with this control.
Definition: control.c:657

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

1437{
1438 struct ast_variable *variables = NULL;
1439 struct ast_channel *chan;
1440
1441 /* Parse any query parameters out of the body parameter */
1442 if (args->variables) {
1443 struct ast_json *json_variables;
1444
1446 json_variables = ast_json_object_get(args->variables, "variables");
1447 if (json_variables
1448 && json_to_ast_variables(response, json_variables, &variables)) {
1449 return;
1450 }
1451 }
1452
1454 args->endpoint,
1455 args->extension,
1456 args->context,
1457 args->priority,
1458 args->label,
1459 args->app,
1460 args->app_args,
1461 args->caller_id,
1462 args->timeout,
1463 variables,
1464 args->channel_id,
1465 args->other_channel_id,
1466 args->originator,
1467 args->formats,
1468 response);
1469 ast_channel_cleanup(chan);
1470 ast_variables_destroy(variables);
1471}
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 1395 of file resource_channels.c.

1398{
1399 struct ast_variable *variables = NULL;
1400 struct ast_channel *chan;
1401
1402 /* Parse any query parameters out of the body parameter */
1403 if (args->variables) {
1404 struct ast_json *json_variables;
1405
1407 json_variables = ast_json_object_get(args->variables, "variables");
1408 if (json_variables
1409 && json_to_ast_variables(response, json_variables, &variables)) {
1410 return;
1411 }
1412 }
1413
1415 args->endpoint,
1416 args->extension,
1417 args->context,
1418 args->priority,
1419 args->label,
1420 args->app,
1421 args->app_args,
1422 args->caller_id,
1423 args->timeout,
1424 variables,
1425 args->channel_id,
1426 args->other_channel_id,
1427 args->originator,
1428 args->formats,
1429 response);
1430 ast_channel_cleanup(chan);
1431 ast_variables_destroy(variables);
1432}
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 719 of file resource_channels.c.

722{
724 args->channel_id,
725 args->media,
726 args->media_count,
727 args->lang,
728 args->offsetms,
729 args->skipms,
730 args->playback_id,
731 response);
732}
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 734 of file resource_channels.c.

737{
739 args->channel_id,
740 args->media,
741 args->media_count,
742 args->lang,
743 args->offsetms,
744 args->skipms,
745 args->playback_id,
746 response);
747}

References args, and ari_channels_handle_play().

Referenced by ast_ari_channels_play_with_id_cb().

◆ ast_ari_channels_record()

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

Start a recording.

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

Parameters
headersHTTP headers
argsSwagger parameters
[out]responseHTTP response

Definition at line 749 of file resource_channels.c.

752{
753 RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
754 RAII_VAR(struct stasis_app_recording *, recording, NULL, ao2_cleanup);
755 RAII_VAR(char *, recording_url, NULL, ast_free);
756 struct ast_json *json;
759 RAII_VAR(char *, uri_encoded_name, NULL, ast_free);
760 size_t uri_name_maxlen;
761
762 ast_assert(response != NULL);
763
764 if (args->max_duration_seconds < 0) {
766 response, 400, "Bad Request",
767 "max_duration_seconds cannot be negative");
768 return;
769 }
770
771 if (args->max_silence_seconds < 0) {
773 response, 400, "Bad Request",
774 "max_silence_seconds cannot be negative");
775 return;
776 }
777
778 control = find_control(response, args->channel_id);
779 if (control == NULL) {
780 /* Response filled in by find_control */
781 return;
782 }
783
785 if (options == NULL) {
787 response, 500, "Internal Server Error",
788 "Out of memory");
789 }
790 ast_string_field_build(options, target, "channel:%s", args->channel_id);
791 options->max_silence_seconds = args->max_silence_seconds;
792 options->max_duration_seconds = args->max_duration_seconds;
793 options->terminate_on =
795 options->if_exists =
797 options->beep = args->beep;
798
799 if (options->terminate_on == STASIS_APP_RECORDING_TERMINATE_INVALID) {
801 response, 400, "Bad Request",
802 "terminateOn invalid");
803 return;
804 }
805
806 if (options->if_exists == AST_RECORD_IF_EXISTS_ERROR) {
808 response, 400, "Bad Request",
809 "ifExists invalid");
810 return;
811 }
812
813 if (!ast_get_format_for_file_ext(options->format)) {
815 response, 422, "Unprocessable Entity",
816 "specified format is unknown on this system");
817 return;
818 }
819
820 recording = stasis_app_control_record(control, options);
821 if (recording == NULL) {
822 switch(errno) {
823 case EINVAL:
824 /* While the arguments are invalid, we should have
825 * caught them prior to calling record.
826 */
828 response, 500, "Internal Server Error",
829 "Error parsing request");
830 break;
831 case EEXIST:
832 ast_ari_response_error(response, 409, "Conflict",
833 "Recording '%s' already exists and can not be overwritten",
834 args->name);
835 break;
836 case ENOMEM:
838 response, 500, "Internal Server Error",
839 "Out of memory");
840 break;
841 case EPERM:
843 response, 400, "Bad Request",
844 "Recording name invalid");
845 break;
846 default:
848 "Unrecognized recording error: %s\n",
849 strerror(errno));
851 response, 500, "Internal Server Error",
852 "Internal Server Error");
853 break;
854 }
855 return;
856 }
857
858 uri_name_maxlen = strlen(args->name) * 3;
859 uri_encoded_name = ast_malloc(uri_name_maxlen);
860 if (!uri_encoded_name) {
862 response, 500, "Internal Server Error",
863 "Out of memory");
864 return;
865 }
866 ast_uri_encode(args->name, uri_encoded_name, uri_name_maxlen,
868
869 if (ast_asprintf(&recording_url, "/recordings/live/%s",
870 uri_encoded_name) == -1) {
871 recording_url = NULL;
873 response, 500, "Internal Server Error",
874 "Out of memory");
875 return;
876 }
877
878 json = stasis_app_recording_to_json(recording);
879 if (!json) {
881 response, 500, "Internal Server Error",
882 "Out of memory");
883 return;
884 }
885
886 ast_ari_response_created(response, recording_url, json);
887}
#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:2014
@ AST_RECORD_IF_EXISTS_ERROR
int errno
struct stasis_app_recording_options * stasis_app_recording_options_create(const char *name, const char *format)
Allocate a recording options object.
struct ast_json * stasis_app_recording_to_json(const struct stasis_app_recording *recording)
Construct a JSON model of a recording.
struct stasis_app_recording * stasis_app_control_record(struct stasis_app_control *control, struct stasis_app_recording_options *options)
Record media from a channel.
enum ast_record_if_exists stasis_app_recording_if_exists_parse(const char *str)
Parse a string into the if_exists enum.
#define STASIS_APP_RECORDING_TERMINATE_INVALID
char stasis_app_recording_termination_parse(const char *str)
Parse a string into the recording termination enum.
#define ast_string_field_build(x, field, fmt, args...)
Set a field to a complex (built) value.
Definition: stringfields.h:555
static struct test_options options
char * ast_uri_encode(const char *string, char *outbuf, int buflen, struct ast_flags spec)
Turn text string to URI-encoded XX version.
Definition: utils.c:723
const struct ast_flags ast_uri_http
Definition: utils.c:719

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

Referenced by ast_ari_channels_record_cb().

◆ ast_ari_channels_redirect()

void ast_ari_channels_redirect ( struct ast_variable headers,
struct ast_ari_channels_redirect_args args,
struct ast_ari_response response 
)

Redirect the channel to a different location.

Parameters
headersHTTP headers
argsSwagger parameters
[out]responseHTTP response

Definition at line 277 of file resource_channels.c.

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

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

Referenced by ast_ari_channels_redirect_cb().

◆ ast_ari_channels_ring()

void ast_ari_channels_ring ( struct ast_variable headers,
struct ast_ari_channels_ring_args args,
struct ast_ari_response response 
)

Indicate ringing to a channel.

Parameters
headersHTTP headers
argsSwagger parameters
[out]responseHTTP response

Definition at line 364 of file resource_channels.c.

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

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

Referenced by ast_ari_channels_ring_cb().

◆ ast_ari_channels_ring_stop()

void ast_ari_channels_ring_stop ( struct ast_variable headers,
struct ast_ari_channels_ring_stop_args args,
struct ast_ari_response response 
)

Stop ringing indication on a channel if locally generated.

Parameters
headersHTTP headers
argsSwagger parameters
[out]responseHTTP response

Definition at line 384 of file resource_channels.c.

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

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

Referenced by ast_ari_channels_ring_stop_cb().

◆ ast_ari_channels_rtpstatistics()

void ast_ari_channels_rtpstatistics ( struct ast_variable headers,
struct ast_ari_channels_rtpstatistics_args args,
struct ast_ari_response response 
)

RTP stats on a channel.

Parameters
headersHTTP headers
argsSwagger parameters
[out]responseHTTP response

Definition at line 2029 of file resource_channels.c.

2032{
2033 RAII_VAR(struct ast_channel *, chan, NULL, ast_channel_cleanup);
2034 RAII_VAR(struct ast_rtp_instance *, rtp, NULL, ao2_cleanup);
2035 struct ast_json *j_res;
2036 const struct ast_channel_tech *tech;
2037 struct ast_rtp_glue *glue;
2038
2039 chan = ast_channel_get_by_name(args->channel_id);
2040 if (!chan) {
2041 ast_ari_response_error(response, 404, "Not Found",
2042 "Channel not found");
2043 return;
2044 }
2045
2046 ast_channel_lock(chan);
2047 tech = ast_channel_tech(chan);
2048 if (!tech) {
2049 ast_channel_unlock(chan);
2050 ast_ari_response_error(response, 404, "Not Found",
2051 "Channel's tech not found");
2052 return;
2053 }
2054
2055 glue = ast_rtp_instance_get_glue(tech->type);
2056 if (!glue) {
2057 ast_channel_unlock(chan);
2058 ast_ari_response_error(response, 403, "Forbidden",
2059 "Unsupported channel type");
2060 return;
2061 }
2062
2063 glue->get_rtp_info(chan, &rtp);
2064 if (!rtp) {
2065 ast_channel_unlock(chan);
2066 ast_ari_response_error(response, 404, "Not Found",
2067 "RTP info not found");
2068 return;
2069 }
2070
2072 if (!j_res) {
2073 ast_channel_unlock(chan);
2074 ast_ari_response_error(response, 404, "Not Found",
2075 "Statistics not found");
2076 return;
2077 }
2078
2079 ast_channel_unlock(chan);
2080 ast_ari_response_ok(response, j_res);
2081
2082 return;
2083}
const struct ast_channel_tech * ast_channel_tech(const struct ast_channel *chan)
struct ast_json * ast_rtp_instance_get_stats_all_json(struct ast_rtp_instance *instance)
Retrieve statistics about an RTP instance in json format.
Definition: rtp_engine.c:4271
struct ast_rtp_glue * ast_rtp_instance_get_glue(const char *type)
Get the RTP glue that binds a channel to the RTP engine.
Definition: rtp_engine.c:2388
Structure to describe a channel "technology", ie a channel driver See for examples:
Definition: channel.h:648
const char *const type
Definition: channel.h:649
enum ast_rtp_glue_result(* get_rtp_info)(struct ast_channel *chan, struct ast_rtp_instance **instance)
Callback for retrieving the RTP instance carrying audio.
Definition: rtp_engine.h:787

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

Referenced by ast_ari_channels_rtpstatistics_cb().

◆ ast_ari_channels_send_dtmf()

void ast_ari_channels_send_dtmf ( struct ast_variable headers,
struct ast_ari_channels_send_dtmf_args args,
struct ast_ari_response response 
)

Send provided DTMF to a given channel.

Parameters
headersHTTP headers
argsSwagger parameters
[out]responseHTTP response

Definition at line 488 of file resource_channels.c.

491{
492 RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
493
494 control = find_control(response, args->channel_id);
495 if (control == NULL) {
496 return;
497 }
498
499 if (channel_state_invalid(control, response)) {
500 return;
501 }
502
503 if (ast_strlen_zero(args->dtmf)) {
505 response, 400, "Bad Request",
506 "DTMF is required");
507 return;
508 }
509
510 stasis_app_control_dtmf(control, args->dtmf, args->before, args->between, args->duration, args->after);
511
513}
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 1542 of file resource_channels.c.

1545{
1546 RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
1547
1548 ast_assert(response != NULL);
1549
1550 if (ast_strlen_zero(args->variable)) {
1552 response, 400, "Bad Request",
1553 "Variable name is required");
1554 return;
1555 }
1556
1557 control = find_control(response, args->channel_id);
1558 if (control == NULL) {
1559 /* response filled in by find_control */
1560 return;
1561 }
1562
1563 if (stasis_app_control_set_channel_var(control, args->variable, args->value)) {
1565 response, 400, "Bad Request",
1566 "Failed to execute function");
1567 return;
1568 }
1569
1571}
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:737

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

1655{
1657 args->channel_id,
1658 args->spy,
1659 args->whisper,
1660 args->app,
1661 args->app_args,
1662 args->snoop_id,
1663 response);
1664}
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 1666 of file resource_channels.c.

1669{
1671 args->channel_id,
1672 args->spy,
1673 args->whisper,
1674 args->app,
1675 args->app_args,
1676 args->snoop_id,
1677 response);
1678}

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

560{
561 RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
562
563 control = find_control(response, args->channel_id);
564 if (control == NULL) {
565 /* Response filled in by find_control */
566 return;
567 }
568
569 if (channel_state_invalid(control, response)) {
570 return;
571 }
572
573 stasis_app_control_moh_start(control, args->moh_class);
575}
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:806

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

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 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
595}
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:824

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

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

2361{
2363 RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
2364 RAII_VAR(struct ast_channel *, chan, NULL, ast_channel_cleanup);
2365
2366 control = find_control(response, args->channel_id);
2367 if (control == NULL) {
2368 /* Response filled in by find_control */
2369 return;
2370 }
2371
2372 chan = ast_channel_get_by_name(args->channel_id);
2373 if (!chan) {
2374 ast_ari_response_error(response, 404, "Not Found",
2375 "Callee not found");
2376 return;
2377 }
2378
2379 if (ast_strlen_zero(args->states)) {
2380 ast_ari_response_error(response, 400, "Bad Request", "states must not be empty");
2381 return;
2382 }
2383
2384 if (strcasecmp(args->states, "channel_progress") == 0) {
2386 } else if (strcasecmp(args->states, "channel_answered") == 0) {
2388 } else if (strcasecmp(args->states, "channel_unavailable") == 0) {
2390 } else if (strcasecmp(args->states, "channel_declined") == 0) {
2392 } else {
2393 ast_ari_response_error(response, 400, "Bad Request", "Invalid states value");
2394 return;
2395 }
2396
2399}
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:4608
ast_control_transfer
@ AST_TRANSFER_FAILED
@ AST_TRANSFER_UNAVAILABLE
@ AST_TRANSFER_SUCCESS
@ AST_TRANSFER_PROGRESS
@ AST_CONTROL_TRANSFER

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

Referenced by ast_ari_channels_transfer_progress_cb().

◆ ast_ari_channels_unhold()

void ast_ari_channels_unhold ( struct ast_variable headers,
struct ast_ari_channels_unhold_args args,
struct ast_ari_response response 
)

Remove a channel from hold.

Parameters
headersHTTP headers
argsSwagger parameters
[out]responseHTTP response

Definition at line 536 of file resource_channels.c.

539{
540 RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
541
542 control = find_control(response, args->channel_id);
543 if (control == NULL) {
544 /* Response filled in by find_control */
545 return;
546 }
547
548 if (channel_state_invalid(control, response)) {
549 return;
550 }
551
553
555}
void stasis_app_control_unhold(struct stasis_app_control *control)
Remove the channel associated with the control from hold.
Definition: control.c:787

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

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

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

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

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

Referenced by ari_channel_thread(), and ast_ari_channels_create().

◆ channel_state_invalid()

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

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

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

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

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

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

Definition at line 109 of file resource_channels.c.

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

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

Referenced by ari_channels_handle_play(), ast_ari_channels_answer(), ast_ari_channels_continue_in_dialplan(), ast_ari_channels_hold(), ast_ari_channels_mute(), ast_ari_channels_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 2132 of file resource_channels.c.

2135{
2136 char *endpoint;
2137 struct ast_channel *chan;
2138 struct varshead *vars;
2139
2140 if (ast_strlen_zero(args->data)) {
2141 ast_ari_response_error(response, 400, "Bad Request", "data can not be empty");
2142 return 1;
2143 }
2144
2145 if (ast_asprintf(&endpoint, "AudioSocket/%s/%s",
2146 args->external_host, args->data) == -1) {
2147 return 1;
2148 }
2149
2151 endpoint,
2152 NULL,
2153 NULL,
2154 0,
2155 NULL,
2156 args->app,
2157 args->data,
2158 NULL,
2159 0,
2160 variables,
2161 args->channel_id,
2162 NULL,
2163 NULL,
2164 args->format,
2165 response);
2166
2167 ast_free(endpoint);
2168
2169 if (!chan) {
2170 return 1;
2171 }
2172
2173 ast_channel_lock(chan);
2174 vars = ast_channel_varshead(chan);
2175 if (vars && !AST_LIST_EMPTY(vars)) {
2176 ast_json_object_set(response->message, "channelvars", ast_json_channel_vars(vars));
2177 }
2178 ast_channel_unlock(chan);
2179 ast_channel_unref(chan);
2180 return 0;
2181}
struct varshead * ast_channel_varshead(struct ast_channel *chan)
int ast_json_object_set(struct ast_json *object, const char *key, struct ast_json *value)
Set a field in a JSON object.
Definition: json.c:414
struct ast_json * ast_json_channel_vars(struct varshead *channelvars)
Construct a JSON object from a ast_var_t list.
Definition: json.c:941
#define AST_LIST_EMPTY(head)
Checks whether the specified list contains any entries.
Definition: linkedlists.h:450
struct ast_json * message
Definition: ari.h:103

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

Referenced by ast_ari_channels_external_media().

◆ external_media_rtp_udp()

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

Definition at line 2085 of file resource_channels.c.

2088{
2089 char *endpoint;
2090 struct ast_channel *chan;
2091 struct varshead *vars;
2092
2093 if (ast_asprintf(&endpoint, "UnicastRTP/%s/c(%s)",
2094 args->external_host,
2095 args->format) == -1) {
2096 return 1;
2097 }
2098
2100 endpoint,
2101 NULL,
2102 NULL,
2103 0,
2104 NULL,
2105 args->app,
2106 args->data,
2107 NULL,
2108 0,
2109 variables,
2110 args->channel_id,
2111 NULL,
2112 NULL,
2113 args->format,
2114 response);
2115
2116 ast_free(endpoint);
2117
2118 if (!chan) {
2119 return 1;
2120 }
2121
2122 ast_channel_lock(chan);
2123 vars = ast_channel_varshead(chan);
2124 if (vars && !AST_LIST_EMPTY(vars)) {
2125 ast_json_object_set(response->message, "channelvars", ast_json_channel_vars(vars));
2126 }
2127 ast_channel_unlock(chan);
2128 ast_channel_unref(chan);
2129 return 0;
2130}

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

2186{
2187 char *endpoint;
2188 struct ast_channel *chan;
2189 struct varshead *vars;
2190
2191 if (ast_asprintf(&endpoint, "WebSocket/%s/c(%s)",
2192 args->external_host,
2193 args->format) == -1) {
2194 return 1;
2195 }
2196
2198 endpoint,
2199 NULL,
2200 NULL,
2201 0,
2202 NULL,
2203 args->app,
2204 args->data,
2205 NULL,
2206 0,
2207 variables,
2208 args->channel_id,
2209 NULL,
2210 NULL,
2211 args->format,
2212 response);
2213
2214 ast_free(endpoint);
2215
2216 if (!chan) {
2217 return 1;
2218 }
2219
2220 ast_channel_lock(chan);
2221 vars = ast_channel_varshead(chan);
2222 if (vars && !AST_LIST_EMPTY(vars)) {
2223 ast_json_object_set(response->message, "channelvars", ast_json_channel_vars(vars));
2224 }
2225 ast_channel_unlock(chan);
2226 ast_channel_unref(chan);
2227 return 0;
2228}

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

Referenced by ast_ari_channels_external_media().

◆ find_control()

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

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

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

Definition at line 153 of file resource_channels.c.

156{
157 RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
158
159 ast_assert(response != NULL);
160
161 control = stasis_app_control_find_by_channel_id(channel_id);
162 if (control == NULL) {
163 /* Distinguish between 404 and 409 errors */
164 RAII_VAR(struct ast_channel *, chan, NULL, ao2_cleanup);
165 chan = ast_channel_get_by_name(channel_id);
166 if (chan == NULL) {
167 ast_ari_response_error(response, 404, "Not Found",
168 "Channel not found");
169 return NULL;
170 }
171
172 ast_ari_response_error(response, 409, "Conflict",
173 "Channel not in Stasis application");
174 return NULL;
175 }
176
177 ao2_ref(control, +1);
178 return control;
179}
struct stasis_app_control * stasis_app_control_find_by_channel_id(const char *channel_id)
Returns the handler for the channel with the given id.
Definition: res_stasis.c:349

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

Referenced by ari_channels_handle_play(), ast_ari_channels_answer(), ast_ari_channels_continue_in_dialplan(), ast_ari_channels_dial(), ast_ari_channels_hold(), ast_ari_channels_move(), ast_ari_channels_mute(), ast_ari_channels_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 1374 of file resource_channels.c.

1375{
1377
1378 res = ast_json_to_ast_variables(json_variables, variables);
1379 switch (res) {
1381 return 0;
1383 ast_ari_response_error(response, 400, "Bad Request",
1384 "Only string values in the 'variables' object allowed");
1385 break;
1388 break;
1389 }
1390 ast_log(AST_LOG_ERROR, "Unable to convert 'variables' in JSON body to channel variables\n");
1391
1392 return -1;
1393}
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 1767 of file resource_channels.c.

1768{
1769 struct ast_datastore *datastore;
1770
1771 datastore = ast_channel_datastore_find(chan, &dialstring_info, NULL);
1772 if (!datastore) {
1773 return NULL;
1774 }
1775
1776 return datastore->data;
1777}
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:2368
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 1733 of file resource_channels.c.

1734{
1735 struct ast_datastore *datastore;
1736
1738 if (!datastore) {
1739 return -1;
1740 }
1741
1742 datastore->data = ast_strdup(dialstring);
1743 if (!datastore->data) {
1744 ast_datastore_free(datastore);
1745 return -1;
1746 }
1747
1748 ast_channel_lock(chan);
1749 if (ast_channel_datastore_add(chan, datastore)) {
1750 ast_channel_unlock(chan);
1751 ast_datastore_free(datastore);
1752 return -1;
1753 }
1754 ast_channel_unlock(chan);
1755
1756 return 0;
1757}
#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:2354
#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 1718 of file resource_channels.c.

Referenced by restore_dialstring(), and save_dialstring().