Asterisk - The Open Source Telephony Project GIT-master-7921072
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/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  pjsip_func_args
 Struct used to push 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, const char *type, const char *field, char *buf, size_t buflen)
 
static int channel_read_rtcp (struct ast_channel *chan, const char *type, const char *field, char *buf, size_t buflen)
 
static int channel_read_rtp (struct ast_channel *chan, const char *type, const char *field, char *buf, size_t buflen)
 
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. More...
 
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. More...
 
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. More...
 
int pjsip_acf_dtmf_mode_write (struct ast_channel *chan, const char *cmd, char *data, const char *value)
 PJSIP_DTMF_MODE function write callback. More...
 
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. More...
 
int pjsip_acf_media_offer_write (struct ast_channel *chan, const char *cmd, char *data, const char *value)
 PJSIP_MEDIA_OFFER function write callback. More...
 
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. More...
 
int pjsip_acf_moh_passthrough_write (struct ast_channel *chan, const char *cmd, char *data, const char *value)
 PJSIP_MOH_PASSTHROUGH function write callback. More...
 
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. More...
 
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. More...
 
int pjsip_action_hangup (struct mansession *s, const struct message *m)
 PJSIPHangup Manager Action. More...
 
int pjsip_app_hangup (struct ast_channel *chan, const char *data)
 PJSIPHangup Dialplan App. More...
 
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. More...
 
static int pjsip_hangup (void *obj)
 Serializer task to hangup channel. More...
 
static int print_escaped_uri (struct ast_channel *chan, const char *type, pjsip_uri_context_e context, const void *uri, char *buf, size_t size)
 
static int read_pjsip (void *data)
 
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. More...
 
static void session_refresh_state_destroy (void *obj)
 Destructor for session refresh information. More...
 
static struct session_refresh_statesession_refresh_state_get_or_alloc (struct ast_sip_session *session)
 Helper function which retrieves or allocates a session refresh state information datastore. More...
 
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. More...
 
static const char * t38state_to_string [T38_MAX_ENUM]
 String representations of the T.38 state enum. More...
 

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,
const char *  type,
const char *  field,
char *  buf,
size_t  buflen 
)
static

Definition at line 287 of file dialplan_functions.c.

288{
289 struct ast_sip_channel_pvt *channel = ast_channel_tech_pvt(chan);
290 char *buf_copy;
291 pjsip_dialog *dlg;
292 int res = 0;
293
294 if (!channel) {
295 ast_log(AST_LOG_WARNING, "Channel %s has no pvt!\n", ast_channel_name(chan));
296 return -1;
297 }
298
299 dlg = channel->session->inv_session->dlg;
300
301 if (ast_strlen_zero(type)) {
302 ast_log(LOG_WARNING, "You must supply a type field for 'pjsip' information\n");
303 return -1;
304 } else if (!strcmp(type, "call-id")) {
305 snprintf(buf, buflen, "%.*s", (int) pj_strlen(&dlg->call_id->id), pj_strbuf(&dlg->call_id->id));
306 } else if (!strcmp(type, "secure")) {
307#ifdef HAVE_PJSIP_GET_DEST_INFO
308 pjsip_host_info dest;
309 pj_pool_t *pool = pjsip_endpt_create_pool(ast_sip_get_pjsip_endpoint(), "secure-check", 128, 128);
310 pjsip_get_dest_info(dlg->target, NULL, pool, &dest);
311 snprintf(buf, buflen, "%d", dest.flag & PJSIP_TRANSPORT_SECURE ? 1 : 0);
312 pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
313#else
314 ast_log(LOG_WARNING, "Asterisk has been built against a version of pjproject which does not have the required functionality to support the 'secure' argument. Please upgrade to version 2.3 or later.\n");
315 return -1;
316#endif
317 } else if (!strcmp(type, "target_uri")) {
318 res = print_escaped_uri(chan, type, PJSIP_URI_IN_REQ_URI, dlg->target, buf,
319 buflen);
320 } else if (!strcmp(type, "local_uri")) {
321 res = print_escaped_uri(chan, type, PJSIP_URI_IN_FROMTO_HDR, dlg->local.info->uri,
322 buf, buflen);
323 } else if (!strcmp(type, "local_tag")) {
324 ast_copy_pj_str(buf, &dlg->local.info->tag, buflen);
325 buf_copy = ast_strdupa(buf);
326 ast_escape_quoted(buf_copy, buf, buflen);
327 } else if (!strcmp(type, "remote_uri")) {
328 res = print_escaped_uri(chan, type, PJSIP_URI_IN_FROMTO_HDR,
329 dlg->remote.info->uri, buf, buflen);
330 } else if (!strcmp(type, "remote_tag")) {
331 ast_copy_pj_str(buf, &dlg->remote.info->tag, buflen);
332 buf_copy = ast_strdupa(buf);
333 ast_escape_quoted(buf_copy, buf, buflen);
334 } else if (!strcmp(type, "request_uri")) {
335 if (channel->session->request_uri) {
336 res = print_escaped_uri(chan, type, PJSIP_URI_IN_REQ_URI,
337 channel->session->request_uri, buf, buflen);
338 }
339 } else if (!strcmp(type, "t38state")) {
341 } else if (!strcmp(type, "local_addr")) {
342 RAII_VAR(struct ast_datastore *, datastore, NULL, ao2_cleanup);
343 struct transport_info_data *transport_data;
344
345 datastore = ast_sip_session_get_datastore(channel->session, "transport_info");
346 if (!datastore) {
347 ast_log(AST_LOG_WARNING, "No transport information for channel %s\n", ast_channel_name(chan));
348 return -1;
349 }
350 transport_data = datastore->data;
351
352 if (pj_sockaddr_has_addr(&transport_data->local_addr)) {
353 pj_sockaddr_print(&transport_data->local_addr, buf, buflen, 3);
354 }
355 } else if (!strcmp(type, "remote_addr")) {
356 RAII_VAR(struct ast_datastore *, datastore, NULL, ao2_cleanup);
357 struct transport_info_data *transport_data;
358
359 datastore = ast_sip_session_get_datastore(channel->session, "transport_info");
360 if (!datastore) {
361 ast_log(AST_LOG_WARNING, "No transport information for channel %s\n", ast_channel_name(chan));
362 return -1;
363 }
364 transport_data = datastore->data;
365
366 if (pj_sockaddr_has_addr(&transport_data->remote_addr)) {
367 pj_sockaddr_print(&transport_data->remote_addr, buf, buflen, 3);
368 }
369 } else {
370 ast_log(AST_LOG_WARNING, "Unrecognized argument '%s' for 'pjsip' information\n", type);
371 return -1;
372 }
373
374 return res;
375}
#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[]
Definition: chan_ooh323.c:109
const char * ast_channel_name(const struct ast_channel *chan)
void * ast_channel_tech_pvt(const struct ast_channel *chan)
static int print_escaped_uri(struct ast_channel *chan, const char *type, pjsip_uri_context_e context, const void *uri, char *buf, size_t size)
static const char * t38state_to_string[T38_MAX_ENUM]
String representations of the T.38 state enum.
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
#define AST_LOG_WARNING
#define LOG_WARNING
pjsip_endpoint * ast_sip_get_pjsip_endpoint(void)
Get a pointer to the PJSIP endpoint.
Definition: res_pjsip.c:520
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:2201
struct ast_datastore * ast_sip_session_get_datastore(struct ast_sip_session *session, const char *name)
Retrieve a session datastore.
#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
A structure which contains a channel implementation and session.
struct ast_sip_session * session
Pointer to session.
pjsip_uri * request_uri
enum ast_sip_session_t38state t38state
struct pjsip_inv_session * inv_session
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:941
char * ast_escape_quoted(const char *string, char *outbuf, int buflen)
Escape characters found in a quoted string.
Definition: utils.c:781

References ao2_cleanup, ast_channel_name(), ast_channel_tech_pvt(), ast_copy_pj_str(), ast_copy_string(), ast_escape_quoted(), ast_log, AST_LOG_WARNING, ast_sip_get_pjsip_endpoint(), ast_sip_session_get_datastore(), ast_strdupa, ast_strlen_zero(), buf, ast_sip_session::inv_session, transport_info_data::local_addr, LOG_WARNING, NULL, print_escaped_uri(), RAII_VAR, transport_info_data::remote_addr, ast_sip_session::request_uri, ast_sip_channel_pvt::session, ast_sip_session::t38state, t38state_to_string, and type.

Referenced by read_pjsip().

◆ channel_read_rtcp()

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

Definition at line 134 of file dialplan_functions.c.

135{
136 struct ast_sip_channel_pvt *channel = ast_channel_tech_pvt(chan);
137 struct ast_sip_session *session;
138 struct ast_sip_session_media *media;
139
140 if (!channel) {
141 ast_log(AST_LOG_WARNING, "Channel %s has no pvt!\n", ast_channel_name(chan));
142 return -1;
143 }
144
145 session = channel->session;
146 if (!session) {
147 ast_log(AST_LOG_WARNING, "Channel %s has no session!\n", ast_channel_name(chan));
148 return -1;
149 }
150
151 if (ast_strlen_zero(type)) {
152 ast_log(AST_LOG_WARNING, "You must supply a type field for 'rtcp' information\n");
153 return -1;
154 }
155
156 if (ast_strlen_zero(field) || !strcmp(field, "audio")) {
157 media = session->active_media_state->default_session[AST_MEDIA_TYPE_AUDIO];
158 } else if (!strcmp(field, "video")) {
159 media = session->active_media_state->default_session[AST_MEDIA_TYPE_VIDEO];
160 } else {
161 ast_log(AST_LOG_WARNING, "Unknown media type field '%s' for 'rtcp' information\n", field);
162 return -1;
163 }
164
165 if (!media || !media->rtp) {
166 ast_log(AST_LOG_WARNING, "Channel %s has no %s media/RTP session\n",
167 ast_channel_name(chan), S_OR(field, "audio"));
168 return -1;
169 }
170
171 if (!strncasecmp(type, "all", 3)) {
173
174 if (!strcasecmp(type, "all_jitter")) {
176 } else if (!strcasecmp(type, "all_rtt")) {
178 } else if (!strcasecmp(type, "all_loss")) {
180 } else if (!strcasecmp(type, "all_mes")) {
182 }
183
184 if (!ast_rtp_instance_get_quality(media->rtp, stat_field, buf, buflen)) {
185 ast_log(AST_LOG_WARNING, "Unable to retrieve 'rtcp' statistics for %s\n", ast_channel_name(chan));
186 return -1;
187 }
188 } else {
189 struct ast_rtp_instance_stats stats;
190 int i;
191 struct {
192 const char *name;
193 enum { INT, DBL } type;
194 union {
195 unsigned int *i4;
196 double *d8;
197 };
198 } lookup[] = {
199 { "txcount", INT, { .i4 = &stats.txcount, }, },
200 { "rxcount", INT, { .i4 = &stats.rxcount, }, },
201 { "txjitter", DBL, { .d8 = &stats.txjitter, }, },
202 { "rxjitter", DBL, { .d8 = &stats.rxjitter, }, },
203 { "remote_maxjitter", DBL, { .d8 = &stats.remote_maxjitter, }, },
204 { "remote_minjitter", DBL, { .d8 = &stats.remote_minjitter, }, },
205 { "remote_normdevjitter", DBL, { .d8 = &stats.remote_normdevjitter, }, },
206 { "remote_stdevjitter", DBL, { .d8 = &stats.remote_stdevjitter, }, },
207 { "local_maxjitter", DBL, { .d8 = &stats.local_maxjitter, }, },
208 { "local_minjitter", DBL, { .d8 = &stats.local_minjitter, }, },
209 { "local_normdevjitter", DBL, { .d8 = &stats.local_normdevjitter, }, },
210 { "local_stdevjitter", DBL, { .d8 = &stats.local_stdevjitter, }, },
211 { "txploss", INT, { .i4 = &stats.txploss, }, },
212 { "rxploss", INT, { .i4 = &stats.rxploss, }, },
213 { "remote_maxrxploss", DBL, { .d8 = &stats.remote_maxrxploss, }, },
214 { "remote_minrxploss", DBL, { .d8 = &stats.remote_minrxploss, }, },
215 { "remote_normdevrxploss", DBL, { .d8 = &stats.remote_normdevrxploss, }, },
216 { "remote_stdevrxploss", DBL, { .d8 = &stats.remote_stdevrxploss, }, },
217 { "local_maxrxploss", DBL, { .d8 = &stats.local_maxrxploss, }, },
218 { "local_minrxploss", DBL, { .d8 = &stats.local_minrxploss, }, },
219 { "local_normdevrxploss", DBL, { .d8 = &stats.local_normdevrxploss, }, },
220 { "local_stdevrxploss", DBL, { .d8 = &stats.local_stdevrxploss, }, },
221 { "rtt", DBL, { .d8 = &stats.rtt, }, },
222 { "maxrtt", DBL, { .d8 = &stats.maxrtt, }, },
223 { "minrtt", DBL, { .d8 = &stats.minrtt, }, },
224 { "normdevrtt", DBL, { .d8 = &stats.normdevrtt, }, },
225 { "stdevrtt", DBL, { .d8 = &stats.stdevrtt, }, },
226 { "local_ssrc", INT, { .i4 = &stats.local_ssrc, }, },
227 { "remote_ssrc", INT, { .i4 = &stats.remote_ssrc, }, },
228 { "txmes", DBL, { .d8 = &stats.txmes, }, },
229 { "rxmes", DBL, { .d8 = &stats.rxmes, }, },
230 { "remote_maxmes", DBL, { .d8 = &stats.remote_maxmes, }, },
231 { "remote_minmes", DBL, { .d8 = &stats.remote_minmes, }, },
232 { "remote_normdevmes", DBL, { .d8 = &stats.remote_normdevmes, }, },
233 { "remote_stdevmes", DBL, { .d8 = &stats.remote_stdevmes, }, },
234 { "local_maxmes", DBL, { .d8 = &stats.local_maxmes, }, },
235 { "local_minmes", DBL, { .d8 = &stats.local_minmes, }, },
236 { "local_normdevmes", DBL, { .d8 = &stats.local_normdevmes, }, },
237 { "local_stdevmes", DBL, { .d8 = &stats.local_stdevmes, }, },
238 { NULL, },
239 };
240
242 ast_log(AST_LOG_WARNING, "Unable to retrieve 'rtcp' statistics for %s\n", ast_channel_name(chan));
243 return -1;
244 }
245
246 for (i = 0; !ast_strlen_zero(lookup[i].name); i++) {
247 if (!strcasecmp(type, lookup[i].name)) {
248 if (lookup[i].type == INT) {
249 snprintf(buf, buflen, "%u", *lookup[i].i4);
250 } else {
251 snprintf(buf, buflen, "%f", *lookup[i].d8);
252 }
253 return 0;
254 }
255 }
256 ast_log(AST_LOG_WARNING, "Unrecognized argument '%s' for 'rtcp' information\n", type);
257 return -1;
258 }
259
260 return 0;
261}
static struct ast_mansession session
@ AST_MEDIA_TYPE_AUDIO
Definition: codec.h:32
@ AST_MEDIA_TYPE_VIDEO
Definition: codec.h:33
static const char name[]
Definition: format_mp3.c:68
ast_rtp_instance_stat_field
Definition: rtp_engine.h:168
@ AST_RTP_INSTANCE_STAT_FIELD_QUALITY_LOSS
Definition: rtp_engine.h:174
@ AST_RTP_INSTANCE_STAT_FIELD_QUALITY_RTT
Definition: rtp_engine.h:176
@ AST_RTP_INSTANCE_STAT_FIELD_QUALITY
Definition: rtp_engine.h:170
@ AST_RTP_INSTANCE_STAT_FIELD_QUALITY_JITTER
Definition: rtp_engine.h:172
@ AST_RTP_INSTANCE_STAT_FIELD_QUALITY_MES
Definition: rtp_engine.h:178
@ AST_RTP_INSTANCE_STAT_ALL
Definition: rtp_engine.h:184
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.
Definition: rtp_engine.c:2477
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.
Definition: rtp_engine.c:2459
#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
A structure containing SIP session media information.
struct ast_rtp_instance * rtp
RTP instance itself.
A structure describing a SIP session.

References ast_channel_name(), ast_channel_tech_pvt(), ast_log, AST_LOG_WARNING, AST_MEDIA_TYPE_AUDIO, AST_MEDIA_TYPE_VIDEO, 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_sip_session_media::rtp, 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_sip_channel_pvt::session, session, 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 read_pjsip().

◆ channel_read_rtp()

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

Definition at line 67 of file dialplan_functions.c.

68{
69 struct ast_sip_channel_pvt *channel = ast_channel_tech_pvt(chan);
71 struct ast_sip_session_media *media;
72 struct ast_sockaddr addr;
73
74 if (!channel) {
75 ast_log(AST_LOG_WARNING, "Channel %s has no pvt!\n", ast_channel_name(chan));
76 return -1;
77 }
78
79 session = channel->session;
80 if (!session) {
81 ast_log(AST_LOG_WARNING, "Channel %s has no session!\n", ast_channel_name(chan));
82 return -1;
83 }
84
85 if (ast_strlen_zero(type)) {
86 ast_log(AST_LOG_WARNING, "You must supply a type field for 'rtp' information\n");
87 return -1;
88 }
89
90 if (ast_strlen_zero(field) || !strcmp(field, "audio")) {
91 media = session->active_media_state->default_session[AST_MEDIA_TYPE_AUDIO];
92 } else if (!strcmp(field, "video")) {
93 media = session->active_media_state->default_session[AST_MEDIA_TYPE_VIDEO];
94 } else {
95 ast_log(AST_LOG_WARNING, "Unknown media type field '%s' for 'rtp' information\n", field);
96 return -1;
97 }
98
99 if (!media || !media->rtp) {
100 ast_log(AST_LOG_WARNING, "Channel %s has no %s media/RTP session\n",
101 ast_channel_name(chan), S_OR(field, "audio"));
102 return -1;
103 }
104
105 if (!strcmp(type, "src")) {
108 } else if (!strcmp(type, "dest")) {
111 } else if (!strcmp(type, "direct")) {
113 } else if (!strcmp(type, "secure")) {
114 if (media->srtp) {
115 struct ast_sdp_srtp *srtp = media->srtp;
117 snprintf(buf, buflen, "%d", flag ? 1 : 0);
118 } else {
119 snprintf(buf, buflen, "%d", 0);
120 }
121 } else if (!strcmp(type, "hold")) {
122 snprintf(buf, buflen, "%d", media->remotely_held ? 1 : 0);
123 } else {
124 ast_log(AST_LOG_WARNING, "Unknown type field '%s' specified for 'rtp' information\n", type);
125 return -1;
126 }
127
128 return 0;
129}
long int flag
Definition: f2c.h:83
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.
Definition: rtp_engine.h:1238
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:664
#define AST_SRTP_CRYPTO_OFFER_OK
Definition: sdp_srtp.h:45
structure for secure RTP audio
Definition: sdp_srtp.h:38
struct ast_sdp_srtp * srtp
Holds SRTP information.
unsigned int remotely_held
Stream is on hold by remote side.
struct ast_sockaddr direct_media_addr
Direct media address.
Socket address structure.
Definition: netsock2.h:97
#define ast_test_flag(p, flag)
Definition: utils.h:63

References ast_channel_name(), ast_channel_tech_pvt(), ast_copy_string(), ast_log, AST_LOG_WARNING, AST_MEDIA_TYPE_AUDIO, AST_MEDIA_TYPE_VIDEO, ast_rtp_instance_get_local_address(), ast_rtp_instance_get_remote_address, ast_sockaddr_stringify(), AST_SRTP_CRYPTO_OFFER_OK, ast_strlen_zero(), ast_test_flag, buf, ast_sip_session_media::direct_media_addr, ast_sip_session_media::remotely_held, ast_sip_session_media::rtp, S_OR, ast_sip_channel_pvt::session, session, ast_sip_session_media::srtp, and type.

Referenced by read_pjsip().

◆ dtmf_mode_refresh_cb()

static int dtmf_mode_refresh_cb ( void *  obj)
static

Definition at line 1040 of file dialplan_functions.c.

1041{
1042 struct refresh_data *data = obj;
1043
1044 if (data->session->inv_session->state == PJSIP_INV_STATE_CONFIRMED) {
1045 ast_debug(3, "Changing DTMF mode on channel %s after OFFER/ANSWER completion. Sending session refresh\n", ast_channel_name(data->session->channel));
1046
1049 } else if (data->session->inv_session->state == PJSIP_INV_STATE_INCOMING) {
1050 ast_debug(3, "Changing DTMF mode on channel %s during OFFER/ANSWER exchange. Updating SDP answer\n", ast_channel_name(data->session->channel));
1052 }
1053
1054 return 0;
1055}
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 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 759 of file dialplan_functions.c.

761{
762 struct ast_stream_topology *topology;
763 int idx;
764 struct ast_stream *stream = NULL;
765 const struct ast_format_cap *caps;
766 size_t accum = 0;
767
768 if (session->inv_session->dlg->state == PJSIP_DIALOG_STATE_ESTABLISHED) {
770
771 /* As we've already answered we need to store our media state until we are ready to send it */
773 if (!state) {
774 return -1;
775 }
776 topology = state->media_state->topology;
777 } else {
778 /* The session is not yet up so we are initially answering or offering */
779 if (!session->pending_media_state->topology) {
780 session->pending_media_state->topology = ast_stream_topology_clone(session->endpoint->media.topology);
781 if (!session->pending_media_state->topology) {
782 return -1;
783 }
784 }
785 topology = session->pending_media_state->topology;
786 }
787
788 /* Find the first suitable stream */
789 for (idx = 0; idx < ast_stream_topology_get_count(topology); ++idx) {
790 stream = ast_stream_topology_get_stream(topology, idx);
791
792 if (ast_stream_get_type(stream) != media_type ||
794 stream = NULL;
795 continue;
796 }
797
798 break;
799 }
800
801 /* If no suitable stream then exit early */
802 if (!stream) {
803 buf[0] = '\0';
804 return 0;
805 }
806
807 caps = ast_stream_get_formats(stream);
808
809 /* Note: buf is not terminated while the string is being built. */
810 for (idx = 0; idx < ast_format_cap_count(caps); ++idx) {
811 struct ast_format *fmt;
812 size_t size;
813
814 fmt = ast_format_cap_get_format(caps, idx);
815
816 /* Add one for a comma or terminator */
817 size = strlen(ast_format_get_name(fmt)) + 1;
818 if (len < size) {
819 ao2_ref(fmt, -1);
820 break;
821 }
822
823 /* Append the format name */
824 strcpy(buf + accum, ast_format_get_name(fmt));/* Safe */
825 ao2_ref(fmt, -1);
826
827 accum += size;
828 len -= size;
829
830 /* The last comma on the built string will be set to the terminator. */
831 buf[accum - 1] = ',';
832 }
833
834 /* Remove the trailing comma or terminate an empty buffer. */
835 buf[accum ? accum - 1 : 0] = '\0';
836 return 0;
837}
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
enum cc_state state
Definition: ccss.c:393
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:400
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:395
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
@ 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:788
int ast_stream_topology_get_count(const struct ast_stream_topology *topology)
Get the number of streams in a topology.
Definition: stream.c:765
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:667
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, session_refresh_state_get_or_alloc(), and state.

Referenced by pjsip_acf_media_offer_read().

◆ media_offer_write_av()

static int media_offer_write_av ( void *  obj)
static

Definition at line 845 of file dialplan_functions.c.

846{
847 struct media_offer_data *data = obj;
848 struct ast_stream_topology *topology;
849 struct ast_stream *stream;
850 struct ast_format_cap *caps;
851
852 if (data->session->inv_session->dlg->state == PJSIP_DIALOG_STATE_ESTABLISHED) {
854
855 /* As we've already answered we need to store our media state until we are ready to send it */
857 if (!state) {
858 return -1;
859 }
860 topology = state->media_state->topology;
861 } else {
862 /* The session is not yet up so we are initially answering or offering */
863 if (!data->session->pending_media_state->topology) {
865 if (!data->session->pending_media_state->topology) {
866 return -1;
867 }
868 }
869 topology = data->session->pending_media_state->topology;
870 }
871
872 /* XXX This method won't work when it comes time to do multistream support. The proper way to do this
873 * will either be to
874 * a) Alter all media streams of a particular type.
875 * b) Change the dialplan function to be able to specify which stream to alter and alter only that
876 * one stream
877 */
879 if (!stream) {
880 return 0;
881 }
882
884 if (!caps) {
885 return -1;
886 }
887
892 ast_stream_set_formats(stream, caps);
893 ast_stream_set_metadata(stream, "pjsip_session_refresh", "force");
894 ao2_ref(caps, -1);
895
896 return 0;
897}
@ 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:320
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:523
@ 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:964
struct ast_stream_topology * topology
Definition: res_pjsip.h:923
struct ast_sip_endpoint_media_configuration media
Definition: res_pjsip.h:996
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(), state, 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 648 of file dialplan_functions.c.

649{
650 struct parse_uri_args *args = data;
651 pj_pool_t *pool;
652 pjsip_name_addr *uri;
653 pjsip_sip_uri *sip_uri;
654 pj_str_t tmp;
655
656 args->ret = 0;
657
658 pool = pjsip_endpt_create_pool(ast_sip_get_pjsip_endpoint(), "ParseUri", 128, 128);
659 if (!pool) {
660 ast_log(LOG_ERROR, "Failed to allocate ParseUri endpoint pool.\n");
661 args->ret = -1;
662 return 0;
663 }
664
665 pj_strdup2_with_null(pool, &tmp, args->uri);
666 uri = (pjsip_name_addr *)pjsip_parse_uri(pool, tmp.ptr, tmp.slen, PJSIP_PARSE_URI_AS_NAMEADDR);
667 if (!uri || (!PJSIP_URI_SCHEME_IS_SIP(uri) && !PJSIP_URI_SCHEME_IS_SIPS(uri))) {
668 ast_log(LOG_WARNING, "Failed to parse URI '%s'\n", args->uri);
669 pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
670 args->ret = -1;
671 return 0;
672 }
673
674 if (!strcmp(args->type, "scheme")) {
675 ast_copy_pj_str(args->buf, pjsip_uri_get_scheme(uri), args->buflen);
676 pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
677 return 0;
678 } else if (!strcmp(args->type, "display")) {
679 ast_copy_pj_str(args->buf, &uri->display, args->buflen);
680 pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
681 return 0;
682 }
683
684 sip_uri = pjsip_uri_get_uri(uri);
685 if (!sip_uri) {
686 ast_log(LOG_ERROR, "Failed to get an URI object for '%s'\n", args->uri);
687 pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
688 args->ret = -1;
689 return 0;
690 }
691
692 if (!strcmp(args->type, "user")) {
693 ast_copy_pj_str(args->buf, &sip_uri->user, args->buflen);
694 } else if (!strcmp(args->type, "passwd")) {
695 ast_copy_pj_str(args->buf, &sip_uri->passwd, args->buflen);
696 } else if (!strcmp(args->type, "host")) {
697 ast_copy_pj_str(args->buf, &sip_uri->host, args->buflen);
698 } else if (!strcmp(args->type, "port")) {
699 snprintf(args->buf, args->buflen, "%d", sip_uri->port);
700 } else if (!strcmp(args->type, "user_param")) {
701 ast_copy_pj_str(args->buf, &sip_uri->user_param, args->buflen);
702 } else if (!strcmp(args->type, "method_param")) {
703 ast_copy_pj_str(args->buf, &sip_uri->method_param, args->buflen);
704 } else if (!strcmp(args->type, "transport_param")) {
705 ast_copy_pj_str(args->buf, &sip_uri->transport_param, args->buflen);
706 } else if (!strcmp(args->type, "ttl_param")) {
707 snprintf(args->buf, args->buflen, "%d", sip_uri->ttl_param);
708 } else if (!strcmp(args->type, "lr_param")) {
709 snprintf(args->buf, args->buflen, "%d", sip_uri->lr_param);
710 } else if (!strcmp(args->type, "maddr_param")) {
711 ast_copy_pj_str(args->buf, &sip_uri->maddr_param, args->buflen);
712 } else {
713 ast_log(AST_LOG_WARNING, "Unknown type part '%s' specified\n", args->type);
714 pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
715 args->ret = -1;
716 return 0;
717 }
718
719 pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
720
721 return 0;
722}
static int tmp()
Definition: bt_open.c:389
#define LOG_ERROR
Struct used to push PJSIP_PARSE_URI function arguments to task processor.
const char * args

References args, ast_copy_pj_str(), ast_log, AST_LOG_WARNING, ast_sip_get_pjsip_endpoint(), LOG_ERROR, LOG_WARNING, tmp(), 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 443 of file dialplan_functions.c.

444{
445 struct pjsip_func_args func_args = { 0, };
446 struct ast_sip_channel_pvt *channel;
447 char *parse = ast_strdupa(data);
448
450 AST_APP_ARG(param);
452 AST_APP_ARG(field);
453 );
454
455 if (!chan) {
456 ast_log(LOG_WARNING, "No channel was provided to %s function.\n", cmd);
457 return -1;
458 }
459
460 /* Check for zero arguments */
461 if (ast_strlen_zero(parse)) {
462 ast_log(LOG_ERROR, "Cannot call %s without arguments\n", cmd);
463 return -1;
464 }
465
467
468 ast_channel_lock(chan);
469
470 /* Sanity check */
471 if (strcmp(ast_channel_tech(chan)->type, "PJSIP")) {
472 ast_log(LOG_WARNING, "Cannot call %s on a non-PJSIP channel\n", cmd);
473 ast_channel_unlock(chan);
474 return 0;
475 }
476
477 channel = ast_channel_tech_pvt(chan);
478 if (!channel) {
479 ast_log(LOG_WARNING, "Channel %s has no pvt!\n", ast_channel_name(chan));
480 ast_channel_unlock(chan);
481 return -1;
482 }
483
484 if (!channel->session) {
485 ast_log(LOG_WARNING, "Channel %s has no session\n", ast_channel_name(chan));
486 ast_channel_unlock(chan);
487 return -1;
488 }
489
490 func_args.session = ao2_bump(channel->session);
491 ast_channel_unlock(chan);
492
493 memset(buf, 0, len);
494
495 func_args.param = args.param;
496 func_args.type = args.type;
497 func_args.field = args.field;
498 func_args.buf = buf;
499 func_args.len = len;
501 ast_log(LOG_WARNING, "Unable to read properties of channel %s: failed to push task\n", ast_channel_name(chan));
502 ao2_ref(func_args.session, -1);
503 return -1;
504 }
505 ao2_ref(func_args.session, -1);
506
507 return func_args.ret;
508}
#define ao2_bump(obj)
Bump refcount on an AO2 object by one, returning the object.
Definition: astobj2.h:480
#define ast_channel_lock(chan)
Definition: channel.h:2922
const struct ast_channel_tech * ast_channel_tech(const struct ast_channel *chan)
#define ast_channel_unlock(chan)
Definition: channel.h:2923
static int read_pjsip(void *data)
int ast_sip_push_task_wait_serializer(struct ast_taskprocessor *serializer, int(*sip_task)(void *), void *task_data)
Push a task to the serializer and wait for it to complete.
Definition: res_pjsip.c:2179
#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.
static char * func_args(char *function)
return a pointer to the arguments of the function, and terminates the function name with '\0'
Struct used to push function arguments to task processor.

References ao2_bump, ao2_ref, args, AST_APP_ARG, ast_channel_lock, ast_channel_name(), ast_channel_tech(), ast_channel_tech_pvt(), 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, func_args(), len(), LOG_ERROR, LOG_WARNING, read_pjsip(), 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 510 of file dialplan_functions.c.

511{
512 RAII_VAR(struct ast_sip_endpoint *, endpoint, NULL, ao2_cleanup);
513 RAII_VAR(struct ast_str *, dial, NULL, ast_free_ptr);
514 const char *aor_name;
515 char *rest;
516
518 AST_APP_ARG(endpoint_name);
519 AST_APP_ARG(aor_name);
520 AST_APP_ARG(request_user);
521 );
522
524
525 if (ast_strlen_zero(args.endpoint_name)) {
526 ast_log(LOG_WARNING, "An endpoint name must be specified when using the '%s' dialplan function\n", cmd);
527 return -1;
528 } else if (!(endpoint = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint", args.endpoint_name))) {
529 ast_log(LOG_WARNING, "Specified endpoint '%s' was not found\n", args.endpoint_name);
530 return -1;
531 }
532
533 aor_name = S_OR(args.aor_name, endpoint->aors);
534
535 if (ast_strlen_zero(aor_name)) {
536 ast_log(LOG_WARNING, "No AOR has been provided and no AORs are configured on endpoint '%s'\n", args.endpoint_name);
537 return -1;
538 } else if (!(dial = ast_str_create(len))) {
539 ast_log(LOG_WARNING, "Could not get enough buffer space for dialing contacts\n");
540 return -1;
541 } else if (!(rest = ast_strdupa(aor_name))) {
542 ast_log(LOG_WARNING, "Could not duplicate provided AORs\n");
543 return -1;
544 }
545
546 while ((aor_name = ast_strip(strsep(&rest, ",")))) {
548 RAII_VAR(struct ao2_container *, contacts, NULL, ao2_cleanup);
549 struct ao2_iterator it_contacts;
550 struct ast_sip_contact *contact;
551
552 if (!aor) {
553 /* If the AOR provided is not found skip it, there may be more */
554 continue;
556 /* No contacts are available, skip it as well */
557 continue;
558 } else if (!ao2_container_count(contacts)) {
559 /* We were given a container but no contacts are in it... */
560 continue;
561 }
562
563 it_contacts = ao2_iterator_init(contacts, 0);
564 for (; (contact = ao2_iterator_next(&it_contacts)); ao2_ref(contact, -1)) {
565 ast_str_append(&dial, -1, "PJSIP/");
566
567 if (!ast_strlen_zero(args.request_user)) {
568 ast_str_append(&dial, -1, "%s@", args.request_user);
569 }
570 ast_str_append(&dial, -1, "%s/%s&", args.endpoint_name, contact->uri);
571 }
572 ao2_iterator_destroy(&it_contacts);
573 }
574
575 /* Trim the '&' at the end off */
576 ast_str_truncate(dial, ast_str_strlen(dial) - 1);
577
579
580 return 0;
581}
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.
char * strsep(char **str, const char *delims)
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:1306
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:1853
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
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:761
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
Definition: strings.h:659
size_t ast_str_strlen(const struct ast_str *buf)
Returns the current length of the string stored within buf.
Definition: strings.h:730
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:478
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:963
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 956 of file dialplan_functions.c.

957{
958 struct ast_sip_channel_pvt *channel;
959
960 if (!chan) {
961 ast_log(LOG_WARNING, "No channel was provided to %s function.\n", cmd);
962 return -1;
963 }
964
965 ast_channel_lock(chan);
966 if (strcmp(ast_channel_tech(chan)->type, "PJSIP")) {
967 ast_log(LOG_WARNING, "Cannot call %s on a non-PJSIP channel\n", cmd);
968 ast_channel_unlock(chan);
969 return -1;
970 }
971
972 channel = ast_channel_tech_pvt(chan);
973
974 if (ast_sip_dtmf_to_str(channel->session->dtmf, buf, len) < 0) {
975 ast_log(LOG_WARNING, "Unknown DTMF mode %d on PJSIP channel %s\n", channel->session->dtmf, ast_channel_name(chan));
976 ast_channel_unlock(chan);
977 return -1;
978 }
979
980 ast_channel_unlock(chan);
981 return 0;
982}
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:2504
enum ast_sip_dtmf_mode dtmf

References ast_channel_lock, ast_channel_name(), ast_channel_tech(), 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 1057 of file dialplan_functions.c.

1058{
1059 struct ast_sip_channel_pvt *channel;
1060 struct ast_sip_session_media *media;
1061 int dsp_features = 0;
1062 int dtmf = -1;
1063 struct refresh_data rdata = {
1065 };
1066
1067 if (!chan) {
1068 ast_log(LOG_WARNING, "No channel was provided to %s function.\n", cmd);
1069 return -1;
1070 }
1071
1072 ast_channel_lock(chan);
1073 if (strcmp(ast_channel_tech(chan)->type, "PJSIP")) {
1074 ast_log(LOG_WARNING, "Cannot call %s on a non-PJSIP channel\n", cmd);
1075 ast_channel_unlock(chan);
1076 return -1;
1077 }
1078
1079 channel = ast_channel_tech_pvt(chan);
1080 rdata.session = channel->session;
1081
1082 dtmf = ast_sip_str_to_dtmf(value);
1083
1084 if (dtmf == -1) {
1085 ast_log(LOG_WARNING, "Cannot set DTMF mode to '%s' on channel '%s' as value is invalid.\n", value,
1086 ast_channel_name(chan));
1087 ast_channel_unlock(chan);
1088 return -1;
1089 }
1090
1091 if (channel->session->dtmf == dtmf) {
1092 /* DTMF mode unchanged, nothing to do! */
1093 ast_channel_unlock(chan);
1094 return 0;
1095 }
1096
1097 channel->session->dtmf = dtmf;
1098
1100
1101 if (media && media->rtp) {
1102 if (channel->session->dtmf == AST_SIP_DTMF_RFC_4733) {
1105 } else if (channel->session->dtmf == AST_SIP_DTMF_INFO) {
1108 } else if (channel->session->dtmf == AST_SIP_DTMF_INBAND) {
1111 } else if (channel->session->dtmf == AST_SIP_DTMF_NONE) {
1114 } else if (channel->session->dtmf == AST_SIP_DTMF_AUTO) {
1116 /* no RFC4733 negotiated, enable inband */
1118 }
1119 } else if (channel->session->dtmf == AST_SIP_DTMF_AUTO_INFO) {
1122 /* if inband, switch to INFO */
1124 }
1125 }
1126 }
1127
1128 if (channel->session->dsp) {
1129 dsp_features = ast_dsp_get_features(channel->session->dsp);
1130 }
1131 if (channel->session->dtmf == AST_SIP_DTMF_INBAND ||
1132 channel->session->dtmf == AST_SIP_DTMF_AUTO) {
1133 dsp_features |= DSP_FEATURE_DIGIT_DETECT;
1134 } else {
1135 dsp_features &= ~DSP_FEATURE_DIGIT_DETECT;
1136 }
1137 if (dsp_features) {
1138 if (!channel->session->dsp) {
1139 if (!(channel->session->dsp = ast_dsp_new())) {
1140 ast_channel_unlock(chan);
1141 return 0;
1142 }
1143 }
1144 ast_dsp_set_features(channel->session->dsp, dsp_features);
1145 } else if (channel->session->dsp) {
1146 ast_dsp_free(channel->session->dsp);
1147 channel->session->dsp = NULL;
1148 }
1149
1150 ast_channel_unlock(chan);
1151
1153}
static int dtmf_mode_refresh_cb(void *obj)
void ast_dsp_free(struct ast_dsp *dsp)
Definition: dsp.c:1783
#define DSP_FEATURE_DIGIT_DETECT
Definition: dsp.h:28
int ast_dsp_get_features(struct ast_dsp *dsp)
Get features.
Definition: dsp.c:1777
void ast_dsp_set_features(struct ast_dsp *dsp, int features)
Select feature set.
Definition: dsp.c:1768
struct ast_dsp * ast_dsp_new(void)
Allocates a new dsp, assumes 8khz for internal sample rate.
Definition: dsp.c:1758
@ AST_SIP_DTMF_NONE
Definition: res_pjsip.h:545
@ AST_SIP_DTMF_AUTO_INFO
Definition: res_pjsip.h:556
@ AST_SIP_DTMF_AUTO
Definition: res_pjsip.h:554
@ AST_SIP_DTMF_INBAND
Definition: res_pjsip.h:550
@ AST_SIP_DTMF_INFO
Definition: res_pjsip.h:552
@ AST_SIP_DTMF_RFC_4733
Definition: res_pjsip.h:548
int ast_sip_str_to_dtmf(const char *dtmf_mode)
Convert the DTMF mode name into an enum.
Definition: res_pjsip.c:2533
@ AST_SIP_SESSION_REFRESH_METHOD_INVITE
Definition: res_pjsip.h:627
enum ast_rtp_dtmf_mode ast_rtp_instance_dtmf_mode_get(struct ast_rtp_instance *instance)
Get the DTMF mode of an RTP instance.
Definition: rtp_engine.c:2150
@ AST_RTP_DTMF_MODE_RFC2833
Definition: rtp_engine.h:152
@ AST_RTP_DTMF_MODE_INBAND
Definition: rtp_engine.h:154
@ AST_RTP_DTMF_MODE_NONE
Definition: rtp_engine.h:150
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.
Definition: rtp_engine.c:2136
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:726
@ AST_RTP_PROPERTY_DTMF
Definition: rtp_engine.h:117
struct ast_sip_session_media * default_session[AST_MEDIA_TYPE_END]
Default media sessions for each type.
struct ast_sip_session_media_state * active_media_state
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(), 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 899 of file dialplan_functions.c.

900{
901 struct ast_sip_channel_pvt *channel;
902
903 if (!chan) {
904 ast_log(LOG_WARNING, "No channel was provided to %s function.\n", cmd);
905 return -1;
906 }
907
908 if (strcmp(ast_channel_tech(chan)->type, "PJSIP")) {
909 ast_log(LOG_WARNING, "Cannot call %s on a non-PJSIP channel\n", cmd);
910 return -1;
911 }
912
913 channel = ast_channel_tech_pvt(chan);
914
915 if (!strcmp(data, "audio")) {
917 } else if (!strcmp(data, "video")) {
919 } else {
920 /* Ensure that the buffer is empty */
921 buf[0] = '\0';
922 }
923
924 return 0;
925}
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(), 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 927 of file dialplan_functions.c.

928{
929 struct ast_sip_channel_pvt *channel;
930 struct media_offer_data mdata = {
931 .value = value
932 };
933
934 if (!chan) {
935 ast_log(LOG_WARNING, "No channel was provided to %s function.\n", cmd);
936 return -1;
937 }
938
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 return -1;
942 }
943
944 channel = ast_channel_tech_pvt(chan);
945 mdata.session = channel->session;
946
947 if (!strcmp(data, "audio")) {
949 } else if (!strcmp(data, "video")) {
951 }
952
954}
static int media_offer_write_av(void *obj)

References ast_channel_tech(), 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 984 of file dialplan_functions.c.

985{
986 struct ast_sip_channel_pvt *channel;
987
988 if (!chan) {
989 ast_log(LOG_WARNING, "No channel was provided to %s function.\n", cmd);
990 return -1;
991 }
992
993 if (len < 3) {
994 ast_log(LOG_WARNING, "%s: buffer too small\n", cmd);
995 return -1;
996 }
997
998 ast_channel_lock(chan);
999 if (strcmp(ast_channel_tech(chan)->type, "PJSIP")) {
1000 ast_log(LOG_WARNING, "Cannot call %s on a non-PJSIP channel\n", cmd);
1001 ast_channel_unlock(chan);
1002 return -1;
1003 }
1004
1005 channel = ast_channel_tech_pvt(chan);
1006 strncpy(buf, AST_YESNO(channel->session->moh_passthrough), len);
1007
1008 ast_channel_unlock(chan);
1009 return 0;
1010}
#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(), 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 1155 of file dialplan_functions.c.

1156{
1157 struct ast_sip_channel_pvt *channel;
1158
1159 if (!chan) {
1160 ast_log(LOG_WARNING, "No channel was provided to %s function.\n", cmd);
1161 return -1;
1162 }
1163
1164 ast_channel_lock(chan);
1165 if (strcmp(ast_channel_tech(chan)->type, "PJSIP")) {
1166 ast_log(LOG_WARNING, "Cannot call %s on a non-PJSIP channel\n", cmd);
1167 ast_channel_unlock(chan);
1168 return -1;
1169 }
1170
1171 channel = ast_channel_tech_pvt(chan);
1173
1174 ast_channel_unlock(chan);
1175
1176 return 0;
1177}
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:2199

References ast_channel_lock, ast_channel_tech(), 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 724 of file dialplan_functions.c.

725{
726 struct parse_uri_args func_args = { 0, };
727
729 AST_APP_ARG(uri_str);
731 );
732
734
735 if (ast_strlen_zero(args.uri_str)) {
736 ast_log(LOG_WARNING, "An URI must be specified when using the '%s' dialplan function\n", cmd);
737 return -1;
738 }
739
740 if (ast_strlen_zero(args.type)) {
741 ast_log(LOG_WARNING, "A type part of the URI must be specified when using the '%s' dialplan function\n", cmd);
742 return -1;
743 }
744
745 memset(buf, 0, buflen);
746
747 func_args.uri = args.uri_str;
748 func_args.type = args.type;
749 func_args.buf = buf;
750 func_args.buflen = buflen;
752 ast_log(LOG_WARNING, "Unable to parse URI: failed to push task\n");
753 return -1;
754 }
755
756 return func_args.ret;
757}
static int parse_uri_cb(void *data)

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

◆ 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 1198 of file dialplan_functions.c.

1199{
1200 struct ast_sip_channel_pvt *channel;
1201 struct refresh_data rdata = {
1203 };
1204
1205 if (!chan) {
1206 ast_log(LOG_WARNING, "No channel was provided to %s function.\n", cmd);
1207 return -1;
1208 }
1209
1210 if (ast_channel_state(chan) != AST_STATE_UP) {
1211 ast_log(LOG_WARNING, "'%s' not allowed on unanswered channel '%s'.\n", cmd, ast_channel_name(chan));
1212 return -1;
1213 }
1214
1215 if (strcmp(ast_channel_tech(chan)->type, "PJSIP")) {
1216 ast_log(LOG_WARNING, "Cannot call %s on a non-PJSIP channel\n", cmd);
1217 return -1;
1218 }
1219
1220 channel = ast_channel_tech_pvt(chan);
1221 rdata.session = channel->session;
1222
1223 if (!strcmp(value, "invite")) {
1225 } else if (!strcmp(value, "update")) {
1227 }
1228
1230}
ast_channel_state
ast_channel states
Definition: channelstate.h:35
@ AST_STATE_UP
Definition: channelstate.h:42
static int refresh_write_cb(void *obj)
@ AST_SIP_SESSION_REFRESH_METHOD_UPDATE
Definition: res_pjsip.h:629

References ast_channel_name(), ast_channel_tech(), 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 1344 of file dialplan_functions.c.

1345{
1346 return ast_manager_hangup_helper(s, m,
1348}
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:4754

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 1324 of file dialplan_functions.c.

1325{
1326 int response_code;
1327 const char *tag = ast_channel_name(chan);
1328
1329 if (ast_strlen_zero(data)) {
1330 ast_log(LOG_WARNING, "%s: Missing response code parameter\n", tag);
1331 return -1;
1332 }
1333
1334 response_code = response_code_validator(tag, data);
1335
1336 pjsip_app_hangup_handler(chan, response_code);
1337
1338 return -1;
1339}

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 1284 of file dialplan_functions.c.

1285{
1286 struct ast_sip_channel_pvt *channel;
1287 struct hangup_data hdata = { NULL, -1 };
1288 const char *tag = ast_channel_name(chan);
1289
1291
1293 if (strcmp(ast_channel_tech(chan)->type, "PJSIP")) {
1294 ast_log(LOG_WARNING, "%s: Not a PJSIP channel\n", tag);
1296 return;
1297 }
1298
1299 channel = ast_channel_tech_pvt(chan);
1300 hdata.session = channel->session;
1301
1302 if (hdata.session->inv_session->role != PJSIP_ROLE_UAS || (
1303 hdata.session->inv_session->state != PJSIP_INV_STATE_INCOMING &&
1304 hdata.session->inv_session->state != PJSIP_INV_STATE_EARLY)) {
1305 ast_log(LOG_WARNING, "%s: Not an incoming channel or invalid state '%s'\n",
1306 tag, pjsip_inv_state_name(hdata.session->inv_session->state));
1308 return;
1309 }
1310
1312
1314 pjsip_hangup, &hdata) != 0) {
1315 ast_log(LOG_WARNING, "%s: failed to push hangup task to serializer\n", tag);
1316 }
1317
1318 return;
1319}
static int pjsip_hangup(void *obj)
Serializer task to hangup channel.
struct ast_sip_session * session
struct ast_channel * chan
Definition: chan_pjsip.c:2484

References ast_channel_lock, ast_channel_name(), ast_channel_tech(), 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 1240 of file dialplan_functions.c.

1241{
1242 struct hangup_data *hdata = obj;
1243 pjsip_tx_data *packet = NULL;
1244
1245 if ((hdata->session->inv_session->state != PJSIP_INV_STATE_DISCONNECTED) &&
1246 (pjsip_inv_answer(hdata->session->inv_session, hdata->response_code, NULL, NULL, &packet) == PJ_SUCCESS)) {
1247 ast_sip_session_send_response(hdata->session, packet);
1248 }
1249
1250 return 0;
1251}
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().

◆ print_escaped_uri()

static int print_escaped_uri ( struct ast_channel chan,
const char *  type,
pjsip_uri_context_e  context,
const void *  uri,
char *  buf,
size_t  size 
)
static

Definition at line 263 of file dialplan_functions.c.

265{
266 int res;
267 char *buf_copy;
268
269 res = pjsip_uri_print(context, uri, buf, size);
270 if (res < 0) {
271 ast_log(LOG_ERROR, "Channel %s: Unescaped %s too long for %d byte buffer\n",
272 ast_channel_name(chan), type, (int) size);
273
274 /* Empty buffer that likely is not terminated. */
275 buf[0] = '\0';
276 return -1;
277 }
278
279 buf_copy = ast_strdupa(buf);
280 ast_escape_quoted(buf_copy, buf, size);
281 return 0;
282}

References ast_channel_name(), ast_escape_quoted(), ast_log, ast_strdupa, buf, voicemailpwcheck::context, LOG_ERROR, and type.

Referenced by channel_read_pjsip().

◆ read_pjsip()

static int read_pjsip ( void *  data)
static

Definition at line 389 of file dialplan_functions.c.

390{
391 struct pjsip_func_args *func_args = data;
392
393 if (!strcmp(func_args->param, "rtp")) {
394 if (!func_args->session->channel) {
395 func_args->ret = -1;
396 return 0;
397 }
398 func_args->ret = channel_read_rtp(func_args->session->channel, func_args->type,
399 func_args->field, func_args->buf,
400 func_args->len);
401 } else if (!strcmp(func_args->param, "rtcp")) {
402 if (!func_args->session->channel) {
403 func_args->ret = -1;
404 return 0;
405 }
406 func_args->ret = channel_read_rtcp(func_args->session->channel, func_args->type,
407 func_args->field, func_args->buf,
408 func_args->len);
409 } else if (!strcmp(func_args->param, "endpoint")) {
410 if (!func_args->session->endpoint) {
411 ast_log(AST_LOG_WARNING, "Channel %s has no endpoint!\n", func_args->session->channel ?
412 ast_channel_name(func_args->session->channel) : "<unknown>");
413 func_args->ret = -1;
414 return 0;
415 }
416 snprintf(func_args->buf, func_args->len, "%s", ast_sorcery_object_get_id(func_args->session->endpoint));
417 } else if (!strcmp(func_args->param, "contact")) {
418 if (!func_args->session->contact) {
419 return 0;
420 }
421 snprintf(func_args->buf, func_args->len, "%s", ast_sorcery_object_get_id(func_args->session->contact));
422 } else if (!strcmp(func_args->param, "aor")) {
423 if (!func_args->session->aor) {
424 return 0;
425 }
426 snprintf(func_args->buf, func_args->len, "%s", ast_sorcery_object_get_id(func_args->session->aor));
427 } else if (!strcmp(func_args->param, "pjsip")) {
428 if (!func_args->session->channel) {
429 func_args->ret = -1;
430 return 0;
431 }
432 func_args->ret = channel_read_pjsip(func_args->session->channel, func_args->type,
433 func_args->field, func_args->buf,
434 func_args->len);
435 } else {
436 func_args->ret = -1;
437 }
438
439 return 0;
440}
static int channel_read_rtp(struct ast_channel *chan, const char *type, const char *field, char *buf, size_t buflen)
static int channel_read_pjsip(struct ast_channel *chan, const char *type, const char *field, char *buf, size_t buflen)
static int channel_read_rtcp(struct ast_channel *chan, const char *type, const char *field, char *buf, size_t buflen)
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
Definition: sorcery.c:2312

References ast_channel_name(), ast_log, AST_LOG_WARNING, ast_sorcery_object_get_id(), channel_read_pjsip(), channel_read_rtcp(), channel_read_rtp(), and func_args().

Referenced by pjsip_acf_channel_read().

◆ refresh_write_cb()

static int refresh_write_cb ( void *  obj)
static

Definition at line 1179 of file dialplan_functions.c.

1180{
1181 struct refresh_data *data = obj;
1183
1185 if (!state) {
1186 return -1;
1187 }
1188
1190 sip_session_response_cb, data->method, 1, state->media_state);
1191
1192 state->media_state = NULL;
1193 ast_sip_session_remove_datastore(data->session, "pjsip_session_refresh");
1194
1195 return 0;
1196}
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(), sip_session_response_cb(), and state.

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 1256 of file dialplan_functions.c.

1257 {
1258 int response_code;
1259
1260 int rc = ast_str_to_int(response, &response_code);
1261 if (rc != 0) {
1262 response_code = ast_sip_str2rc(response);
1263 if (response_code < 0) {
1264 ast_log(LOG_WARNING, "%s: Unrecognized response code parameter '%s'."
1265 " Defaulting to 603 DECLINE\n",
1266 channel_name, response);
1267 return PJSIP_SC_DECLINE;
1268 }
1269 }
1270
1271 if (response_code < 400 || response_code > 699) {
1272 ast_log(LOG_WARNING, "%s: Response code %d is out of range 400 -> 699."
1273 " Defaulting to 603 DECLINE\n",
1274 channel_name, response_code);
1275 return PJSIP_SC_DECLINE;
1276 }
1277 return response_code;
1278}
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:3714

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 590 of file dialplan_functions.c.

591{
592 struct session_refresh_state *state = obj;
593
595 ast_free(obj);
596}
#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 605 of file dialplan_functions.c.

606{
607 RAII_VAR(struct ast_datastore *, datastore, ast_sip_session_get_datastore(session, "pjsip_session_refresh"), ao2_cleanup);
609
610 /* While the datastore refcount is decremented this is operating in the serializer so it will remain valid regardless */
611 if (datastore) {
612 return datastore->data;
613 }
614
615 if (!(datastore = ast_sip_session_alloc_datastore(&session_refresh_datastore, "pjsip_session_refresh"))
616 || !(datastore->data = ast_calloc(1, sizeof(struct session_refresh_state)))
617 || ast_sip_session_add_datastore(session, datastore)) {
618 return NULL;
619 }
620
621 state = datastore->data;
623 if (!state->media_state) {
624 ast_sip_session_remove_datastore(session, "pjsip_session_refresh");
625 return NULL;
626 }
627 state->media_state->topology = ast_stream_topology_clone(session->endpoint->media.topology);
628 if (!state->media_state->topology) {
629 ast_sip_session_remove_datastore(session, "pjsip_session_refresh");
630 return NULL;
631 }
632
633 datastore->data = state;
634
635 return state;
636}
#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, session_refresh_datastore, and state.

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 1017 of file dialplan_functions.c.

1018{
1019 struct ast_format *fmt;
1020
1021 if (!session->channel) {
1022 /* Egads! */
1023 return 0;
1024 }
1025
1027 if (!fmt) {
1028 /* No format? That's weird. */
1029 return 0;
1030 }
1031 ast_channel_set_writeformat(session->channel, fmt);
1033 ast_channel_set_readformat(session->channel, fmt);
1035 ao2_ref(fmt, -1);
1036
1037 return 0;
1038}
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:417

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 599 of file dialplan_functions.c.

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 56 of file dialplan_functions.c.

Referenced by channel_read_pjsip().