31 #include "asterisk/res_pjsip.h"
32 #include "asterisk/res_pjsip_session.h"
36 static const pj_str_t PATH_NAME = {
"Path", 4 };
37 static pj_str_t PATH_SUPPORTED_NAME = {
"path", 4 };
44 if (ast_strlen_zero(contact->
aor)) {
48 return ast_sip_location_retrieve_aor(contact->
aor);
53 char *configured_aors, *aor_name;
54 const pj_str_t *uri_username;
55 const pj_str_t *uri_hostname;
60 if (ast_strlen_zero(endpoint->
aors)) {
64 uri_hostname = ast_sip_pjsip_uri_get_hostname(uri);
65 domain_name =
ast_alloca(uri_hostname->slen + 1);
66 ast_copy_pj_str(domain_name, uri_hostname, uri_hostname->slen + 1);
68 uri_username = ast_sip_pjsip_uri_get_username(uri);
70 ast_copy_pj_str(username, uri_username, uri_username->slen + 1);
76 AST_SIP_USER_OPTIONS_TRUNCATE_CHECK(username);
81 while ((aor_name =
ast_strip(strsep(&configured_aors,
",")))) {
84 if (ast_strlen_zero(aor_name)) {
88 if (!strcmp(username, aor_name)) {
92 if (!
id && !(
id =
ast_str_create(strlen(username) + uri_hostname->slen + 2))) {
111 if (ast_strlen_zero(aor_name)) {
115 return ast_sip_location_retrieve_aor(aor_name);
122 char contact_buf[512];
128 if (!(contacts = ast_sip_location_retrieve_aor_contacts(aor))) {
136 contact_buf_len = pjsip_uri_print(PJSIP_URI_IN_CONTACT_HDR, uri, contact_buf, 512);
137 contact_buf[contact_buf_len] =
'\0';
140 for (; (contact = ao2_iterator_next(&it_contacts));
ao2_ref(contact, -1)) {
141 if (!strcmp(contact_buf, contact->
uri)) {
164 static int path_get_string(pj_pool_t *
pool,
struct ast_sip_contact *contact, pj_str_t *path_str)
166 if (!contact || ast_strlen_zero(contact->
path)) {
170 *path_str = pj_strdup3(pool, contact->
path);
174 static int add_supported(pjsip_tx_data *tdata)
176 pjsip_supported_hdr *hdr;
179 hdr = pjsip_msg_find_hdr(tdata->msg, PJSIP_H_SUPPORTED, NULL);
182 hdr = pjsip_supported_hdr_create(tdata->pool);
187 pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr *)hdr);
191 for (i = 0; i < hdr->count; ++i) {
192 if (pj_stricmp(&hdr->values[i], &PATH_SUPPORTED_NAME) == 0) {
197 if (hdr->count >= PJSIP_GENERIC_ARRAY_MAX_COUNT) {
202 pj_strassign(&hdr->values[hdr->count++], &PATH_SUPPORTED_NAME);
224 aor = find_aor(contact);
226 aor = find_aor2(endpoint, tdata->msg->line.req.uri);
232 if (add_supported(tdata)) {
237 contact = find_contact(aor, tdata->msg->line.req.uri);
239 if (!ast_strlen_zero(contact->
path)) {
240 ast_sip_set_outbound_proxy(tdata, contact->
path);
246 if (!ast_strlen_zero(contact->
path)) {
247 ast_sip_set_outbound_proxy(tdata, contact->
path);
252 static void path_session_outgoing_request(
struct ast_sip_session *session, pjsip_tx_data *tdata)
267 struct pjsip_status_line status = tdata->msg->line.status;
269 pjsip_generic_string_hdr *path_hdr;
271 pjsip_cseq_hdr *cseq = pjsip_msg_find_hdr(tdata->msg, PJSIP_H_CSEQ, NULL);
272 const pj_str_t REGISTER_METHOD = {
"REGISTER", 8};
275 || !pj_stristr(®ISTER_METHOD, &cseq->method.name)
276 || !PJSIP_IS_STATUS_IN_CLASS(status.code, 200)) {
280 aor = find_aor(contact);
282 || path_get_string(tdata->pool, contact, &path_dup)) {
286 path_hdr = pjsip_generic_string_hdr_create(tdata->pool, &PATH_NAME, &path_dup);
291 pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*)path_hdr);
294 static void path_session_outgoing_response(
struct ast_sip_session *session, pjsip_tx_data *tdata)
300 .
priority = AST_SIP_SUPPLEMENT_PRIORITY_CHANNEL - 100,
301 .outgoing_request = path_outgoing_request,
302 .outgoing_response = path_outgoing_response,
306 .
priority = AST_SIP_SUPPLEMENT_PRIORITY_CHANNEL - 100,
307 .outgoing_request = path_session_outgoing_request,
308 .outgoing_response = path_session_outgoing_response,
311 static int load_module(
void)
313 ast_sip_register_supplement(&path_supplement);
314 ast_sip_session_register_supplement(&path_session_supplement);
319 static int unload_module(
void)
321 ast_sip_unregister_supplement(&path_supplement);
322 ast_sip_session_unregister_supplement(&path_session_supplement);
326 AST_MODULE_INFO(
ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER,
"PJSIP Path Header Support",
327 .support_level = AST_MODULE_SUPPORT_CORE,
329 .unload = unload_module,
331 .requires =
"res_pjsip,res_pjsip_session",
struct ast_sip_endpoint * endpoint
Asterisk main include file. File version handling, generic pbx functions.
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
String manipulation functions.
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
static pj_pool_t * pool
Global memory pool for configuration and timers.
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
A structure describing a SIP session.
void * ast_sorcery_retrieve_by_id(const struct ast_sorcery *sorcery, const char *type, const char *id)
Retrieve an object using its unique identifier.
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
#define ast_strdupa(s)
duplicate a string in memory from the stack
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
char * ast_strip(char *s)
Strip leading/trailing whitespace from a string.
An entity with which Asterisk communicates.
unsigned int support_path
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Support for dynamic strings.
enum ast_sip_supplement_priority priority
A supplement to SIP message processing.
const ast_string_field domain
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
A supplement to SIP message processing.
const ast_string_field aors
#define ASTERISK_GPL_KEY
The text the key() function should return.
struct ast_sip_contact * contact
Asterisk module definitions.
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
enum ast_sip_supplement_priority priority