Asterisk - The Open Source Telephony Project GIT-master-f36a736
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: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.
Definition: rtp_engine.c:2640
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:2622
#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:1250
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:665
#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 1062 of file dialplan_functions.c.

1063{
1064 struct refresh_data *data = obj;
1065
1066 if (data->session->inv_session->state == PJSIP_INV_STATE_CONFIRMED) {
1067 ast_debug(3, "Changing DTMF mode on channel %s after OFFER/ANSWER completion. Sending session refresh\n", ast_channel_name(data->session->channel));
1068
1071 } else if (data->session->inv_session->state == PJSIP_INV_STATE_INCOMING) {
1072 ast_debug(3, "Changing DTMF mode on channel %s during OFFER/ANSWER exchange. Updating SDP answer\n", ast_channel_name(data->session->channel));
1074 }
1075
1076 return 0;
1077}
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 781 of file dialplan_functions.c.

783{
784 struct ast_stream_topology *topology;
785 int idx;
786 struct ast_stream *stream = NULL;
787 const struct ast_format_cap *caps;
788 size_t accum = 0;
789
790 if (session->inv_session->dlg->state == PJSIP_DIALOG_STATE_ESTABLISHED) {
792
793 /* As we've already answered we need to store our media state until we are ready to send it */
795 if (!state) {
796 return -1;
797 }
798 topology = state->media_state->topology;
799 } else {
800 /* The session is not yet up so we are initially answering or offering */
801 if (!session->pending_media_state->topology) {
802 session->pending_media_state->topology = ast_stream_topology_clone(session->endpoint->media.topology);
803 if (!session->pending_media_state->topology) {
804 return -1;
805 }
806 }
807 topology = session->pending_media_state->topology;
808 }
809
810 /* Find the first suitable stream */
811 for (idx = 0; idx < ast_stream_topology_get_count(topology); ++idx) {
812 stream = ast_stream_topology_get_stream(topology, idx);
813
814 if (ast_stream_get_type(stream) != media_type ||
816 stream = NULL;
817 continue;
818 }
819
820 break;
821 }
822
823 /* If no suitable stream then exit early */
824 if (!stream) {
825 buf[0] = '\0';
826 return 0;
827 }
828
829 caps = ast_stream_get_formats(stream);
830
831 /* Note: buf is not terminated while the string is being built. */
832 for (idx = 0; idx < ast_format_cap_count(caps); ++idx) {
833 struct ast_format *fmt;
834 size_t size;
835
836 fmt = ast_format_cap_get_format(caps, idx);
837
838 /* Add one for a comma or terminator */
839 size = strlen(ast_format_get_name(fmt)) + 1;
840 if (len < size) {
841 ao2_ref(fmt, -1);
842 break;
843 }
844
845 /* Append the format name */
846 strcpy(buf + accum, ast_format_get_name(fmt));/* Safe */
847 ao2_ref(fmt, -1);
848
849 accum += size;
850 len -= size;
851
852 /* The last comma on the built string will be set to the terminator. */
853 buf[accum - 1] = ',';
854 }
855
856 /* Remove the trailing comma or terminate an empty buffer. */
857 buf[accum ? accum - 1 : 0] = '\0';
858 return 0;
859}
#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: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, 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 867 of file dialplan_functions.c.

868{
869 struct media_offer_data *data = obj;
870 struct ast_stream_topology *topology;
871 struct ast_stream *stream;
872 struct ast_format_cap *caps;
873
874 if (data->session->inv_session->dlg->state == PJSIP_DIALOG_STATE_ESTABLISHED) {
876
877 /* As we've already answered we need to store our media state until we are ready to send it */
879 if (!state) {
880 return -1;
881 }
882 topology = state->media_state->topology;
883 } else {
884 /* The session is not yet up so we are initially answering or offering */
885 if (!data->session->pending_media_state->topology) {
887 if (!data->session->pending_media_state->topology) {
888 return -1;
889 }
890 }
891 topology = data->session->pending_media_state->topology;
892 }
893
894 /* XXX This method won't work when it comes time to do multistream support. The proper way to do this
895 * will either be to
896 * a) Alter all media streams of a particular type.
897 * b) Change the dialplan function to be able to specify which stream to alter and alter only that
898 * one stream
899 */
901 if (!stream) {
902 return 0;
903 }
904
906 if (!caps) {
907 return -1;
908 }
909
914 ast_stream_set_formats(stream, caps);
915 ast_stream_set_metadata(stream, "pjsip_session_refresh", "force");
916 ao2_ref(caps, -1);
917
918 return 0;
919}
@ 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:967
struct ast_stream_topology * topology
Definition: res_pjsip.h:918
struct ast_sip_endpoint_media_configuration media
Definition: res_pjsip.h:991
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:2968
const struct ast_channel_tech * ast_channel_tech(const struct ast_channel *chan)
#define ast_channel_unlock(chan)
Definition: channel.h:2969
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:1305
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:475
Contact associated with an address of record.
Definition: res_pjsip.h:389
const ast_string_field uri
Definition: res_pjsip.h:411
const ast_string_field aor
Definition: res_pjsip.h:411
An entity with which Asterisk communicates.
Definition: res_pjsip.h:958
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 978 of file dialplan_functions.c.

979{
980 struct ast_sip_channel_pvt *channel;
981
982 if (!chan) {
983 ast_log(LOG_WARNING, "No channel was provided to %s function.\n", cmd);
984 return -1;
985 }
986
987 ast_channel_lock(chan);
988 if (strcmp(ast_channel_tech(chan)->type, "PJSIP")) {
989 ast_log(LOG_WARNING, "Cannot call %s on a non-PJSIP channel\n", cmd);
990 ast_channel_unlock(chan);
991 return -1;
992 }
993
994 channel = ast_channel_tech_pvt(chan);
995
996 if (ast_sip_dtmf_to_str(channel->session->dtmf, buf, len) < 0) {
997 ast_log(LOG_WARNING, "Unknown DTMF mode %d on PJSIP channel %s\n", channel->session->dtmf, ast_channel_name(chan));
998 ast_channel_unlock(chan);
999 return -1;
1000 }
1001
1002 ast_channel_unlock(chan);
1003 return 0;
1004}
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 1079 of file dialplan_functions.c.

1080{
1081 struct ast_sip_channel_pvt *channel;
1082 struct ast_sip_session_media *media;
1083 int dsp_features = 0;
1084 int dtmf = -1;
1085 struct refresh_data rdata = {
1087 };
1088
1089 if (!chan) {
1090 ast_log(LOG_WARNING, "No channel was provided to %s function.\n", cmd);
1091 return -1;
1092 }
1093
1094 ast_channel_lock(chan);
1095 if (strcmp(ast_channel_tech(chan)->type, "PJSIP")) {
1096 ast_log(LOG_WARNING, "Cannot call %s on a non-PJSIP channel\n", cmd);
1097 ast_channel_unlock(chan);
1098 return -1;
1099 }
1100
1101 channel = ast_channel_tech_pvt(chan);
1102 rdata.session = channel->session;
1103
1104 dtmf = ast_sip_str_to_dtmf(value);
1105
1106 if (dtmf == -1) {
1107 ast_log(LOG_WARNING, "Cannot set DTMF mode to '%s' on channel '%s' as value is invalid.\n", value,
1108 ast_channel_name(chan));
1109 ast_channel_unlock(chan);
1110 return -1;
1111 }
1112
1113 if (channel->session->dtmf == dtmf) {
1114 /* DTMF mode unchanged, nothing to do! */
1115 ast_channel_unlock(chan);
1116 return 0;
1117 }
1118
1119 channel->session->dtmf = dtmf;
1120
1122
1123 if (media && media->rtp) {
1124 if (channel->session->dtmf == AST_SIP_DTMF_RFC_4733) {
1127 } else if (channel->session->dtmf == AST_SIP_DTMF_INFO) {
1130 } else if (channel->session->dtmf == AST_SIP_DTMF_INBAND) {
1133 } else if (channel->session->dtmf == AST_SIP_DTMF_NONE) {
1136 } else if (channel->session->dtmf == AST_SIP_DTMF_AUTO) {
1138 /* no RFC4733 negotiated, enable inband */
1140 }
1141 } else if (channel->session->dtmf == AST_SIP_DTMF_AUTO_INFO) {
1144 /* if inband, switch to INFO */
1146 }
1147 }
1148 }
1149
1150 if (channel->session->dsp) {
1151 dsp_features = ast_dsp_get_features(channel->session->dsp);
1152 }
1153 if (channel->session->dtmf == AST_SIP_DTMF_INBAND ||
1154 channel->session->dtmf == AST_SIP_DTMF_AUTO) {
1155 dsp_features |= DSP_FEATURE_DIGIT_DETECT;
1156 } else {
1157 dsp_features &= ~DSP_FEATURE_DIGIT_DETECT;
1158 }
1159 if (dsp_features) {
1160 if (!channel->session->dsp) {
1161 if (!(channel->session->dsp = ast_dsp_new())) {
1162 ast_channel_unlock(chan);
1163 return 0;
1164 }
1165 }
1166 ast_dsp_set_features(channel->session->dsp, dsp_features);
1167 } else if (channel->session->dsp) {
1168 ast_dsp_free(channel->session->dsp);
1169 channel->session->dsp = NULL;
1170 }
1171
1172 ast_channel_unlock(chan);
1173
1175}
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:542
@ AST_SIP_DTMF_AUTO_INFO
Definition: res_pjsip.h:553
@ AST_SIP_DTMF_AUTO
Definition: res_pjsip.h:551
@ AST_SIP_DTMF_INBAND
Definition: res_pjsip.h:547
@ AST_SIP_DTMF_INFO
Definition: res_pjsip.h:549
@ AST_SIP_DTMF_RFC_4733
Definition: res_pjsip.h:545
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:622
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:2313
@ 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.
Definition: rtp_engine.c:2299
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:727
@ AST_RTP_PROPERTY_DTMF
Definition: rtp_engine.h:120
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 921 of file dialplan_functions.c.

922{
923 struct ast_sip_channel_pvt *channel;
924
925 if (!chan) {
926 ast_log(LOG_WARNING, "No channel was provided to %s function.\n", cmd);
927 return -1;
928 }
929
930 if (strcmp(ast_channel_tech(chan)->type, "PJSIP")) {
931 ast_log(LOG_WARNING, "Cannot call %s on a non-PJSIP channel\n", cmd);
932 return -1;
933 }
934
935 channel = ast_channel_tech_pvt(chan);
936
937 if (!strcmp(data, "audio")) {
939 } else if (!strcmp(data, "video")) {
941 } else {
942 /* Ensure that the buffer is empty */
943 buf[0] = '\0';
944 }
945
946 return 0;
947}
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 949 of file dialplan_functions.c.

950{
951 struct ast_sip_channel_pvt *channel;
952 struct media_offer_data mdata = {
953 .value = value
954 };
955
956 if (!chan) {
957 ast_log(LOG_WARNING, "No channel was provided to %s function.\n", cmd);
958 return -1;
959 }
960
961 if (strcmp(ast_channel_tech(chan)->type, "PJSIP")) {
962 ast_log(LOG_WARNING, "Cannot call %s on a non-PJSIP channel\n", cmd);
963 return -1;
964 }
965
966 channel = ast_channel_tech_pvt(chan);
967 mdata.session = channel->session;
968
969 if (!strcmp(data, "audio")) {
971 } else if (!strcmp(data, "video")) {
973 }
974
976}
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 1006 of file dialplan_functions.c.

1007{
1008 struct ast_sip_channel_pvt *channel;
1009
1010 if (!chan) {
1011 ast_log(LOG_WARNING, "No channel was provided to %s function.\n", cmd);
1012 return -1;
1013 }
1014
1015 if (len < 3) {
1016 ast_log(LOG_WARNING, "%s: buffer too small\n", cmd);
1017 return -1;
1018 }
1019
1020 ast_channel_lock(chan);
1021 if (strcmp(ast_channel_tech(chan)->type, "PJSIP")) {
1022 ast_log(LOG_WARNING, "Cannot call %s on a non-PJSIP channel\n", cmd);
1023 ast_channel_unlock(chan);
1024 return -1;
1025 }
1026
1027 channel = ast_channel_tech_pvt(chan);
1028 strncpy(buf, AST_YESNO(channel->session->moh_passthrough), len);
1029
1030 ast_channel_unlock(chan);
1031 return 0;
1032}
#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 1177 of file dialplan_functions.c.

1178{
1179 struct ast_sip_channel_pvt *channel;
1180
1181 if (!chan) {
1182 ast_log(LOG_WARNING, "No channel was provided to %s function.\n", cmd);
1183 return -1;
1184 }
1185
1186 ast_channel_lock(chan);
1187 if (strcmp(ast_channel_tech(chan)->type, "PJSIP")) {
1188 ast_log(LOG_WARNING, "Cannot call %s on a non-PJSIP channel\n", cmd);
1189 ast_channel_unlock(chan);
1190 return -1;
1191 }
1192
1193 channel = ast_channel_tech_pvt(chan);
1195
1196 ast_channel_unlock(chan);
1197
1198 return 0;
1199}
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 int reading_uri_from_var;
728
730 AST_APP_ARG(uri_str);
732 );
733
735
736 reading_uri_from_var = !strcasecmp(cmd, "PJSIP_PARSE_URI_FROM");
737
738 if (reading_uri_from_var) {
739 const char *var;
740
741 if (ast_strlen_zero(args.uri_str)) {
742 ast_log(LOG_WARNING, "The name of a variable containing a URI must be specified when using the '%s' dialplan function\n", cmd);
743 return -1;
744 }
745
746 ast_channel_lock(chan);
747 if ((var = pbx_builtin_getvar_helper(chan, args.uri_str))) {
748 args.uri_str = ast_strdupa(var);
749 }
750 ast_channel_unlock(chan);
751 }
752
753 if (ast_strlen_zero(args.uri_str)) {
754 if (reading_uri_from_var) {
755 ast_log(LOG_WARNING, "The variable provided to the '%s' dialplan function must contain a URI\n", cmd);
756 } else {
757 ast_log(LOG_WARNING, "A URI must be specified when using the '%s' dialplan function\n", cmd);
758 }
759 return -1;
760 }
761
762 if (ast_strlen_zero(args.type)) {
763 ast_log(LOG_WARNING, "A type part of the URI must be specified when using the '%s' dialplan function\n", cmd);
764 return -1;
765 }
766
767 memset(buf, 0, buflen);
768
769 func_args.uri = args.uri_str;
770 func_args.type = args.type;
771 func_args.buf = buf;
772 func_args.buflen = buflen;
774 ast_log(LOG_WARNING, "Unable to parse URI: failed to push task\n");
775 return -1;
776 }
777
778 return func_args.ret;
779}
#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.

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

1221{
1222 struct ast_sip_channel_pvt *channel;
1223 struct refresh_data rdata = {
1225 };
1226
1227 if (!chan) {
1228 ast_log(LOG_WARNING, "No channel was provided to %s function.\n", cmd);
1229 return -1;
1230 }
1231
1232 if (ast_channel_state(chan) != AST_STATE_UP) {
1233 ast_log(LOG_WARNING, "'%s' not allowed on unanswered channel '%s'.\n", cmd, ast_channel_name(chan));
1234 return -1;
1235 }
1236
1237 if (strcmp(ast_channel_tech(chan)->type, "PJSIP")) {
1238 ast_log(LOG_WARNING, "Cannot call %s on a non-PJSIP channel\n", cmd);
1239 return -1;
1240 }
1241
1242 channel = ast_channel_tech_pvt(chan);
1243 rdata.session = channel->session;
1244
1245 if (!strcmp(value, "invite")) {
1247 } else if (!strcmp(value, "update")) {
1249 }
1250
1252}
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:624

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

1367{
1368 return ast_manager_hangup_helper(s, m,
1370}
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:3342

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

1347{
1348 int response_code;
1349 const char *tag = ast_channel_name(chan);
1350
1351 if (ast_strlen_zero(data)) {
1352 ast_log(LOG_WARNING, "%s: Missing response code parameter\n", tag);
1353 return -1;
1354 }
1355
1356 response_code = response_code_validator(tag, data);
1357
1358 pjsip_app_hangup_handler(chan, response_code);
1359
1360 return -1;
1361}

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

1307{
1308 struct ast_sip_channel_pvt *channel;
1309 struct hangup_data hdata = { NULL, -1 };
1310 const char *tag = ast_channel_name(chan);
1311
1313
1315 if (strcmp(ast_channel_tech(chan)->type, "PJSIP")) {
1316 ast_log(LOG_WARNING, "%s: Not a PJSIP channel\n", tag);
1318 return;
1319 }
1320
1321 channel = ast_channel_tech_pvt(chan);
1322 hdata.session = channel->session;
1323
1324 if (hdata.session->inv_session->role != PJSIP_ROLE_UAS || (
1325 hdata.session->inv_session->state != PJSIP_INV_STATE_INCOMING &&
1326 hdata.session->inv_session->state != PJSIP_INV_STATE_EARLY)) {
1327 ast_log(LOG_WARNING, "%s: Not an incoming channel or invalid state '%s'\n",
1328 tag, pjsip_inv_state_name(hdata.session->inv_session->state));
1330 return;
1331 }
1332
1334
1336 pjsip_hangup, &hdata) != 0) {
1337 ast_log(LOG_WARNING, "%s: failed to push hangup task to serializer\n", tag);
1338 }
1339
1340 return;
1341}
static int pjsip_hangup(void *obj)
Serializer task to hangup channel.
struct ast_sip_session * session
struct ast_channel * chan
Definition: chan_pjsip.c:2487

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

1263{
1264 struct hangup_data *hdata = obj;
1265 pjsip_tx_data *packet = NULL;
1266
1267 if ((hdata->session->inv_session->state != PJSIP_INV_STATE_DISCONNECTED) &&
1268 (pjsip_inv_answer(hdata->session->inv_session, hdata->response_code, NULL, NULL, &packet) == PJ_SUCCESS)) {
1269 ast_sip_session_send_response(hdata->session, packet);
1270 }
1271
1272 return 0;
1273}
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:2317

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

1202{
1203 struct refresh_data *data = obj;
1205
1207 if (!state) {
1208 return -1;
1209 }
1210
1212 sip_session_response_cb, data->method, 1, state->media_state);
1213
1214 state->media_state = NULL;
1215 ast_sip_session_remove_datastore(data->session, "pjsip_session_refresh");
1216
1217 return 0;
1218}
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 1278 of file dialplan_functions.c.

1279 {
1280 int response_code;
1281
1282 int rc = ast_str_to_int(response, &response_code);
1283 if (rc != 0) {
1284 response_code = ast_sip_str2rc(response);
1285 if (response_code < 0) {
1286 ast_log(LOG_WARNING, "%s: Unrecognized response code parameter '%s'."
1287 " Defaulting to 603 DECLINE\n",
1288 channel_name, response);
1289 return PJSIP_SC_DECLINE;
1290 }
1291 }
1292
1293 if (response_code < 400 || response_code > 699) {
1294 ast_log(LOG_WARNING, "%s: Response code %d is out of range 400 -> 699."
1295 " Defaulting to 603 DECLINE\n",
1296 channel_name, response_code);
1297 return PJSIP_SC_DECLINE;
1298 }
1299 return response_code;
1300}
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 1039 of file dialplan_functions.c.

1040{
1041 struct ast_format *fmt;
1042
1043 if (!session->channel) {
1044 /* Egads! */
1045 return 0;
1046 }
1047
1049 if (!fmt) {
1050 /* No format? That's weird. */
1051 return 0;
1052 }
1053 ast_channel_set_writeformat(session->channel, fmt);
1055 ast_channel_set_readformat(session->channel, fmt);
1057 ao2_ref(fmt, -1);
1058
1059 return 0;
1060}
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().