Asterisk - The Open Source Telephony Project GIT-master-57e2743
Loading...
Searching...
No Matches
Data Structures | Functions | Variables
dialplan_functions.c File Reference

PJSIP channel dialplan functions. More...

#include "asterisk.h"
#include <pjsip.h>
#include <pjlib.h>
#include <pjsip_ua.h>
#include "asterisk/astobj2.h"
#include "asterisk/module.h"
#include "asterisk/acl.h"
#include "asterisk/app.h"
#include "asterisk/conversions.h"
#include "asterisk/channel.h"
#include "asterisk/stream.h"
#include "asterisk/format.h"
#include "asterisk/dsp.h"
#include "asterisk/pbx.h"
#include "asterisk/res_pjsip.h"
#include "asterisk/res_pjsip_session.h"
#include "include/chan_pjsip.h"
#include "include/channel_info.h"
#include "include/dialplan_functions.h"
Include dependency graph for dialplan_functions.c:

Go to the source code of this file.

Data Structures

struct  hangup_data
 
struct  media_offer_data
 
struct  parse_uri_args
 Struct used to push PJSIP_PARSE_URI function arguments to task processor. More...
 
struct  refresh_data
 
struct  session_refresh_state
 Session refresh state information. More...
 

Functions

static int channel_read_pjsip (struct ast_channel *chan, struct ast_sip_session *session, const char *type, char *buf, size_t len)
 
static int channel_read_rtcp (struct ast_channel *chan, struct ast_rtp_instance *rtp, const char *type, const char *field, char *buf, size_t buflen)
 
static int channel_read_rtp (struct ast_channel *chan, struct ast_rtp_instance *rtp, const struct ast_sockaddr *direct_media_addr, unsigned int secure, unsigned int held, const char *type, const char *field, char *buf, size_t buflen)
 
static int copy_escaped_uri (struct ast_channel *chan, const char *type, const struct pjsip_channel_uri *uri, char *buf, size_t size)
 
static int dtmf_mode_refresh_cb (void *obj)
 
static int media_offer_read_av (struct ast_sip_session *session, char *buf, size_t len, enum ast_media_type media_type)
 
static int media_offer_write_av (void *obj)
 
static int parse_uri_cb (void *data)
 
int pjsip_acf_channel_read (struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
 CHANNEL function read callback.
 
int pjsip_acf_dial_contacts_read (struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
 PJSIP_DIAL_CONTACTS function read callback.
 
int pjsip_acf_dtmf_mode_read (struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
 PJSIP_DTMF_MODE function read callback.
 
int pjsip_acf_dtmf_mode_write (struct ast_channel *chan, const char *cmd, char *data, const char *value)
 PJSIP_DTMF_MODE function write callback.
 
int pjsip_acf_media_offer_read (struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
 PJSIP_MEDIA_OFFER function read callback.
 
int pjsip_acf_media_offer_write (struct ast_channel *chan, const char *cmd, char *data, const char *value)
 PJSIP_MEDIA_OFFER function write callback.
 
int pjsip_acf_moh_passthrough_read (struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
 PJSIP_MOH_PASSTHROUGH function read callback.
 
int pjsip_acf_moh_passthrough_write (struct ast_channel *chan, const char *cmd, char *data, const char *value)
 PJSIP_MOH_PASSTHROUGH function write callback.
 
int pjsip_acf_parse_uri_read (struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
 PJSIP_PARSE_URI function read callback.
 
int pjsip_acf_session_refresh_write (struct ast_channel *chan, const char *cmd, char *data, const char *value)
 PJSIP_SEND_SESSION_REFRESH function write callback.
 
int pjsip_action_hangup (struct mansession *s, const struct message *m)
 PJSIPHangup Manager Action.
 
int pjsip_app_hangup (struct ast_channel *chan, const char *data)
 PJSIPHangup Dialplan App.
 
static void pjsip_app_hangup_handler (struct ast_channel *chan, int response_code)
 Called by pjsip_app_hangup and pjsip_action_hangup to actually perform the hangup.
 
static int pjsip_hangup (void *obj)
 Serializer task to hangup channel.
 
int pjsip_transfer_handling_write (struct ast_channel *chan, const char *cmd, char *data, const char *value)
 PJSIP_TRANSFER_HANDLING function write callback.
 
static int read_request_uri (struct ast_channel *chan, struct ast_sip_session *session, char *buf, size_t size)
 
static int refresh_write_cb (void *obj)
 
static int response_code_validator (const char *channel_name, const char *response)
 Callback that validates the response code.
 
static void session_refresh_state_destroy (void *obj)
 Destructor for session refresh information.
 
static struct session_refresh_state * session_refresh_state_get_or_alloc (struct ast_sip_session *session)
 Helper function which retrieves or allocates a session refresh state information datastore.
 
static int sip_session_response_cb (struct ast_sip_session *session, pjsip_rx_data *rdata)
 

Variables

static const struct ast_datastore_info session_refresh_datastore
 Datastore for attaching session refresh state information.
 
static const char * t38state_to_string [T38_MAX_ENUM]
 String representations of the T.38 state enum.
 

Detailed Description

PJSIP channel dialplan functions.

Author
Joshua Colp <jcolp@digium.com> 
Matt Jordan <mjordan@digium.com> 

Definition in file dialplan_functions.c.

Function Documentation

◆ channel_read_pjsip()

static int channel_read_pjsip ( struct ast_channel *  chan,
struct ast_sip_session *  session,
const char *  type,
char *  buf,
size_t  len 
)
static

Definition at line 264 of file dialplan_functions.c.

266{
267 const struct pjsip_channel_info *info;
268
269 if (ast_strlen_zero(type)) {
270 ast_log(LOG_WARNING, "You must supply a type field for 'pjsip' information\n");
271 return -1;
272 }
273
274 if (!strcmp(type, "call-id") || !strcmp(type, "local_tag")) {
275 pjsip_dialog *dlg = session->inv_session ? session->inv_session->dlg : NULL;
276
277 if (!dlg) {
278 return -1;
279 }
280 /* These identities are fixed for the lifetime of the retained dialog. */
281 if (!strcmp(type, "call-id")) {
282 ast_copy_pj_str(buf, &dlg->call_id->id, len);
283 } else {
284 char *copy;
285
286 ast_copy_pj_str(buf, &dlg->local.info->tag, len);
289 }
290 return 0;
291 }
292 if (!strcmp(type, "request_uri")) {
293 return read_request_uri(chan, session, buf, len);
294 }
295 if (!strcmp(type, "t38state")) {
296 if (session->t38state < 0 || session->t38state >= T38_MAX_ENUM) {
297 return -1;
298 }
300 return 0;
301 }
302 if (!strcmp(type, "local_addr") || !strcmp(type, "remote_addr")) {
305 struct transport_info_data *transport;
306 const pj_sockaddr *addr;
307
308 if (!datastore) {
309 ast_log(LOG_WARNING, "No transport information for channel %s\n",
310 ast_channel_name(chan));
311 return -1;
312 }
313 /* The transport payload is fully initialized before publication and immutable. */
314 transport = datastore->data;
315 addr = !strcmp(type, "local_addr") ? &transport->local_addr : &transport->remote_addr;
316 if (pj_sockaddr_has_addr(addr)) {
317 pj_sockaddr_print(addr, buf, len, 3);
318 }
319 return 0;
320 }
321
323 if (!info) {
324 ast_log(LOG_WARNING, "Channel %s has no PJSIP channel information\n",
325 ast_channel_name(chan));
326 return -1;
327 }
328 if (!strcmp(type, "secure")) {
329#ifdef HAVE_PJSIP_GET_DEST_INFO
330 if (info->secure < 0) {
331 return -1;
332 }
333 snprintf(buf, len, "%d", info->secure);
334#else
335 ast_log(LOG_WARNING, "Asterisk was built without support for CHANNEL(pjsip,secure)\n");
336 return -1;
337#endif
338 } else if (!strcmp(type, "target_uri")) {
339 return copy_escaped_uri(chan, type, &info->target_uri, buf, len);
340 } else if (!strcmp(type, "local_uri")) {
341 return copy_escaped_uri(chan, type, &info->local_uri, buf, len);
342 } else if (!strcmp(type, "remote_uri")) {
343 return copy_escaped_uri(chan, type, &info->remote_uri, buf, len);
344 } else if (!strcmp(type, "remote_tag")) {
345 if (!info->remote_tag) {
346 return -1;
347 }
348 ast_escape_quoted(info->remote_tag, buf, len);
349 } else {
350 ast_log(LOG_WARNING, "Unrecognized argument '%s' for 'pjsip' information\n", type);
351 return -1;
352 }
353 return 0;
354}
static int copy(char *infile, char *outfile)
Utility function to copy a file.
static struct ast_mansession session
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition astmm.h:298
#define ast_log
Definition astobj2.c:42
#define ao2_cleanup(obj)
Definition astobj2.h:1934
static const char type[]
const char * ast_channel_name(const struct ast_channel *chan)
struct pjsip_channel_info * pjsip_channel_info_get(struct ast_channel *chan)
Find the channel's information, or NULL if it has none.
static int read_request_uri(struct ast_channel *chan, struct ast_sip_session *session, char *buf, size_t size)
static const char * t38state_to_string[T38_MAX_ENUM]
String representations of the T.38 state enum.
static int copy_escaped_uri(struct ast_channel *chan, const char *type, const struct pjsip_channel_uri *uri, char *buf, size_t size)
char buf[BUFSIZE]
Definition eagi_proxy.c:66
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
#define LOG_WARNING
void ast_copy_pj_str(char *dest, const pj_str_t *src, size_t size)
Copy a pj_str_t into a standard character buffer.
Definition res_pjsip.c:2221
struct ast_datastore * ast_sip_session_get_datastore(struct ast_sip_session *session, const char *name)
Retrieve a session datastore.
@ T38_MAX_ENUM
#define NULL
Definition resample.c:96
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition strings.h:65
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition strings.h:425
Structure for a data store object.
Definition datastore.h:64
struct ast_datastore * datastore
Transport information stored in transport_info datastore.
Definition chan_pjsip.h:30
pj_sockaddr local_addr
Our address that received the request.
Definition chan_pjsip.h:34
pj_sockaddr remote_addr
The address that sent the request.
Definition chan_pjsip.h:32
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition utils.h:981
char * ast_escape_quoted(const char *string, char *outbuf, int buflen)
Escape characters found in a quoted string.
Definition utils.c:815

References ao2_cleanup, ast_channel_name(), ast_copy_pj_str(), ast_copy_string(), ast_escape_quoted(), ast_log, ast_sip_session_get_datastore(), ast_strdupa, ast_strlen_zero(), buf, copy(), copy_escaped_uri(), pjsip_channel_info::datastore, len(), transport_info_data::local_addr, LOG_WARNING, NULL, pjsip_channel_info_get(), RAII_VAR, read_request_uri(), transport_info_data::remote_addr, session, T38_MAX_ENUM, t38state_to_string, and type.

Referenced by pjsip_acf_channel_read().

◆ channel_read_rtcp()

static int channel_read_rtcp ( struct ast_channel *  chan,
struct ast_rtp_instance *  rtp,
const char *  type,
const char *  field,
char *  buf,
size_t  buflen 
)
static

Definition at line 129 of file dialplan_functions.c.

131{
132 if (ast_strlen_zero(type)) {
133 ast_log(AST_LOG_WARNING, "You must supply a type field for 'rtcp' information\n");
134 return -1;
135 }
136
137 if (!ast_strlen_zero(field) && strcmp(field, "audio") && strcmp(field, "video")) {
138 ast_log(AST_LOG_WARNING, "Unknown media type field '%s' for 'rtcp' information\n", field);
139 return -1;
140 }
141
142 if (!rtp) {
143 ast_log(AST_LOG_WARNING, "Channel %s has no %s media/RTP session\n",
144 ast_channel_name(chan), S_OR(field, "audio"));
145 return -1;
146 }
147
148 if (!strncasecmp(type, "all", 3)) {
150
151 if (!strcasecmp(type, "all_jitter")) {
153 } else if (!strcasecmp(type, "all_rtt")) {
155 } else if (!strcasecmp(type, "all_loss")) {
157 } else if (!strcasecmp(type, "all_mes")) {
159 }
160
161 if (!ast_rtp_instance_get_quality(rtp, stat_field, buf, buflen)) {
162 ast_log(AST_LOG_WARNING, "Unable to retrieve 'rtcp' statistics for %s\n", ast_channel_name(chan));
163 return -1;
164 }
165 } else {
166 struct ast_rtp_instance_stats stats;
167 int i;
168 struct {
169 const char *name;
170 enum { INT, DBL } type;
171 union {
172 unsigned int *i4;
173 double *d8;
174 };
175 } lookup[] = {
176 { "txcount", INT, { .i4 = &stats.txcount, }, },
177 { "rxcount", INT, { .i4 = &stats.rxcount, }, },
178 { "txjitter", DBL, { .d8 = &stats.txjitter, }, },
179 { "rxjitter", DBL, { .d8 = &stats.rxjitter, }, },
180 { "remote_maxjitter", DBL, { .d8 = &stats.remote_maxjitter, }, },
181 { "remote_minjitter", DBL, { .d8 = &stats.remote_minjitter, }, },
182 { "remote_normdevjitter", DBL, { .d8 = &stats.remote_normdevjitter, }, },
183 { "remote_stdevjitter", DBL, { .d8 = &stats.remote_stdevjitter, }, },
184 { "local_maxjitter", DBL, { .d8 = &stats.local_maxjitter, }, },
185 { "local_minjitter", DBL, { .d8 = &stats.local_minjitter, }, },
186 { "local_normdevjitter", DBL, { .d8 = &stats.local_normdevjitter, }, },
187 { "local_stdevjitter", DBL, { .d8 = &stats.local_stdevjitter, }, },
188 { "txploss", INT, { .i4 = &stats.txploss, }, },
189 { "rxploss", INT, { .i4 = &stats.rxploss, }, },
190 { "remote_maxrxploss", DBL, { .d8 = &stats.remote_maxrxploss, }, },
191 { "remote_minrxploss", DBL, { .d8 = &stats.remote_minrxploss, }, },
192 { "remote_normdevrxploss", DBL, { .d8 = &stats.remote_normdevrxploss, }, },
193 { "remote_stdevrxploss", DBL, { .d8 = &stats.remote_stdevrxploss, }, },
194 { "local_maxrxploss", DBL, { .d8 = &stats.local_maxrxploss, }, },
195 { "local_minrxploss", DBL, { .d8 = &stats.local_minrxploss, }, },
196 { "local_normdevrxploss", DBL, { .d8 = &stats.local_normdevrxploss, }, },
197 { "local_stdevrxploss", DBL, { .d8 = &stats.local_stdevrxploss, }, },
198 { "rtt", DBL, { .d8 = &stats.rtt, }, },
199 { "maxrtt", DBL, { .d8 = &stats.maxrtt, }, },
200 { "minrtt", DBL, { .d8 = &stats.minrtt, }, },
201 { "normdevrtt", DBL, { .d8 = &stats.normdevrtt, }, },
202 { "stdevrtt", DBL, { .d8 = &stats.stdevrtt, }, },
203 { "local_ssrc", INT, { .i4 = &stats.local_ssrc, }, },
204 { "remote_ssrc", INT, { .i4 = &stats.remote_ssrc, }, },
205 { "txmes", DBL, { .d8 = &stats.txmes, }, },
206 { "rxmes", DBL, { .d8 = &stats.rxmes, }, },
207 { "remote_maxmes", DBL, { .d8 = &stats.remote_maxmes, }, },
208 { "remote_minmes", DBL, { .d8 = &stats.remote_minmes, }, },
209 { "remote_normdevmes", DBL, { .d8 = &stats.remote_normdevmes, }, },
210 { "remote_stdevmes", DBL, { .d8 = &stats.remote_stdevmes, }, },
211 { "local_maxmes", DBL, { .d8 = &stats.local_maxmes, }, },
212 { "local_minmes", DBL, { .d8 = &stats.local_minmes, }, },
213 { "local_normdevmes", DBL, { .d8 = &stats.local_normdevmes, }, },
214 { "local_stdevmes", DBL, { .d8 = &stats.local_stdevmes, }, },
215 { NULL, },
216 };
217
219 ast_log(AST_LOG_WARNING, "Unable to retrieve 'rtcp' statistics for %s\n", ast_channel_name(chan));
220 return -1;
221 }
222
223 for (i = 0; !ast_strlen_zero(lookup[i].name); i++) {
224 if (!strcasecmp(type, lookup[i].name)) {
225 if (lookup[i].type == INT) {
226 snprintf(buf, buflen, "%u", *lookup[i].i4);
227 } else {
228 snprintf(buf, buflen, "%f", *lookup[i].d8);
229 }
230 return 0;
231 }
232 }
233 ast_log(AST_LOG_WARNING, "Unrecognized argument '%s' for 'rtcp' information\n", type);
234 return -1;
235 }
236
237 return 0;
238}
static const char name[]
Definition format_mp3.c:68
#define AST_LOG_WARNING
ast_rtp_instance_stat_field
Definition rtp_engine.h:171
@ AST_RTP_INSTANCE_STAT_FIELD_QUALITY_LOSS
Definition rtp_engine.h:177
@ AST_RTP_INSTANCE_STAT_FIELD_QUALITY_RTT
Definition rtp_engine.h:179
@ AST_RTP_INSTANCE_STAT_FIELD_QUALITY
Definition rtp_engine.h:173
@ AST_RTP_INSTANCE_STAT_FIELD_QUALITY_JITTER
Definition rtp_engine.h:175
@ AST_RTP_INSTANCE_STAT_FIELD_QUALITY_MES
Definition rtp_engine.h:181
@ AST_RTP_INSTANCE_STAT_ALL
Definition rtp_engine.h:187
char * ast_rtp_instance_get_quality(struct ast_rtp_instance *instance, enum ast_rtp_instance_stat_field field, char *buf, size_t size)
Retrieve quality statistics about an RTP instance.
int ast_rtp_instance_get_stats(struct ast_rtp_instance *instance, struct ast_rtp_instance_stats *stats, enum ast_rtp_instance_stat stat)
Retrieve statistics about an RTP instance.
#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

References ast_channel_name(), ast_log, AST_LOG_WARNING, ast_rtp_instance_get_quality(), ast_rtp_instance_get_stats(), AST_RTP_INSTANCE_STAT_ALL, AST_RTP_INSTANCE_STAT_FIELD_QUALITY, AST_RTP_INSTANCE_STAT_FIELD_QUALITY_JITTER, AST_RTP_INSTANCE_STAT_FIELD_QUALITY_LOSS, AST_RTP_INSTANCE_STAT_FIELD_QUALITY_MES, AST_RTP_INSTANCE_STAT_FIELD_QUALITY_RTT, ast_strlen_zero(), buf, ast_rtp_instance_stats::local_maxjitter, ast_rtp_instance_stats::local_maxmes, ast_rtp_instance_stats::local_maxrxploss, ast_rtp_instance_stats::local_minjitter, ast_rtp_instance_stats::local_minmes, ast_rtp_instance_stats::local_minrxploss, ast_rtp_instance_stats::local_normdevjitter, ast_rtp_instance_stats::local_normdevmes, ast_rtp_instance_stats::local_normdevrxploss, ast_rtp_instance_stats::local_ssrc, ast_rtp_instance_stats::local_stdevjitter, ast_rtp_instance_stats::local_stdevmes, ast_rtp_instance_stats::local_stdevrxploss, ast_rtp_instance_stats::maxrtt, ast_rtp_instance_stats::minrtt, name, ast_rtp_instance_stats::normdevrtt, NULL, ast_rtp_instance_stats::remote_maxjitter, ast_rtp_instance_stats::remote_maxmes, ast_rtp_instance_stats::remote_maxrxploss, ast_rtp_instance_stats::remote_minjitter, ast_rtp_instance_stats::remote_minmes, ast_rtp_instance_stats::remote_minrxploss, ast_rtp_instance_stats::remote_normdevjitter, ast_rtp_instance_stats::remote_normdevmes, ast_rtp_instance_stats::remote_normdevrxploss, ast_rtp_instance_stats::remote_ssrc, ast_rtp_instance_stats::remote_stdevjitter, ast_rtp_instance_stats::remote_stdevmes, ast_rtp_instance_stats::remote_stdevrxploss, ast_rtp_instance_stats::rtt, ast_rtp_instance_stats::rxcount, ast_rtp_instance_stats::rxjitter, ast_rtp_instance_stats::rxmes, ast_rtp_instance_stats::rxploss, S_OR, ast_rtp_instance_stats::stdevrtt, ast_rtp_instance_stats::txcount, ast_rtp_instance_stats::txjitter, ast_rtp_instance_stats::txmes, ast_rtp_instance_stats::txploss, and type.

Referenced by pjsip_acf_channel_read().

◆ channel_read_rtp()

static int channel_read_rtp ( struct ast_channel *  chan,
struct ast_rtp_instance *  rtp,
const struct ast_sockaddr *  direct_media_addr,
unsigned int  secure,
unsigned int  held,
const char *  type,
const char *  field,
char *  buf,
size_t  buflen 
)
static

Definition at line 84 of file dialplan_functions.c.

87{
88 struct ast_sockaddr addr;
89
90 if (ast_strlen_zero(type)) {
91 ast_log(AST_LOG_WARNING, "You must supply a type field for 'rtp' information\n");
92 return -1;
93 }
94
95 if (!ast_strlen_zero(field) && strcmp(field, "audio") && strcmp(field, "video")) {
96 ast_log(AST_LOG_WARNING, "Unknown media type field '%s' for 'rtp' information\n", field);
97 return -1;
98 }
99
100 if (!rtp) {
101 ast_log(AST_LOG_WARNING, "Channel %s has no %s media/RTP session\n",
102 ast_channel_name(chan), S_OR(field, "audio"));
103 return -1;
104 }
105
106 if (!strcmp(type, "src")) {
109 } else if (!strcmp(type, "dest")) {
112 } else if (!strcmp(type, "direct")) {
113 ast_copy_string(buf, ast_sockaddr_stringify(direct_media_addr), buflen);
114 } else if (!strcmp(type, "secure")) {
115 snprintf(buf, buflen, "%u", secure);
116 } else if (!strcmp(type, "hold")) {
117 snprintf(buf, buflen, "%u", held);
118 } else {
119 ast_log(AST_LOG_WARNING, "Unknown type field '%s' specified for 'rtp' information\n", type);
120 return -1;
121 }
122
123 return 0;
124}
static char * ast_sockaddr_stringify(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() with default format.
Definition netsock2.h:256
#define ast_rtp_instance_get_remote_address(instance, address)
Get the address of the remote endpoint that we are sending RTP to.
void ast_rtp_instance_get_local_address(struct ast_rtp_instance *instance, struct ast_sockaddr *address)
Get the local address that we are expecting RTP on.
Definition rtp_engine.c:694
Socket address structure.
Definition netsock2.h:97

References ast_channel_name(), ast_copy_string(), ast_log, AST_LOG_WARNING, ast_rtp_instance_get_local_address(), ast_rtp_instance_get_remote_address, ast_sockaddr_stringify(), ast_strlen_zero(), buf, S_OR, and type.

Referenced by pjsip_acf_channel_read().

◆ copy_escaped_uri()

static int copy_escaped_uri ( struct ast_channel *  chan,
const char *  type,
const struct pjsip_channel_uri *  uri,
char *  buf,
size_t  size 
)
static

Definition at line 68 of file dialplan_functions.c.

70{
71 if (uri->length < 0 || uri->length >= size) {
72 ast_log(LOG_ERROR, "Channel %s: Unescaped %s too long for %zu byte buffer\n",
73 ast_channel_name(chan), type, size);
74 buf[0] = '\0';
75 return -1;
76 }
77 ast_escape_quoted(uri->value, buf, size);
78 return 0;
79}
#define LOG_ERROR
char value[PJSIP_MAX_URL_SIZE]

References ast_channel_name(), ast_escape_quoted(), ast_log, buf, pjsip_channel_uri::length, LOG_ERROR, type, and pjsip_channel_uri::value.

Referenced by channel_read_pjsip().

◆ dtmf_mode_refresh_cb()

static int dtmf_mode_refresh_cb ( void *  obj)
static

Definition at line 1013 of file dialplan_functions.c.

1014{
1015 struct refresh_data *data = obj;
1016
1017 if (data->session->inv_session->state == PJSIP_INV_STATE_CONFIRMED) {
1018 ast_debug(3, "Changing DTMF mode on channel %s after OFFER/ANSWER completion. Sending session refresh\n", ast_channel_name(data->session->channel));
1019
1022 } else if (data->session->inv_session->state == PJSIP_INV_STATE_INCOMING) {
1023 ast_debug(3, "Changing DTMF mode on channel %s during OFFER/ANSWER exchange. Updating SDP answer\n", ast_channel_name(data->session->channel));
1025 }
1026
1027 return 0;
1028}
static int sip_session_response_cb(struct ast_sip_session *session, pjsip_rx_data *rdata)
#define ast_debug(level,...)
Log a DEBUG message.
int ast_sip_session_regenerate_answer(struct ast_sip_session *session, ast_sip_session_sdp_creation_cb on_sdp_creation)
Regenerate SDP Answer.
int ast_sip_session_refresh(struct ast_sip_session *session, ast_sip_session_request_creation_cb on_request_creation, ast_sip_session_sdp_creation_cb on_sdp_creation, ast_sip_session_response_cb on_response, enum ast_sip_session_refresh_method method, int generate_new_sdp, struct ast_sip_session_media_state *media_state)
Send a reinvite or UPDATE on a session.
struct ast_channel * channel
struct pjsip_inv_session * inv_session
struct ast_sip_session * session
enum ast_sip_session_refresh_method method

References ast_channel_name(), ast_debug, ast_sip_session_refresh(), ast_sip_session_regenerate_answer(), ast_sip_session::channel, ast_sip_session::inv_session, refresh_data::method, NULL, refresh_data::session, and sip_session_response_cb().

Referenced by pjsip_acf_dtmf_mode_write().

◆ media_offer_read_av()

static int media_offer_read_av ( struct ast_sip_session *  session,
char *  buf,
size_t  len,
enum ast_media_type  media_type 
)
static

Definition at line 732 of file dialplan_functions.c.

734{
735 struct ast_stream_topology *topology;
736 int idx;
737 struct ast_stream *stream = NULL;
738 const struct ast_format_cap *caps;
739 size_t accum = 0;
740
741 if (session->inv_session->dlg->state == PJSIP_DIALOG_STATE_ESTABLISHED) {
743
744 /* As we've already answered we need to store our media state until we are ready to send it */
746 if (!state) {
747 return -1;
748 }
749 topology = state->media_state->topology;
750 } else {
751 /* The session is not yet up so we are initially answering or offering */
752 if (!session->pending_media_state->topology) {
753 session->pending_media_state->topology = ast_stream_topology_clone(session->endpoint->media.topology);
754 if (!session->pending_media_state->topology) {
755 return -1;
756 }
757 }
758 topology = session->pending_media_state->topology;
759 }
760
761 /* Find the first suitable stream */
762 for (idx = 0; idx < ast_stream_topology_get_count(topology); ++idx) {
763 stream = ast_stream_topology_get_stream(topology, idx);
764
765 if (ast_stream_get_type(stream) != media_type ||
767 stream = NULL;
768 continue;
769 }
770
771 break;
772 }
773
774 /* If no suitable stream then exit early */
775 if (!stream) {
776 buf[0] = '\0';
777 return 0;
778 }
779
780 caps = ast_stream_get_formats(stream);
781
782 /* Note: buf is not terminated while the string is being built. */
783 for (idx = 0; idx < ast_format_cap_count(caps); ++idx) {
784 struct ast_format *fmt;
785 size_t size;
786
787 fmt = ast_format_cap_get_format(caps, idx);
788
789 /* Add one for a comma or terminator */
790 size = strlen(ast_format_get_name(fmt)) + 1;
791 if (len < size) {
792 ao2_ref(fmt, -1);
793 break;
794 }
795
796 /* Append the format name */
797 strcpy(buf + accum, ast_format_get_name(fmt));/* Safe */
798 ao2_ref(fmt, -1);
799
800 accum += size;
801 len -= size;
802
803 /* The last comma on the built string will be set to the terminator. */
804 buf[accum - 1] = ',';
805 }
806
807 /* Remove the trailing comma or terminate an empty buffer. */
808 buf[accum ? accum - 1 : 0] = '\0';
809 return 0;
810}
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition astobj2.h:459
static struct session_refresh_state * session_refresh_state_get_or_alloc(struct ast_sip_session *session)
Helper function which retrieves or allocates a session refresh state information datastore.
const char * ast_format_get_name(const struct ast_format *format)
Get the name associated with a format.
Definition format.c:334
struct ast_format * ast_format_cap_get_format(const struct ast_format_cap *cap, int position)
Get the format at a specific index.
Definition format_cap.c:408
size_t ast_format_cap_count(const struct ast_format_cap *cap)
Get the number of formats present within the capabilities structure.
Definition format_cap.c:403
@ AST_STREAM_STATE_REMOVED
Set when the stream has been removed/declined.
Definition stream.h:78
struct ast_stream * ast_stream_topology_get_stream(const struct ast_stream_topology *topology, unsigned int position)
Get a specific stream from the topology.
Definition stream.c:791
int ast_stream_topology_get_count(const struct ast_stream_topology *topology)
Get the number of streams in a topology.
Definition stream.c:768
enum ast_stream_state ast_stream_get_state(const struct ast_stream *stream)
Get the current state of a stream.
Definition stream.c:373
enum ast_media_type ast_stream_get_type(const struct ast_stream *stream)
Get the media type of a stream.
Definition stream.c:316
const struct ast_format_cap * ast_stream_get_formats(const struct ast_stream *stream)
Get the current negotiated formats of a stream.
Definition stream.c:330
struct ast_stream_topology * ast_stream_topology_clone(const struct ast_stream_topology *topology)
Create a deep clone of an existing stream topology.
Definition stream.c:670
Format capabilities structure, holds formats + preference order + etc.
Definition format_cap.c:54
Definition of a media format.
Definition format.c:43
Session refresh state information.

References ao2_ref, ast_format_cap_count(), ast_format_cap_get_format(), ast_format_get_name(), ast_stream_get_formats(), ast_stream_get_state(), ast_stream_get_type(), AST_STREAM_STATE_REMOVED, ast_stream_topology_clone(), ast_stream_topology_get_count(), ast_stream_topology_get_stream(), buf, len(), NULL, session, and session_refresh_state_get_or_alloc().

Referenced by pjsip_acf_media_offer_read().

◆ media_offer_write_av()

static int media_offer_write_av ( void *  obj)
static

Definition at line 818 of file dialplan_functions.c.

819{
820 struct media_offer_data *data = obj;
821 struct ast_stream_topology *topology;
822 struct ast_stream *stream;
823 struct ast_format_cap *caps;
824
825 if (data->session->inv_session->dlg->state == PJSIP_DIALOG_STATE_ESTABLISHED) {
827
828 /* As we've already answered we need to store our media state until we are ready to send it */
830 if (!state) {
831 return -1;
832 }
833 topology = state->media_state->topology;
834 } else {
835 /* The session is not yet up so we are initially answering or offering */
836 if (!data->session->pending_media_state->topology) {
838 if (!data->session->pending_media_state->topology) {
839 return -1;
840 }
841 }
842 topology = data->session->pending_media_state->topology;
843 }
844
845 /* XXX This method won't work when it comes time to do multistream support. The proper way to do this
846 * will either be to
847 * a) Alter all media streams of a particular type.
848 * b) Change the dialplan function to be able to specify which stream to alter and alter only that
849 * one stream
850 */
852 if (!stream) {
853 return 0;
854 }
855
857 if (!caps) {
858 return -1;
859 }
860
865 ast_stream_set_formats(stream, caps);
866 ast_stream_set_metadata(stream, "pjsip_session_refresh", "force");
867 ao2_ref(caps, -1);
868
869 return 0;
870}
@ AST_MEDIA_TYPE_UNKNOWN
Definition codec.h:31
int ast_format_cap_update_by_allow_disallow(struct ast_format_cap *cap, const char *list, int allowing)
Parse an "allow" or "deny" list and modify a format capabilities structure accordingly.
Definition format_cap.c:328
void ast_format_cap_remove_by_type(struct ast_format_cap *cap, enum ast_media_type type)
Remove all formats matching a specific format type.
Definition format_cap.c:531
@ AST_FORMAT_CAP_FLAG_DEFAULT
Definition format_cap.h:38
int ast_format_cap_append_from_cap(struct ast_format_cap *dst, const struct ast_format_cap *src, enum ast_media_type type)
Append the formats of provided type in src to dst.
Definition format_cap.c:269
#define ast_format_cap_alloc(flags)
Allocate a new ast_format_cap structure.
Definition format_cap.h:49
int ast_stream_set_metadata(struct ast_stream *stream, const char *m_key, const char *value)
Set a stream metadata value.
Definition stream.c:460
void ast_stream_set_formats(struct ast_stream *stream, struct ast_format_cap *caps)
Set the current negotiated formats of a stream.
Definition stream.c:365
struct ast_stream * ast_stream_topology_get_first_stream_by_type(const struct ast_stream_topology *topology, enum ast_media_type type)
Gets the first active stream of a specific type from the topology.
Definition stream.c:967
struct ast_stream_topology * topology
Definition res_pjsip.h:1027
struct ast_sip_endpoint_media_configuration media
Definition res_pjsip.h:1100
struct ast_stream_topology * topology
The media stream topology.
struct ast_sip_endpoint * endpoint
struct ast_sip_session_media_state * pending_media_state
enum ast_media_type media_type
struct ast_sip_session * session

References ao2_ref, ast_format_cap_alloc, ast_format_cap_append_from_cap(), AST_FORMAT_CAP_FLAG_DEFAULT, ast_format_cap_remove_by_type(), ast_format_cap_update_by_allow_disallow(), AST_MEDIA_TYPE_UNKNOWN, ast_stream_get_formats(), ast_stream_set_formats(), ast_stream_set_metadata(), ast_stream_topology_clone(), ast_stream_topology_get_first_stream_by_type(), ast_sip_session::endpoint, ast_sip_session::inv_session, ast_sip_endpoint::media, media_offer_data::media_type, ast_sip_session::pending_media_state, media_offer_data::session, session_refresh_state_get_or_alloc(), ast_sip_endpoint_media_configuration::topology, ast_sip_session_media_state::topology, and media_offer_data::value.

Referenced by pjsip_acf_media_offer_write().

◆ parse_uri_cb()

static int parse_uri_cb ( void *  data)
static

Definition at line 599 of file dialplan_functions.c.

600{
601 struct parse_uri_args *args = data;
602 pj_pool_t *pool;
603 pjsip_name_addr *uri;
604 pjsip_sip_uri *sip_uri;
605 pj_str_t tmp;
606
607 args->ret = 0;
608
609 pool = pjsip_endpt_create_pool(ast_sip_get_pjsip_endpoint(), "ParseUri", 128, 128);
610 if (!pool) {
611 ast_log(LOG_ERROR, "Failed to allocate ParseUri endpoint pool.\n");
612 args->ret = -1;
613 return 0;
614 }
615
616 pj_strdup2_with_null(pool, &tmp, args->uri);
617 uri = (pjsip_name_addr *)pjsip_parse_uri(pool, tmp.ptr, tmp.slen, PJSIP_PARSE_URI_AS_NAMEADDR);
618 if (!uri || (!PJSIP_URI_SCHEME_IS_SIP(uri) && !PJSIP_URI_SCHEME_IS_SIPS(uri))) {
619 ast_log(LOG_WARNING, "Failed to parse URI '%s'\n", args->uri);
620 pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
621 args->ret = -1;
622 return 0;
623 }
624
625 if (!strcmp(args->type, "scheme")) {
626 ast_copy_pj_str(args->buf, pjsip_uri_get_scheme(uri), args->buflen);
627 pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
628 return 0;
629 } else if (!strcmp(args->type, "display")) {
630 ast_copy_pj_str(args->buf, &uri->display, args->buflen);
631 pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
632 return 0;
633 }
634
635 sip_uri = pjsip_uri_get_uri(uri);
636 if (!sip_uri) {
637 ast_log(LOG_ERROR, "Failed to get an URI object for '%s'\n", args->uri);
638 pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
639 args->ret = -1;
640 return 0;
641 }
642
643 if (!strcmp(args->type, "user")) {
644 ast_copy_pj_str(args->buf, &sip_uri->user, args->buflen);
645 } else if (!strcmp(args->type, "passwd")) {
646 ast_copy_pj_str(args->buf, &sip_uri->passwd, args->buflen);
647 } else if (!strcmp(args->type, "host")) {
648 ast_copy_pj_str(args->buf, &sip_uri->host, args->buflen);
649 } else if (!strcmp(args->type, "port")) {
650 snprintf(args->buf, args->buflen, "%d", sip_uri->port);
651 } else if (!strcmp(args->type, "user_param")) {
652 ast_copy_pj_str(args->buf, &sip_uri->user_param, args->buflen);
653 } else if (!strcmp(args->type, "method_param")) {
654 ast_copy_pj_str(args->buf, &sip_uri->method_param, args->buflen);
655 } else if (!strcmp(args->type, "transport_param")) {
656 ast_copy_pj_str(args->buf, &sip_uri->transport_param, args->buflen);
657 } else if (!strcmp(args->type, "ttl_param")) {
658 snprintf(args->buf, args->buflen, "%d", sip_uri->ttl_param);
659 } else if (!strcmp(args->type, "lr_param")) {
660 snprintf(args->buf, args->buflen, "%d", sip_uri->lr_param);
661 } else if (!strcmp(args->type, "maddr_param")) {
662 ast_copy_pj_str(args->buf, &sip_uri->maddr_param, args->buflen);
663 } else {
664 ast_log(AST_LOG_WARNING, "Unknown type part '%s' specified\n", args->type);
665 pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
666 args->ret = -1;
667 return 0;
668 }
669
670 pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
671
672 return 0;
673}
pjsip_endpoint * ast_sip_get_pjsip_endpoint(void)
Get a pointer to the PJSIP endpoint.
Definition res_pjsip.c:518
static struct @523 args
Struct used to push PJSIP_PARSE_URI function arguments to task processor.

References args, ast_copy_pj_str(), ast_log, AST_LOG_WARNING, ast_sip_get_pjsip_endpoint(), LOG_ERROR, LOG_WARNING, parse_uri_args::ret, and parse_uri_args::uri.

Referenced by pjsip_acf_parse_uri_read().

◆ pjsip_acf_channel_read()

int pjsip_acf_channel_read ( struct ast_channel *  chan,
const char *  cmd,
char *  data,
char *  buf,
size_t  len 
)

CHANNEL function read callback.

Parameters
chanThe channel the function is called on
cmdThe name of the function
dataArguments passed to the function
bufOut buffer that should be populated with the data
lenSize of the buffer
Return values
0on success
-1on failure

Definition at line 356 of file dialplan_functions.c.

357{
358 struct ast_sip_channel_pvt *channel;
359 char *parse = ast_strdupa(data);
360 int res = 0;
361
363 AST_APP_ARG(param);
365 AST_APP_ARG(field);
366 );
367
368 if (!chan) {
369 ast_log(LOG_WARNING, "No channel was provided to %s function.\n", cmd);
370 return -1;
371 }
372
373 /* Check for zero arguments */
374 if (ast_strlen_zero(parse)) {
375 ast_log(LOG_ERROR, "Cannot call %s without arguments\n", cmd);
376 return -1;
377 }
378
379 if (!len) {
380 ast_log(LOG_ERROR, "Cannot call %s without an output buffer\n", cmd);
381 return -1;
382 }
383
385
386 ast_channel_lock(chan);
387
388 /* Sanity check */
389 if (strcmp(ast_channel_tech(chan)->type, "PJSIP")) {
390 ast_log(LOG_WARNING, "Cannot call %s on a non-PJSIP channel\n", cmd);
391 ast_channel_unlock(chan);
392 return 0;
393 }
394
395 channel = ast_channel_tech_pvt(chan);
396 if (!channel) {
397 ast_log(LOG_WARNING, "Channel %s has no pvt!\n", ast_channel_name(chan));
398 ast_channel_unlock(chan);
399 return -1;
400 }
401
402 if (!channel->session) {
403 ast_log(LOG_WARNING, "Channel %s has no session\n", ast_channel_name(chan));
404 ast_channel_unlock(chan);
405 return -1;
406 }
407
408 memset(buf, 0, len);
409
410 if (!strcmp(args.param, "endpoint")) {
411 if (!channel->session->endpoint) {
412 res = -1;
413 } else {
415 }
416 } else if (!strcmp(args.param, "contact")) {
417 if (channel->session->contact) {
419 }
420 } else if (!strcmp(args.param, "aor")) {
421 if (channel->session->aor) {
423 }
424 } else if (!strcmp(args.param, "pjsip")) {
425 res = channel_read_pjsip(chan, channel->session, args.type, buf, len);
426 } else if (!strcmp(args.param, "rtp") || !strcmp(args.param, "rtcp")) {
427 const struct pjsip_channel_info *info = pjsip_channel_info_get(chan);
428 struct ast_rtp_instance *rtp;
429 struct ast_sip_session_media *media;
430 struct ast_sockaddr no_address = { { 0, } };
431 const struct ast_sockaddr *direct_media_addr;
432 unsigned int secure;
433 unsigned int held;
434 int video = !strcmp(S_OR(args.field, "audio"), "video");
435
436 if (!info) {
437 res = -1;
438 } else {
439 /* The channel lock keeps these retained instances alive throughout the read. */
440 rtp = video ? info->video_rtp : info->audio_rtp;
441 media = channel->session->active_media_state
444 direct_media_addr = media ? &media->direct_media_addr : &no_address;
445 secure = video ? info->video_secure : info->audio_secure;
446 held = video ? info->video_held : info->audio_held;
447 if (!strcmp(args.param, "rtp")) {
448 res = channel_read_rtp(chan, rtp, direct_media_addr, secure, held,
449 args.type, args.field, buf, len);
450 } else {
451 res = channel_read_rtcp(chan, rtp, args.type, args.field, buf, len);
452 }
453 }
454 } else {
455 res = -1;
456 }
457 ast_channel_unlock(chan);
458 return res;
459}
void * ast_channel_tech_pvt(const struct ast_channel *chan)
#define ast_channel_lock(chan)
Definition channel.h:2983
#define ast_channel_unlock(chan)
Definition channel.h:2984
@ AST_MEDIA_TYPE_AUDIO
Definition codec.h:32
@ AST_MEDIA_TYPE_VIDEO
Definition codec.h:33
static int channel_read_rtcp(struct ast_channel *chan, struct ast_rtp_instance *rtp, const char *type, const char *field, char *buf, size_t buflen)
static int channel_read_pjsip(struct ast_channel *chan, struct ast_sip_session *session, const char *type, char *buf, size_t len)
static int channel_read_rtp(struct ast_channel *chan, struct ast_rtp_instance *rtp, const struct ast_sockaddr *direct_media_addr, unsigned int secure, unsigned int held, const char *type, const char *field, char *buf, size_t buflen)
#define AST_APP_ARG(name)
Define an application argument.
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application's arguments.
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the 'standard' argument separation process for an application.
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
Definition sorcery.c:2381
Structure to describe a channel "technology", ie a channel driver See for examples:
Definition channel.h:648
A structure which contains a channel implementation and session.
struct ast_sip_session * session
Pointer to session.
struct ast_sip_session_media * default_session[AST_MEDIA_TYPE_END]
Default media sessions for each type.
A structure containing SIP session media information.
struct ast_sockaddr direct_media_addr
Direct media address.
struct ast_sip_contact * contact
struct ast_sip_session_media_state * active_media_state
struct ast_sip_aor * aor

References ast_sip_session::active_media_state, ast_sip_session::aor, args, AST_APP_ARG, ast_channel_lock, ast_channel_name(), ast_channel_tech_pvt(), ast_channel_unlock, ast_copy_string(), AST_DECLARE_APP_ARGS, ast_log, AST_MEDIA_TYPE_AUDIO, AST_MEDIA_TYPE_VIDEO, ast_sorcery_object_get_id(), AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), buf, channel_read_pjsip(), channel_read_rtcp(), channel_read_rtp(), ast_sip_session::contact, ast_sip_session_media_state::default_session, ast_sip_session_media::direct_media_addr, ast_sip_session::endpoint, len(), LOG_ERROR, LOG_WARNING, NULL, pjsip_channel_info_get(), S_OR, ast_sip_channel_pvt::session, and type.

◆ pjsip_acf_dial_contacts_read()

int pjsip_acf_dial_contacts_read ( struct ast_channel *  chan,
const char *  cmd,
char *  data,
char *  buf,
size_t  len 
)

PJSIP_DIAL_CONTACTS function read callback.

Parameters
chanThe channel the function is called on
cmdThe name of the function
dataArguments passed to the function
bufOut buffer that should be populated with the data
lenSize of the buffer
Return values
0on success
-1on failure

Definition at line 461 of file dialplan_functions.c.

462{
463 RAII_VAR(struct ast_sip_endpoint *, endpoint, NULL, ao2_cleanup);
464 RAII_VAR(struct ast_str *, dial, NULL, ast_free_ptr);
465 const char *aor_name;
466 char *rest;
467
469 AST_APP_ARG(endpoint_name);
470 AST_APP_ARG(aor_name);
471 AST_APP_ARG(request_user);
472 );
473
475
476 if (ast_strlen_zero(args.endpoint_name)) {
477 ast_log(LOG_WARNING, "An endpoint name must be specified when using the '%s' dialplan function\n", cmd);
478 return -1;
479 } else if (!(endpoint = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint", args.endpoint_name))) {
480 ast_log(LOG_WARNING, "Specified endpoint '%s' was not found\n", args.endpoint_name);
481 return -1;
482 }
483
484 aor_name = S_OR(args.aor_name, endpoint->aors);
485
486 if (ast_strlen_zero(aor_name)) {
487 ast_log(LOG_WARNING, "No AOR has been provided and no AORs are configured on endpoint '%s'\n", args.endpoint_name);
488 return -1;
489 } else if (!(dial = ast_str_create(len))) {
490 ast_log(LOG_WARNING, "Could not get enough buffer space for dialing contacts\n");
491 return -1;
492 } else if (!(rest = ast_strdupa(aor_name))) {
493 ast_log(LOG_WARNING, "Could not duplicate provided AORs\n");
494 return -1;
495 }
496
497 while ((aor_name = ast_strip(strsep(&rest, ",")))) {
499 RAII_VAR(struct ao2_container *, contacts, NULL, ao2_cleanup);
500 struct ao2_iterator it_contacts;
501 struct ast_sip_contact *contact;
502
503 if (!aor) {
504 /* If the AOR provided is not found skip it, there may be more */
505 continue;
507 /* No contacts are available, skip it as well */
508 continue;
509 } else if (!ao2_container_count(contacts)) {
510 /* We were given a container but no contacts are in it... */
511 continue;
512 }
513
514 it_contacts = ao2_iterator_init(contacts, 0);
515 for (; (contact = ao2_iterator_next(&it_contacts)); ao2_ref(contact, -1)) {
516 ast_str_append(&dial, -1, "PJSIP/");
517
518 if (!ast_strlen_zero(args.request_user)) {
519 ast_str_append(&dial, -1, "%s@", args.request_user);
520 }
521 ast_str_append(&dial, -1, "%s/%s&", args.endpoint_name, contact->uri);
522 }
523 ao2_iterator_destroy(&it_contacts);
524 }
525
526 /* Trim the '&' at the end off */
527 ast_str_truncate(dial, ast_str_strlen(dial) - 1);
528
530
531 return 0;
532}
char * strsep(char **str, const char *delims)
void ast_free_ptr(void *ptr)
free() wrapper
Definition astmm.c:1739
#define ao2_iterator_next(iter)
Definition astobj2.h:1911
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
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 ast_sip_aor * ast_sip_location_retrieve_aor(const char *aor_name)
Retrieve a named AOR.
Definition location.c:147
@ AST_SIP_CONTACT_FILTER_REACHABLE
Return only reachable or unknown contacts.
Definition res_pjsip.h:1443
struct ast_sorcery * ast_sip_get_sorcery(void)
Get a pointer to the SIP sorcery structure.
struct ao2_container * ast_sip_location_retrieve_aor_contacts_filtered(const struct ast_sip_aor *aor, unsigned int flags)
Retrieve all contacts currently available for an AOR and filter based on flags.
Definition location.c:252
void * ast_sorcery_retrieve_by_id(const struct ast_sorcery *sorcery, const char *type, const char *id)
Retrieve an object using its unique identifier.
Definition sorcery.c:1917
char * ast_str_truncate(struct ast_str *buf, ssize_t len)
Truncates the enclosed string to the given length.
Definition strings.h:786
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
size_t attribute_pure ast_str_strlen(const struct ast_str *buf)
Returns the current length of the string stored within buf.
Definition strings.h:730
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
Definition strings.h:659
char *attribute_pure ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition strings.h:761
char * ast_strip(char *s)
Strip leading/trailing whitespace from a string.
Definition strings.h:223
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
A SIP address of record.
Definition res_pjsip.h:480
Contact associated with an address of record.
Definition res_pjsip.h:392
const ast_string_field uri
Definition res_pjsip.h:414
const ast_string_field aor
Definition res_pjsip.h:414
An entity with which Asterisk communicates.
Definition res_pjsip.h:1067
Support for dynamic strings.
Definition strings.h:623

References ao2_cleanup, ao2_container_count(), ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_ref, ast_sip_contact::aor, args, AST_APP_ARG, ast_copy_string(), AST_DECLARE_APP_ARGS, ast_free_ptr(), ast_log, AST_SIP_CONTACT_FILTER_REACHABLE, ast_sip_get_sorcery(), ast_sip_location_retrieve_aor(), ast_sip_location_retrieve_aor_contacts_filtered(), ast_sorcery_retrieve_by_id(), AST_STANDARD_APP_ARGS, ast_str_append(), ast_str_buffer(), ast_str_create, ast_str_strlen(), ast_str_truncate(), ast_strdupa, ast_strip(), ast_strlen_zero(), buf, len(), LOG_WARNING, NULL, RAII_VAR, S_OR, strsep(), and ast_sip_contact::uri.

◆ pjsip_acf_dtmf_mode_read()

int pjsip_acf_dtmf_mode_read ( struct ast_channel *  chan,
const char *  cmd,
char *  data,
char *  buf,
size_t  len 
)

PJSIP_DTMF_MODE function read callback.

Parameters
chanThe channel the function is called on
cmdThe name of the function
dataArguments passed to the function
bufOut buffer that should be populated with the data
lenSize of the buffer
Return values
0on success
-1on failure

Definition at line 929 of file dialplan_functions.c.

930{
931 struct ast_sip_channel_pvt *channel;
932
933 if (!chan) {
934 ast_log(LOG_WARNING, "No channel was provided to %s function.\n", cmd);
935 return -1;
936 }
937
938 ast_channel_lock(chan);
939 if (strcmp(ast_channel_tech(chan)->type, "PJSIP")) {
940 ast_log(LOG_WARNING, "Cannot call %s on a non-PJSIP channel\n", cmd);
941 ast_channel_unlock(chan);
942 return -1;
943 }
944
945 channel = ast_channel_tech_pvt(chan);
946
947 if (ast_sip_dtmf_to_str(channel->session->dtmf, buf, len) < 0) {
948 ast_log(LOG_WARNING, "Unknown DTMF mode %d on PJSIP channel %s\n", channel->session->dtmf, ast_channel_name(chan));
949 ast_channel_unlock(chan);
950 return -1;
951 }
952
953 ast_channel_unlock(chan);
954 return 0;
955}
int ast_sip_dtmf_to_str(const enum ast_sip_dtmf_mode dtmf, char *buf, size_t buf_len)
Convert the DTMF mode enum value into a string.
Definition res_pjsip.c:2524
enum ast_sip_dtmf_mode dtmf

References ast_channel_lock, ast_channel_name(), ast_channel_tech_pvt(), ast_channel_unlock, ast_log, ast_sip_dtmf_to_str(), buf, ast_sip_session::dtmf, len(), LOG_WARNING, ast_sip_channel_pvt::session, and type.

◆ pjsip_acf_dtmf_mode_write()

int pjsip_acf_dtmf_mode_write ( struct ast_channel *  chan,
const char *  cmd,
char *  data,
const char *  value 
)

PJSIP_DTMF_MODE function write callback.

Parameters
chanThe channel the function is called on
cmdThe name of the function
dataArguments passed to the function
valueValue to be set by the function
Return values
0on success
-1on failure

Definition at line 1030 of file dialplan_functions.c.

1031{
1032 struct ast_sip_channel_pvt *channel;
1033 struct ast_sip_session_media *media;
1034 int dsp_features = 0;
1035 int dtmf = -1;
1036 struct refresh_data rdata = {
1038 };
1039
1040 if (!chan) {
1041 ast_log(LOG_WARNING, "No channel was provided to %s function.\n", cmd);
1042 return -1;
1043 }
1044
1045 ast_channel_lock(chan);
1046 if (strcmp(ast_channel_tech(chan)->type, "PJSIP")) {
1047 ast_log(LOG_WARNING, "Cannot call %s on a non-PJSIP channel\n", cmd);
1048 ast_channel_unlock(chan);
1049 return -1;
1050 }
1051
1052 channel = ast_channel_tech_pvt(chan);
1053 rdata.session = channel->session;
1054
1055 dtmf = ast_sip_str_to_dtmf(value);
1056
1057 if (dtmf == -1) {
1058 ast_log(LOG_WARNING, "Cannot set DTMF mode to '%s' on channel '%s' as value is invalid.\n", value,
1059 ast_channel_name(chan));
1060 ast_channel_unlock(chan);
1061 return -1;
1062 }
1063
1064 if (channel->session->dtmf == dtmf) {
1065 /* DTMF mode unchanged, nothing to do! */
1066 ast_channel_unlock(chan);
1067 return 0;
1068 }
1069
1070 channel->session->dtmf = dtmf;
1071
1073
1074 if (media && media->rtp) {
1075 if (channel->session->dtmf == AST_SIP_DTMF_RFC_4733) {
1078 } else if (channel->session->dtmf == AST_SIP_DTMF_INFO) {
1081 } else if (channel->session->dtmf == AST_SIP_DTMF_INBAND) {
1084 } else if (channel->session->dtmf == AST_SIP_DTMF_NONE) {
1087 } else if (channel->session->dtmf == AST_SIP_DTMF_AUTO) {
1089 /* no RFC4733 negotiated, enable inband */
1091 }
1092 } else if (channel->session->dtmf == AST_SIP_DTMF_AUTO_INFO) {
1095 /* if inband, switch to INFO */
1097 }
1098 }
1099 }
1100
1101 if (channel->session->dsp) {
1102 dsp_features = ast_dsp_get_features(channel->session->dsp);
1103 }
1104 if (channel->session->dtmf == AST_SIP_DTMF_INBAND ||
1105 channel->session->dtmf == AST_SIP_DTMF_AUTO) {
1106 dsp_features |= DSP_FEATURE_DIGIT_DETECT;
1107 } else {
1108 dsp_features &= ~DSP_FEATURE_DIGIT_DETECT;
1109 }
1110 if (dsp_features) {
1111 if (!channel->session->dsp) {
1112 if (!(channel->session->dsp = ast_dsp_new())) {
1113 ast_channel_unlock(chan);
1114 return 0;
1115 }
1116 }
1117 ast_dsp_set_features(channel->session->dsp, dsp_features);
1118 } else if (channel->session->dsp) {
1119 ast_dsp_free(channel->session->dsp);
1120 channel->session->dsp = NULL;
1121 }
1122
1123 ast_channel_unlock(chan);
1124
1126}
static int dtmf_mode_refresh_cb(void *obj)
void ast_dsp_free(struct ast_dsp *dsp)
Definition dsp.c:1968
#define DSP_FEATURE_DIGIT_DETECT
Definition dsp.h:28
int ast_dsp_get_features(struct ast_dsp *dsp)
Get features.
Definition dsp.c:1962
void ast_dsp_set_features(struct ast_dsp *dsp, int features)
Select feature set.
Definition dsp.c:1953
struct ast_dsp * ast_dsp_new(void)
Allocates a new dsp, assumes 8khz for internal sample rate.
Definition dsp.c:1943
#define ast_sip_push_task_wait_serializer(serializer, sip_task, task_data)
Definition res_pjsip.h:2221
@ AST_SIP_DTMF_NONE
Definition res_pjsip.h:549
@ AST_SIP_DTMF_AUTO_INFO
Definition res_pjsip.h:560
@ AST_SIP_DTMF_AUTO
Definition res_pjsip.h:558
@ AST_SIP_DTMF_INBAND
Definition res_pjsip.h:554
@ AST_SIP_DTMF_INFO
Definition res_pjsip.h:556
@ AST_SIP_DTMF_RFC_4733
Definition res_pjsip.h:552
int ast_sip_str_to_dtmf(const char *dtmf_mode)
Convert the DTMF mode name into an enum.
Definition res_pjsip.c:2553
@ AST_SIP_SESSION_REFRESH_METHOD_INVITE
Definition res_pjsip.h:717
enum ast_rtp_dtmf_mode ast_rtp_instance_dtmf_mode_get(struct ast_rtp_instance *instance)
Get the DTMF mode of an RTP instance.
@ AST_RTP_DTMF_MODE_RFC2833
Definition rtp_engine.h:155
@ AST_RTP_DTMF_MODE_INBAND
Definition rtp_engine.h:157
@ AST_RTP_DTMF_MODE_NONE
Definition rtp_engine.h:153
int ast_rtp_instance_dtmf_mode_set(struct ast_rtp_instance *instance, enum ast_rtp_dtmf_mode dtmf_mode)
Set the DTMF mode that should be used.
void ast_rtp_instance_set_prop(struct ast_rtp_instance *instance, enum ast_rtp_property property, int value)
Set the value of an RTP instance property.
Definition rtp_engine.c:756
@ AST_RTP_PROPERTY_DTMF
Definition rtp_engine.h:120
struct ast_rtp_instance * rtp
RTP instance itself.
struct ast_dsp * dsp
struct ast_taskprocessor * serializer
int value
Definition syslog.c:37

References ast_sip_session::active_media_state, ast_channel_lock, ast_channel_name(), ast_channel_tech_pvt(), ast_channel_unlock, ast_dsp_free(), ast_dsp_get_features(), ast_dsp_new(), ast_dsp_set_features(), ast_log, AST_MEDIA_TYPE_AUDIO, AST_RTP_DTMF_MODE_INBAND, AST_RTP_DTMF_MODE_NONE, AST_RTP_DTMF_MODE_RFC2833, ast_rtp_instance_dtmf_mode_get(), ast_rtp_instance_dtmf_mode_set(), ast_rtp_instance_set_prop(), AST_RTP_PROPERTY_DTMF, AST_SIP_DTMF_AUTO, AST_SIP_DTMF_AUTO_INFO, AST_SIP_DTMF_INBAND, AST_SIP_DTMF_INFO, AST_SIP_DTMF_NONE, AST_SIP_DTMF_RFC_4733, ast_sip_push_task_wait_serializer, AST_SIP_SESSION_REFRESH_METHOD_INVITE, ast_sip_str_to_dtmf(), ast_sip_session_media_state::default_session, ast_sip_session::dsp, DSP_FEATURE_DIGIT_DETECT, ast_sip_session::dtmf, dtmf_mode_refresh_cb(), LOG_WARNING, refresh_data::method, NULL, ast_sip_session_media::rtp, ast_sip_session::serializer, refresh_data::session, ast_sip_channel_pvt::session, type, and value.

◆ pjsip_acf_media_offer_read()

int pjsip_acf_media_offer_read ( struct ast_channel *  chan,
const char *  cmd,
char *  data,
char *  buf,
size_t  len 
)

PJSIP_MEDIA_OFFER function read callback.

Parameters
chanThe channel the function is called on
cmdThe name of the function
dataArguments passed to the function
bufOut buffer that should be populated with the data
lenSize of the buffer
Return values
0on success
-1on failure

Definition at line 872 of file dialplan_functions.c.

873{
874 struct ast_sip_channel_pvt *channel;
875
876 if (!chan) {
877 ast_log(LOG_WARNING, "No channel was provided to %s function.\n", cmd);
878 return -1;
879 }
880
881 if (strcmp(ast_channel_tech(chan)->type, "PJSIP")) {
882 ast_log(LOG_WARNING, "Cannot call %s on a non-PJSIP channel\n", cmd);
883 return -1;
884 }
885
886 channel = ast_channel_tech_pvt(chan);
887
888 if (!strcmp(data, "audio")) {
890 } else if (!strcmp(data, "video")) {
892 } else {
893 /* Ensure that the buffer is empty */
894 buf[0] = '\0';
895 }
896
897 return 0;
898}
static int media_offer_read_av(struct ast_sip_session *session, char *buf, size_t len, enum ast_media_type media_type)

References ast_channel_tech_pvt(), ast_log, AST_MEDIA_TYPE_AUDIO, AST_MEDIA_TYPE_VIDEO, buf, len(), LOG_WARNING, media_offer_read_av(), ast_sip_channel_pvt::session, and type.

◆ pjsip_acf_media_offer_write()

int pjsip_acf_media_offer_write ( struct ast_channel *  chan,
const char *  cmd,
char *  data,
const char *  value 
)

PJSIP_MEDIA_OFFER function write callback.

Parameters
chanThe channel the function is called on
cmdThe name of the function
dataArguments passed to the function
valueValue to be set by the function
Return values
0on success
-1on failure

Definition at line 900 of file dialplan_functions.c.

901{
902 struct ast_sip_channel_pvt *channel;
903 struct media_offer_data mdata = {
904 .value = value
905 };
906
907 if (!chan) {
908 ast_log(LOG_WARNING, "No channel was provided to %s function.\n", cmd);
909 return -1;
910 }
911
912 if (strcmp(ast_channel_tech(chan)->type, "PJSIP")) {
913 ast_log(LOG_WARNING, "Cannot call %s on a non-PJSIP channel\n", cmd);
914 return -1;
915 }
916
917 channel = ast_channel_tech_pvt(chan);
918 mdata.session = channel->session;
919
920 if (!strcmp(data, "audio")) {
922 } else if (!strcmp(data, "video")) {
924 }
925
927}
static int media_offer_write_av(void *obj)

References ast_channel_tech_pvt(), ast_log, AST_MEDIA_TYPE_AUDIO, AST_MEDIA_TYPE_VIDEO, ast_sip_push_task_wait_serializer, LOG_WARNING, media_offer_write_av(), media_offer_data::media_type, ast_sip_session::serializer, media_offer_data::session, ast_sip_channel_pvt::session, type, media_offer_data::value, and value.

◆ pjsip_acf_moh_passthrough_read()

int pjsip_acf_moh_passthrough_read ( struct ast_channel *  chan,
const char *  cmd,
char *  data,
char *  buf,
size_t  len 
)

PJSIP_MOH_PASSTHROUGH function read callback.

Parameters
chanThe channel the function is called on
cmdThe name of the function
dataArguments passed to the function
bufOut buffer that should be populated with the data
lenSize of the buffer
Return values
0on success
-1on failure

Definition at line 957 of file dialplan_functions.c.

958{
959 struct ast_sip_channel_pvt *channel;
960
961 if (!chan) {
962 ast_log(LOG_WARNING, "No channel was provided to %s function.\n", cmd);
963 return -1;
964 }
965
966 if (len < 3) {
967 ast_log(LOG_WARNING, "%s: buffer too small\n", cmd);
968 return -1;
969 }
970
971 ast_channel_lock(chan);
972 if (strcmp(ast_channel_tech(chan)->type, "PJSIP")) {
973 ast_log(LOG_WARNING, "Cannot call %s on a non-PJSIP channel\n", cmd);
974 ast_channel_unlock(chan);
975 return -1;
976 }
977
978 channel = ast_channel_tech_pvt(chan);
979 strncpy(buf, AST_YESNO(channel->session->moh_passthrough), len);
980
981 ast_channel_unlock(chan);
982 return 0;
983}
#define AST_YESNO(x)
return Yes or No depending on the argument.
Definition strings.h:143
unsigned int moh_passthrough

References ast_channel_lock, ast_channel_tech_pvt(), ast_channel_unlock, ast_log, AST_YESNO, buf, len(), LOG_WARNING, ast_sip_session::moh_passthrough, ast_sip_channel_pvt::session, and type.

◆ pjsip_acf_moh_passthrough_write()

int pjsip_acf_moh_passthrough_write ( struct ast_channel *  chan,
const char *  cmd,
char *  data,
const char *  value 
)

PJSIP_MOH_PASSTHROUGH function write callback.

Parameters
chanThe channel the function is called on
cmdThe name of the function
dataArguments passed to the function
valueValue to be set by the function
Return values
0on success
-1on failure

Definition at line 1128 of file dialplan_functions.c.

1129{
1130 struct ast_sip_channel_pvt *channel;
1131
1132 if (!chan) {
1133 ast_log(LOG_WARNING, "No channel was provided to %s function.\n", cmd);
1134 return -1;
1135 }
1136
1137 ast_channel_lock(chan);
1138 if (strcmp(ast_channel_tech(chan)->type, "PJSIP")) {
1139 ast_log(LOG_WARNING, "Cannot call %s on a non-PJSIP channel\n", cmd);
1140 ast_channel_unlock(chan);
1141 return -1;
1142 }
1143
1144 channel = ast_channel_tech_pvt(chan);
1146
1147 ast_channel_unlock(chan);
1148
1149 return 0;
1150}
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true"....
Definition utils.c:2233

References ast_channel_lock, ast_channel_tech_pvt(), ast_channel_unlock, ast_log, ast_true(), LOG_WARNING, ast_sip_session::moh_passthrough, ast_sip_channel_pvt::session, type, and value.

◆ pjsip_acf_parse_uri_read()

int pjsip_acf_parse_uri_read ( struct ast_channel *  chan,
const char *  cmd,
char *  data,
char *  buf,
size_t  len 
)

PJSIP_PARSE_URI function read callback.

Parameters
chanThe channel the function is called on
cmdThe name of the function
dataArguments passed to the function
bufOut buffer that should be populated with the data
lenSize of the buffer
Return values
0on success
-1on failure

Definition at line 675 of file dialplan_functions.c.

676{
677 struct parse_uri_args func_args = { 0, };
678 int reading_uri_from_var;
679
681 AST_APP_ARG(uri_str);
683 );
684
686
687 reading_uri_from_var = !strcasecmp(cmd, "PJSIP_PARSE_URI_FROM");
688
689 if (reading_uri_from_var) {
690 const char *var;
691
692 if (ast_strlen_zero(args.uri_str)) {
693 ast_log(LOG_WARNING, "The name of a variable containing a URI must be specified when using the '%s' dialplan function\n", cmd);
694 return -1;
695 }
696
697 ast_channel_lock(chan);
698 if ((var = pbx_builtin_getvar_helper(chan, args.uri_str))) {
699 args.uri_str = ast_strdupa(var);
700 }
701 ast_channel_unlock(chan);
702 }
703
704 if (ast_strlen_zero(args.uri_str)) {
705 if (reading_uri_from_var) {
706 ast_log(LOG_WARNING, "The variable provided to the '%s' dialplan function must contain a URI\n", cmd);
707 } else {
708 ast_log(LOG_WARNING, "A URI must be specified when using the '%s' dialplan function\n", cmd);
709 }
710 return -1;
711 }
712
713 if (ast_strlen_zero(args.type)) {
714 ast_log(LOG_WARNING, "A type part of the URI must be specified when using the '%s' dialplan function\n", cmd);
715 return -1;
716 }
717
718 memset(buf, 0, buflen);
719
720 func_args.uri = args.uri_str;
721 func_args.type = args.type;
722 func_args.buf = buf;
723 func_args.buflen = buflen;
725 ast_log(LOG_WARNING, "Unable to parse URI: failed to push task\n");
726 return -1;
727 }
728
729 return func_args.ret;
730}
#define var
Definition ast_expr2f.c:605
static int parse_uri_cb(void *data)
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.
static char * func_args(char *function)
return a pointer to the arguments of the function, and terminates the function name with '\0'

References args, AST_APP_ARG, ast_channel_lock, ast_channel_unlock, AST_DECLARE_APP_ARGS, ast_log, ast_sip_push_task_wait_serializer, AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), buf, parse_uri_args::buflen, func_args(), LOG_WARNING, NULL, parse_uri_cb(), pbx_builtin_getvar_helper(), type, and var.

◆ pjsip_acf_session_refresh_write()

int pjsip_acf_session_refresh_write ( struct ast_channel *  chan,
const char *  cmd,
char *  data,
const char *  value 
)

PJSIP_SEND_SESSION_REFRESH function write callback.

Parameters
chanThe channel the function is called on
cmdthe Name of the function
dataArguments passed to the function
valueValue to be set by the function
Return values
0on success
-1on failure

Definition at line 1171 of file dialplan_functions.c.

1172{
1173 struct ast_sip_channel_pvt *channel;
1174 struct refresh_data rdata = {
1176 };
1177
1178 if (!chan) {
1179 ast_log(LOG_WARNING, "No channel was provided to %s function.\n", cmd);
1180 return -1;
1181 }
1182
1183 if (ast_channel_state(chan) != AST_STATE_UP) {
1184 ast_log(LOG_WARNING, "'%s' not allowed on unanswered channel '%s'.\n", cmd, ast_channel_name(chan));
1185 return -1;
1186 }
1187
1188 if (strcmp(ast_channel_tech(chan)->type, "PJSIP")) {
1189 ast_log(LOG_WARNING, "Cannot call %s on a non-PJSIP channel\n", cmd);
1190 return -1;
1191 }
1192
1193 channel = ast_channel_tech_pvt(chan);
1194 rdata.session = channel->session;
1195
1196 if (!strcmp(value, "invite")) {
1198 } else if (!strcmp(value, "update")) {
1200 }
1201
1203}
ast_channel_state
ast_channel states
@ AST_STATE_UP
static int refresh_write_cb(void *obj)
@ AST_SIP_SESSION_REFRESH_METHOD_UPDATE
Definition res_pjsip.h:719

References ast_channel_name(), ast_channel_tech_pvt(), ast_log, ast_sip_push_task_wait_serializer, AST_SIP_SESSION_REFRESH_METHOD_INVITE, AST_SIP_SESSION_REFRESH_METHOD_UPDATE, AST_STATE_UP, LOG_WARNING, refresh_data::method, refresh_write_cb(), ast_sip_session::serializer, refresh_data::session, ast_sip_channel_pvt::session, type, and value.

◆ pjsip_action_hangup()

int pjsip_action_hangup ( struct mansession *  s,
const struct message *  m 
)

PJSIPHangup Manager Action.

Manager action to hang up an incoming PJSIP channel with a SIP response code.

Definition at line 1317 of file dialplan_functions.c.

1318{
1319 return ast_manager_hangup_helper(s, m,
1321}
static int response_code_validator(const char *channel_name, const char *response)
Callback that validates the response code.
static void pjsip_app_hangup_handler(struct ast_channel *chan, int response_code)
Called by pjsip_app_hangup and pjsip_action_hangup to actually perform the hangup.
int ast_manager_hangup_helper(struct mansession *s, const struct message *m, manager_hangup_handler_t handler, manager_hangup_cause_validator_t cause_validator)
A manager helper function that hangs up a channel using a supplied channel type specific hangup funct...
Definition manager.c:3469

References ast_manager_hangup_helper(), pjsip_app_hangup_handler(), and response_code_validator().

Referenced by load_module().

◆ pjsip_app_hangup()

int pjsip_app_hangup ( struct ast_channel *  chan,
const char *  data 
)

PJSIPHangup Dialplan App.

Hang up an incoming PJSIP channel with a SIP response code.

Definition at line 1297 of file dialplan_functions.c.

1298{
1299 int response_code;
1300 const char *tag = ast_channel_name(chan);
1301
1302 if (ast_strlen_zero(data)) {
1303 ast_log(LOG_WARNING, "%s: Missing response code parameter\n", tag);
1304 return -1;
1305 }
1306
1307 response_code = response_code_validator(tag, data);
1308
1309 pjsip_app_hangup_handler(chan, response_code);
1310
1311 return -1;
1312}

References ast_channel_name(), ast_log, ast_strlen_zero(), hangup_data::chan, LOG_WARNING, pjsip_app_hangup_handler(), hangup_data::response_code, and response_code_validator().

Referenced by load_module().

◆ pjsip_app_hangup_handler()

static void pjsip_app_hangup_handler ( struct ast_channel *  chan,
int  response_code 
)
static

Called by pjsip_app_hangup and pjsip_action_hangup to actually perform the hangup.

Definition at line 1257 of file dialplan_functions.c.

1258{
1259 struct ast_sip_channel_pvt *channel;
1260 struct hangup_data hdata = { NULL, -1 };
1261 const char *tag = ast_channel_name(chan);
1262
1264
1266 if (strcmp(ast_channel_tech(chan)->type, "PJSIP")) {
1267 ast_log(LOG_WARNING, "%s: Not a PJSIP channel\n", tag);
1269 return;
1270 }
1271
1272 channel = ast_channel_tech_pvt(chan);
1273 hdata.session = channel->session;
1274
1275 if (hdata.session->inv_session->role != PJSIP_ROLE_UAS || (
1276 hdata.session->inv_session->state != PJSIP_INV_STATE_INCOMING &&
1277 hdata.session->inv_session->state != PJSIP_INV_STATE_EARLY)) {
1278 ast_log(LOG_WARNING, "%s: Not an incoming channel or invalid state '%s'\n",
1279 tag, pjsip_inv_state_name(hdata.session->inv_session->state));
1281 return;
1282 }
1283
1285
1287 pjsip_hangup, &hdata) != 0) {
1288 ast_log(LOG_WARNING, "%s: failed to push hangup task to serializer\n", tag);
1289 }
1290
1291 return;
1292}
static int pjsip_hangup(void *obj)
Serializer task to hangup channel.
struct ast_sip_session * session
struct ast_channel * chan

References ast_channel_lock, ast_channel_name(), ast_channel_tech_pvt(), ast_channel_unlock, ast_log, ast_sip_push_task_wait_serializer, hangup_data::chan, ast_sip_session::inv_session, LOG_WARNING, NULL, pjsip_hangup(), hangup_data::response_code, ast_sip_session::serializer, hangup_data::session, ast_sip_channel_pvt::session, and type.

Referenced by pjsip_action_hangup(), and pjsip_app_hangup().

◆ pjsip_hangup()

static int pjsip_hangup ( void *  obj)
static

Serializer task to hangup channel.

Definition at line 1213 of file dialplan_functions.c.

1214{
1215 struct hangup_data *hdata = obj;
1216 pjsip_tx_data *packet = NULL;
1217
1218 if ((hdata->session->inv_session->state != PJSIP_INV_STATE_DISCONNECTED) &&
1219 (pjsip_inv_answer(hdata->session->inv_session, hdata->response_code, NULL, NULL, &packet) == PJ_SUCCESS)) {
1220 ast_sip_session_send_response(hdata->session, packet);
1221 }
1222
1223 return 0;
1224}
void ast_sip_session_send_response(struct ast_sip_session *session, pjsip_tx_data *tdata)
Send a SIP response.

References ast_sip_session_send_response(), ast_sip_session::inv_session, NULL, hangup_data::response_code, and hangup_data::session.

Referenced by pjsip_app_hangup_handler().

◆ pjsip_transfer_handling_write()

int pjsip_transfer_handling_write ( struct ast_channel *  chan,
const char *  cmd,
char *  data,
const char *  value 
)

PJSIP_TRANSFER_HANDLING function write callback.

Parameters
chanThe channel the function is called on
cmdthe Name of the function
dataArguments passed to the function
valueValue to be set by the function
Return values
0on success
-1on failure

Definition at line 1323 of file dialplan_functions.c.

1324{
1325 struct ast_sip_channel_pvt *channel;
1326 int ret = 0;
1327
1328 if (!chan) {
1329 ast_log(LOG_WARNING, "No channel was provided to %s function.\n", cmd);
1330 return -1;
1331 }
1332
1333 ast_channel_lock(chan);
1334 if (strcmp(ast_channel_tech(chan)->type, "PJSIP")) {
1335 ast_log(LOG_WARNING, "Cannot call %s on a non-PJSIP channel %s\n", cmd, ast_channel_name(chan));
1336 ast_channel_unlock(chan);
1337 return -1;
1338 }
1339
1340 channel = ast_channel_tech_pvt(chan);
1341
1342 if (ast_strlen_zero(value) || !strcmp(value, "core")) {
1343 channel->session->transferhandling_ari = 0;
1344 } else if (!strcmp(value, "ari-only")) {
1345 channel->session->transferhandling_ari = 1;
1346 } else {
1347 ast_log(AST_LOG_WARNING, "Cannot set unknown transfer handling '%s' on channel '%s', transfer handling will remain unchanged.",
1348 value, ast_channel_name(chan));
1349 ret = -1;
1350 }
1351
1352 ast_channel_unlock(chan);
1353 return ret;
1354}
unsigned int transferhandling_ari

References ast_channel_lock, ast_channel_name(), ast_channel_tech_pvt(), ast_channel_unlock, ast_log, AST_LOG_WARNING, ast_strlen_zero(), LOG_WARNING, ast_sip_channel_pvt::session, ast_sip_session::transferhandling_ari, type, and value.

◆ read_request_uri()

static int read_request_uri ( struct ast_channel *  chan,
struct ast_sip_session *  session,
char *  buf,
size_t  size 
)
static

Definition at line 241 of file dialplan_functions.c.

243{
244 int length;
245 char *copy;
246
247 if (!session->request_uri) {
248 return 0;
249 }
250 length = pjsip_uri_print(PJSIP_URI_IN_REQ_URI, session->request_uri, buf, size);
251 if (length < 0 || length >= size) {
252 ast_log(LOG_ERROR, "Channel %s: Request URI too long for %zu byte buffer\n",
253 ast_channel_name(chan), size);
254 buf[0] = '\0';
255 return -1;
256 }
257 buf[length] = '\0';
259 ast_escape_quoted(copy, buf, size);
260 return 0;
261}

References ast_channel_name(), ast_escape_quoted(), ast_log, ast_strdupa, buf, copy(), LOG_ERROR, and session.

Referenced by channel_read_pjsip().

◆ refresh_write_cb()

static int refresh_write_cb ( void *  obj)
static

Definition at line 1152 of file dialplan_functions.c.

1153{
1154 struct refresh_data *data = obj;
1156
1158 if (!state) {
1159 return -1;
1160 }
1161
1163 sip_session_response_cb, data->method, 1, state->media_state);
1164
1165 state->media_state = NULL;
1166 ast_sip_session_remove_datastore(data->session, "pjsip_session_refresh");
1167
1168 return 0;
1169}
void ast_sip_session_remove_datastore(struct ast_sip_session *session, const char *name)
Remove a session datastore from the session.

References ast_sip_session_refresh(), ast_sip_session_remove_datastore(), refresh_data::method, NULL, refresh_data::session, session_refresh_state_get_or_alloc(), and sip_session_response_cb().

Referenced by pjsip_acf_session_refresh_write().

◆ response_code_validator()

static int response_code_validator ( const char *  channel_name,
const char *  response 
)
static

Callback that validates the response code.

Definition at line 1229 of file dialplan_functions.c.

1230 {
1231 int response_code;
1232
1233 int rc = ast_str_to_int(response, &response_code);
1234 if (rc != 0) {
1235 response_code = ast_sip_str2rc(response);
1236 if (response_code < 0) {
1237 ast_log(LOG_WARNING, "%s: Unrecognized response code parameter '%s'."
1238 " Defaulting to 603 DECLINE\n",
1239 channel_name, response);
1240 return PJSIP_SC_DECLINE;
1241 }
1242 }
1243
1244 if (response_code < 400 || response_code > 699) {
1245 ast_log(LOG_WARNING, "%s: Response code %d is out of range 400 -> 699."
1246 " Defaulting to 603 DECLINE\n",
1247 channel_name, response_code);
1248 return PJSIP_SC_DECLINE;
1249 }
1250 return response_code;
1251}
int ast_str_to_int(const char *str, int *res)
Convert the given string to a signed integer.
Definition conversions.c:44
int ast_sip_str2rc(const char *name)
Convert name to SIP response code.
Definition res_pjsip.c:3754

References ast_log, ast_sip_str2rc(), ast_str_to_int(), LOG_WARNING, and hangup_data::response_code.

Referenced by pjsip_action_hangup(), and pjsip_app_hangup().

◆ session_refresh_state_destroy()

static void session_refresh_state_destroy ( void *  obj)
static

Destructor for session refresh information.

Definition at line 541 of file dialplan_functions.c.

542{
543 struct session_refresh_state *state = obj;
544
546 ast_free(obj);
547}
#define ast_free(a)
Definition astmm.h:180
void ast_sip_session_media_state_free(struct ast_sip_session_media_state *media_state)
Free a session media state structure.

References ast_free, and ast_sip_session_media_state_free().

◆ session_refresh_state_get_or_alloc()

static struct session_refresh_state * session_refresh_state_get_or_alloc ( struct ast_sip_session *  session)
static

Helper function which retrieves or allocates a session refresh state information datastore.

Definition at line 556 of file dialplan_functions.c.

557{
558 RAII_VAR(struct ast_datastore *, datastore, ast_sip_session_get_datastore(session, "pjsip_session_refresh"), ao2_cleanup);
560
561 /* While the datastore refcount is decremented this is operating in the serializer so it will remain valid regardless */
562 if (datastore) {
563 return datastore->data;
564 }
565
566 if (!(datastore = ast_sip_session_alloc_datastore(&session_refresh_datastore, "pjsip_session_refresh"))
567 || !(datastore->data = ast_calloc(1, sizeof(struct session_refresh_state)))
568 || ast_sip_session_add_datastore(session, datastore)) {
569 return NULL;
570 }
571
572 state = datastore->data;
574 if (!state->media_state) {
575 ast_sip_session_remove_datastore(session, "pjsip_session_refresh");
576 return NULL;
577 }
578 state->media_state->topology = ast_stream_topology_clone(session->endpoint->media.topology);
579 if (!state->media_state->topology) {
580 ast_sip_session_remove_datastore(session, "pjsip_session_refresh");
581 return NULL;
582 }
583
584 datastore->data = state;
585
586 return state;
587}
#define ast_calloc(num, len)
A wrapper for calloc()
Definition astmm.h:202
static const struct ast_datastore_info session_refresh_datastore
Datastore for attaching session refresh state information.
struct ast_sip_session_media_state * ast_sip_session_media_state_alloc(void)
Allocate a session media state structure.
int ast_sip_session_add_datastore(struct ast_sip_session *session, struct ast_datastore *datastore)
Add a datastore to a SIP session.
struct ast_datastore * ast_sip_session_alloc_datastore(const struct ast_datastore_info *info, const char *uid)
Alternative for ast_datastore_alloc()

References ao2_cleanup, ast_calloc, ast_sip_session_add_datastore(), ast_sip_session_alloc_datastore(), ast_sip_session_get_datastore(), ast_sip_session_media_state_alloc(), ast_sip_session_remove_datastore(), ast_stream_topology_clone(), NULL, RAII_VAR, session, and session_refresh_datastore.

Referenced by media_offer_read_av(), media_offer_write_av(), and refresh_write_cb().

◆ sip_session_response_cb()

static int sip_session_response_cb ( struct ast_sip_session *  session,
pjsip_rx_data *  rdata 
)
static

Definition at line 990 of file dialplan_functions.c.

991{
992 struct ast_format *fmt;
993
994 if (!session->channel) {
995 /* Egads! */
996 return 0;
997 }
998
1000 if (!fmt) {
1001 /* No format? That's weird. */
1002 return 0;
1003 }
1004 ast_channel_set_writeformat(session->channel, fmt);
1006 ast_channel_set_readformat(session->channel, fmt);
1008 ao2_ref(fmt, -1);
1009
1010 return 0;
1011}
struct ast_format_cap * ast_channel_nativeformats(const struct ast_channel *chan)
void ast_channel_set_rawreadformat(struct ast_channel *chan, struct ast_format *format)
void ast_channel_set_rawwriteformat(struct ast_channel *chan, struct ast_format *format)
void ast_channel_set_readformat(struct ast_channel *chan, struct ast_format *format)
void ast_channel_set_writeformat(struct ast_channel *chan, struct ast_format *format)
struct ast_format * ast_format_cap_get_best_by_type(const struct ast_format_cap *cap, enum ast_media_type type)
Get the most preferred format for a particular media type.
Definition format_cap.c:425

References ao2_ref, ast_channel_nativeformats(), ast_channel_set_rawreadformat(), ast_channel_set_rawwriteformat(), ast_channel_set_readformat(), ast_channel_set_writeformat(), ast_format_cap_get_best_by_type(), AST_MEDIA_TYPE_AUDIO, and session.

Referenced by dtmf_mode_refresh_cb(), and refresh_write_cb().

Variable Documentation

◆ session_refresh_datastore

const struct ast_datastore_info session_refresh_datastore
static
Initial value:
= {
.type = "pjsip_session_refresh",
}
static void session_refresh_state_destroy(void *obj)
Destructor for session refresh information.

Datastore for attaching session refresh state information.

Definition at line 550 of file dialplan_functions.c.

550 {
551 .type = "pjsip_session_refresh",
553};

Referenced by session_refresh_state_get_or_alloc().

◆ t38state_to_string

const char* t38state_to_string[T38_MAX_ENUM]
static

String representations of the T.38 state enum.

Definition at line 57 of file dialplan_functions.c.

57 {
58 [T38_DISABLED] = "DISABLED",
59 [T38_LOCAL_REINVITE] = "LOCAL_REINVITE",
60 [T38_PEER_REINVITE] = "REMOTE_REINVITE",
61 [T38_ENABLED] = "ENABLED",
62 [T38_REJECTED] = "REJECTED",
63};
#define T38_ENABLED
#define T38_DISABLED
@ T38_PEER_REINVITE
@ T38_LOCAL_REINVITE
@ T38_REJECTED

Referenced by channel_read_pjsip().