Asterisk - The Open Source Telephony Project GIT-master-f36a736
Functions | Variables
res_pjsip_path.c File Reference
#include "asterisk.h"
#include <pjsip.h>
#include <pjsip_ua.h>
#include "asterisk/res_pjsip.h"
#include "asterisk/res_pjsip_session.h"
#include "asterisk/module.h"
#include "asterisk/strings.h"
Include dependency graph for res_pjsip_path.c:

Go to the source code of this file.

Functions

static void __reg_module (void)
 
static void __unreg_module (void)
 
static int add_supported (pjsip_tx_data *tdata)
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
static struct ast_sip_aorfind_aor (struct ast_sip_contact *contact)
 
static struct ast_sip_aorfind_aor2 (struct ast_sip_endpoint *endpoint, pjsip_uri *uri)
 
static struct ast_sip_contactfind_contact (struct ast_sip_aor *aor, pjsip_uri *uri)
 
static int load_module (void)
 
static int path_get_string (pj_pool_t *pool, struct ast_sip_contact *contact, pj_str_t *path_str)
 Get the path string associated with this contact and tdata. More...
 
static void path_outgoing_request (struct ast_sip_endpoint *endpoint, struct ast_sip_contact *contact, pjsip_tx_data *tdata)
 
static void path_outgoing_response (struct ast_sip_endpoint *endpoint, struct ast_sip_contact *contact, pjsip_tx_data *tdata)
 
static void path_session_outgoing_request (struct ast_sip_session *session, pjsip_tx_data *tdata)
 
static void path_session_outgoing_response (struct ast_sip_session *session, pjsip_tx_data *tdata)
 
static int unload_module (void)
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "PJSIP Path Header Support" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_APP_DEPEND, .requires = "res_pjsip,res_pjsip_session", }
 
static const struct ast_module_infoast_module_info = &__mod_info
 
static const pj_str_t PATH_NAME = { "Path", 4 }
 
static struct ast_sip_session_supplement path_session_supplement
 
static struct ast_sip_supplement path_supplement
 
static pj_str_t PATH_SUPPORTED_NAME = { "path", 4 }
 

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 332 of file res_pjsip_path.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 332 of file res_pjsip_path.c.

◆ add_supported()

static int add_supported ( pjsip_tx_data *  tdata)
static

Definition at line 174 of file res_pjsip_path.c.

175{
176 pjsip_supported_hdr *hdr;
177 int i;
178
179 hdr = pjsip_msg_find_hdr(tdata->msg, PJSIP_H_SUPPORTED, NULL);
180 if (!hdr) {
181 /* insert a new Supported header */
182 hdr = pjsip_supported_hdr_create(tdata->pool);
183 if (!hdr) {
184 return -1;
185 }
186
187 pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr *)hdr);
188 }
189
190 /* Don't add the value if it's already there */
191 for (i = 0; i < hdr->count; ++i) {
192 if (pj_stricmp(&hdr->values[i], &PATH_SUPPORTED_NAME) == 0) {
193 return 0;
194 }
195 }
196
197 if (hdr->count >= PJSIP_GENERIC_ARRAY_MAX_COUNT) {
198 return -1;
199 }
200
201 /* add on to the existing Supported header */
202 pj_strassign(&hdr->values[hdr->count++], &PATH_SUPPORTED_NAME);
203
204 return 0;
205}
static pj_str_t PATH_SUPPORTED_NAME
#define NULL
Definition: resample.c:96

References NULL, and PATH_SUPPORTED_NAME.

Referenced by path_outgoing_request(), and path_outgoing_response().

◆ AST_MODULE_SELF_SYM()

struct ast_module * AST_MODULE_SELF_SYM ( void  )

Definition at line 332 of file res_pjsip_path.c.

◆ find_aor()

static struct ast_sip_aor * find_aor ( struct ast_sip_contact contact)
static

Definition at line 39 of file res_pjsip_path.c.

40{
41 if (!contact) {
42 return NULL;
43 }
44 if (ast_strlen_zero(contact->aor)) {
45 return NULL;
46 }
47
48 return ast_sip_location_retrieve_aor(contact->aor);
49}
struct ast_sip_aor * ast_sip_location_retrieve_aor(const char *aor_name)
Retrieve a named AOR.
Definition: location.c:147
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
const ast_string_field aor
Definition: res_pjsip.h:411

References ast_sip_contact::aor, ast_sip_location_retrieve_aor(), ast_strlen_zero(), and NULL.

Referenced by path_outgoing_request(), and path_outgoing_response().

◆ find_aor2()

static struct ast_sip_aor * find_aor2 ( struct ast_sip_endpoint endpoint,
pjsip_uri *  uri 
)
static

Definition at line 51 of file res_pjsip_path.c.

52{
53 char *configured_aors, *aor_name;
54 const pj_str_t *uri_username;
55 const pj_str_t *uri_hostname;
56 char *domain_name;
57 char *username;
58 struct ast_str *id = NULL;
59
60 if (ast_strlen_zero(endpoint->aors)) {
61 return NULL;
62 }
63
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);
67
68 uri_username = ast_sip_pjsip_uri_get_username(uri);
69 username = ast_alloca(uri_username->slen + 1);
70 ast_copy_pj_str(username, uri_username, uri_username->slen + 1);
71
72 /*
73 * We may want to match without any user options getting
74 * in the way.
75 */
77
78 configured_aors = ast_strdupa(endpoint->aors);
79
80 /* Iterate the configured AORs to see if the user or the user+domain match */
81 while ((aor_name = ast_strip(strsep(&configured_aors, ",")))) {
82 struct ast_sip_domain_alias *alias = NULL;
83
84 if (ast_strlen_zero(aor_name)) {
85 continue;
86 }
87
88 if (!strcmp(username, aor_name)) {
89 break;
90 }
91
92 if (!id && !(id = ast_str_create(strlen(username) + uri_hostname->slen + 2))) {
93 aor_name = NULL;
94 break;
95 }
96
97 ast_str_set(&id, 0, "%s@", username);
98 if ((alias = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "domain_alias", domain_name))) {
99 ast_str_append(&id, 0, "%s", alias->domain);
100 ao2_cleanup(alias);
101 } else {
102 ast_str_append(&id, 0, "%s", domain_name);
103 }
104
105 if (!strcmp(aor_name, ast_str_buffer(id))) {
106 break;
107 }
108 }
109 ast_free(id);
110
111 if (ast_strlen_zero(aor_name)) {
112 return NULL;
113 }
114
115 return ast_sip_location_retrieve_aor(aor_name);
116}
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: astmm.h:288
#define ast_free(a)
Definition: astmm.h:180
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:298
#define ao2_cleanup(obj)
Definition: astobj2.h:1934
char * strsep(char **str, const char *delims)
const pj_str_t * ast_sip_pjsip_uri_get_username(pjsip_uri *uri)
Get the user portion of the pjsip_uri.
Definition: res_pjsip.c:3477
#define AST_SIP_USER_OPTIONS_TRUNCATE_CHECK(str)
Truncate the URI user field options string if enabled.
Definition: res_pjsip.h:3350
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_sorcery * ast_sip_get_sorcery(void)
Get a pointer to the SIP sorcery structure.
const pj_str_t * ast_sip_pjsip_uri_get_hostname(pjsip_uri *uri)
Get the host portion of the pjsip_uri.
Definition: res_pjsip.c:3496
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
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
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
Definition: strings.h:1113
char * ast_strip(char *s)
Strip leading/trailing whitespace from a string.
Definition: strings.h:223
const ast_string_field domain
Definition: res_pjsip.h:320
const ast_string_field aors
Definition: res_pjsip.h:987
Support for dynamic strings.
Definition: strings.h:623

References ao2_cleanup, ast_sip_endpoint::aors, ast_alloca, ast_copy_pj_str(), ast_free, ast_sip_get_sorcery(), ast_sip_location_retrieve_aor(), ast_sip_pjsip_uri_get_hostname(), ast_sip_pjsip_uri_get_username(), AST_SIP_USER_OPTIONS_TRUNCATE_CHECK, ast_sorcery_retrieve_by_id(), ast_str_append(), ast_str_buffer(), ast_str_create, ast_str_set(), ast_strdupa, ast_strip(), ast_strlen_zero(), ast_sip_domain_alias::domain, NULL, and strsep().

Referenced by path_outgoing_request().

◆ find_contact()

static struct ast_sip_contact * find_contact ( struct ast_sip_aor aor,
pjsip_uri *  uri 
)
static

Definition at line 118 of file res_pjsip_path.c.

119{
120 struct ao2_iterator it_contacts;
121 struct ast_sip_contact *contact;
122 char contact_buf[512];
123 int contact_buf_len;
124 int res = 0;
125
126 RAII_VAR(struct ao2_container *, contacts, NULL, ao2_cleanup);
127
128 if (!(contacts = ast_sip_location_retrieve_aor_contacts(aor))) {
129 /* No contacts are available, skip it as well */
130 return NULL;
131 } else if (!ao2_container_count(contacts)) {
132 /* We were given a container but no contacts are in it... */
133 return NULL;
134 }
135
136 contact_buf_len = pjsip_uri_print(PJSIP_URI_IN_CONTACT_HDR, uri, contact_buf, 512);
137 contact_buf[contact_buf_len] = '\0';
138
139 it_contacts = ao2_iterator_init(contacts, 0);
140 for (; (contact = ao2_iterator_next(&it_contacts)); ao2_ref(contact, -1)) {
141 if (!strcmp(contact_buf, contact->uri)) {
142 res = 1;
143 break;
144 }
145 }
146 ao2_iterator_destroy(&it_contacts);
147 if (!res) {
148 return NULL;
149 }
150 return contact;
151}
#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.
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
struct ao2_container * ast_sip_location_retrieve_aor_contacts(const struct ast_sip_aor *aor)
Retrieve all contacts currently available for an AOR.
Definition: location.c:247
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
Contact associated with an address of record.
Definition: res_pjsip.h:389
const ast_string_field uri
Definition: res_pjsip.h:411
#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

References ao2_cleanup, ao2_container_count(), ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_ref, ast_sip_contact::aor, ast_sip_location_retrieve_aor_contacts(), NULL, RAII_VAR, and ast_sip_contact::uri.

Referenced by path_outgoing_request().

◆ load_module()

static int load_module ( void  )
static

Definition at line 311 of file res_pjsip_path.c.

312{
315
317}
@ AST_MODULE_LOAD_SUCCESS
Definition: module.h:70
void ast_sip_register_supplement(struct ast_sip_supplement *supplement)
Register a supplement to SIP out of dialog processing.
Definition: res_pjsip.c:1456
static struct ast_sip_supplement path_supplement
static struct ast_sip_session_supplement path_session_supplement
#define ast_sip_session_register_supplement(supplement)

References AST_MODULE_LOAD_SUCCESS, ast_sip_register_supplement(), ast_sip_session_register_supplement, path_session_supplement, and path_supplement.

◆ path_get_string()

static int path_get_string ( pj_pool_t *  pool,
struct ast_sip_contact contact,
pj_str_t *  path_str 
)
static

Get the path string associated with this contact and tdata.

Parameters
pool
contactThe URI identifying the associated contact
path_strThe place to store the retrieved path information
Return values
zeroon success
non-zeroon failure or no available path information

Definition at line 164 of file res_pjsip_path.c.

165{
166 if (!contact || ast_strlen_zero(contact->path)) {
167 return -1;
168 }
169
170 *path_str = pj_strdup3(pool, contact->path);
171 return 0;
172}
const ast_string_field path
Definition: res_pjsip.h:411

References ast_strlen_zero(), and ast_sip_contact::path.

Referenced by path_outgoing_response().

◆ path_outgoing_request()

static void path_outgoing_request ( struct ast_sip_endpoint endpoint,
struct ast_sip_contact contact,
pjsip_tx_data *  tdata 
)
static

Definition at line 216 of file res_pjsip_path.c.

217{
218 RAII_VAR(struct ast_sip_aor *, aor, NULL, ao2_cleanup);
219
220 if (!endpoint) {
221 return;
222 }
223
224 aor = find_aor(contact);
225 if (!aor) {
226 aor = find_aor2(endpoint, tdata->msg->line.req.uri);
227 }
228 if (!aor || !aor->support_path) {
229 return;
230 }
231
232 if (add_supported(tdata)) {
233 return;
234 }
235
236 if (!contact) {
237 contact = find_contact(aor, tdata->msg->line.req.uri);
238 if (contact) {
239 if (!ast_strlen_zero(contact->path)) {
240 ast_sip_set_outbound_proxy(tdata, contact->path);
241 }
242 ao2_ref(contact, -1);
243 contact = NULL;
244 }
245 } else {
246 if (!ast_strlen_zero(contact->path)) {
247 ast_sip_set_outbound_proxy(tdata, contact->path);
248 }
249 }
250}
int ast_sip_set_outbound_proxy(pjsip_tx_data *tdata, const char *proxy)
Set the outbound proxy for an outbound SIP message.
Definition: res_pjsip.c:1992
static struct ast_sip_aor * find_aor(struct ast_sip_contact *contact)
static struct ast_sip_contact * find_contact(struct ast_sip_aor *aor, pjsip_uri *uri)
static int add_supported(pjsip_tx_data *tdata)
static struct ast_sip_aor * find_aor2(struct ast_sip_endpoint *endpoint, pjsip_uri *uri)
A SIP address of record.
Definition: res_pjsip.h:475

References add_supported(), ao2_cleanup, ao2_ref, ast_sip_contact::aor, ast_sip_set_outbound_proxy(), ast_strlen_zero(), ast_sip_contact::endpoint, find_aor(), find_aor2(), find_contact(), NULL, ast_sip_contact::path, and RAII_VAR.

Referenced by path_session_outgoing_request().

◆ path_outgoing_response()

static void path_outgoing_response ( struct ast_sip_endpoint endpoint,
struct ast_sip_contact contact,
pjsip_tx_data *  tdata 
)
static

Definition at line 265 of file res_pjsip_path.c.

266{
267 struct pjsip_status_line status = tdata->msg->line.status;
268 pj_str_t path_dup;
269 pjsip_generic_string_hdr *path_hdr;
270 RAII_VAR(struct ast_sip_aor *, aor, NULL, ao2_cleanup);
271 pjsip_cseq_hdr *cseq = pjsip_msg_find_hdr(tdata->msg, PJSIP_H_CSEQ, NULL);
272 const pj_str_t REGISTER_METHOD = {"REGISTER", 8};
273
274 if (!endpoint
275 || !pj_stristr(&REGISTER_METHOD, &cseq->method.name)
276 || !PJSIP_IS_STATUS_IN_CLASS(status.code, 200)) {
277 return;
278 }
279
280 aor = find_aor(contact);
281 if (!aor || !aor->support_path || add_supported(tdata)
282 || path_get_string(tdata->pool, contact, &path_dup)) {
283 return;
284 }
285
286 path_hdr = pjsip_generic_string_hdr_create(tdata->pool, &PATH_NAME, &path_dup);
287 if (!path_hdr) {
288 return;
289 }
290
291 pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*)path_hdr);
292}
jack_status_t status
Definition: app_jack.c:146
static int path_get_string(pj_pool_t *pool, struct ast_sip_contact *contact, pj_str_t *path_str)
Get the path string associated with this contact and tdata.
static const pj_str_t PATH_NAME

References add_supported(), ao2_cleanup, find_aor(), NULL, path_get_string(), PATH_NAME, RAII_VAR, and status.

Referenced by path_session_outgoing_response().

◆ path_session_outgoing_request()

static void path_session_outgoing_request ( struct ast_sip_session session,
pjsip_tx_data *  tdata 
)
static

Definition at line 252 of file res_pjsip_path.c.

253{
254 path_outgoing_request(session->endpoint, session->contact, tdata);
255}
static struct ast_mansession session
static void path_outgoing_request(struct ast_sip_endpoint *endpoint, struct ast_sip_contact *contact, pjsip_tx_data *tdata)

References path_outgoing_request(), and session.

◆ path_session_outgoing_response()

static void path_session_outgoing_response ( struct ast_sip_session session,
pjsip_tx_data *  tdata 
)
static

Definition at line 294 of file res_pjsip_path.c.

295{
296 path_outgoing_response(session->endpoint, session->contact, tdata);
297}
static void path_outgoing_response(struct ast_sip_endpoint *endpoint, struct ast_sip_contact *contact, pjsip_tx_data *tdata)

References path_outgoing_response(), and session.

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 319 of file res_pjsip_path.c.

320{
323 return 0;
324}
void ast_sip_unregister_supplement(struct ast_sip_supplement *supplement)
Unregister a an supplement to SIP out of dialog processing.
Definition: res_pjsip.c:1476
void ast_sip_session_unregister_supplement(struct ast_sip_session_supplement *supplement)
Unregister a an supplement to SIP session processing.
Definition: pjsip_session.c:63

References ast_sip_session_unregister_supplement(), ast_sip_unregister_supplement(), path_session_supplement, and path_supplement.

Variable Documentation

◆ __mod_info

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "PJSIP Path Header Support" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_APP_DEPEND, .requires = "res_pjsip,res_pjsip_session", }
static

Definition at line 332 of file res_pjsip_path.c.

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 332 of file res_pjsip_path.c.

◆ PATH_NAME

const pj_str_t PATH_NAME = { "Path", 4 }
static

Definition at line 36 of file res_pjsip_path.c.

Referenced by path_outgoing_response().

◆ path_session_supplement

struct ast_sip_session_supplement path_session_supplement
static
Initial value:
= {
.outgoing_request = path_session_outgoing_request,
.outgoing_response = path_session_outgoing_response,
}
@ AST_SIP_SUPPLEMENT_PRIORITY_CHANNEL
Definition: res_pjsip.h:3185
static void path_session_outgoing_response(struct ast_sip_session *session, pjsip_tx_data *tdata)
static void path_session_outgoing_request(struct ast_sip_session *session, pjsip_tx_data *tdata)

Definition at line 305 of file res_pjsip_path.c.

Referenced by load_module(), and unload_module().

◆ path_supplement

struct ast_sip_supplement path_supplement
static
Initial value:
= {
.outgoing_request = path_outgoing_request,
.outgoing_response = path_outgoing_response,
}

Definition at line 299 of file res_pjsip_path.c.

Referenced by load_module(), and unload_module().

◆ PATH_SUPPORTED_NAME

pj_str_t PATH_SUPPORTED_NAME = { "path", 4 }
static

Definition at line 37 of file res_pjsip_path.c.

Referenced by add_supported().