41static int find_pidf(
const char *session_name,
struct pjsip_rx_data *rdata,
char *geoloc_uri,
42 char **pidf_body,
unsigned int *pidf_len)
50 if (!rdata->msg_info.msg->body) {
51 ast_log(
LOG_WARNING,
"%s: There's no message body in which to search for '%s'. Skipping\n",
52 session_name, geoloc_uri);
56 if (local_uri[0] ==
'<') {
59 ra = strchr(local_uri,
'>');
72 *pidf_body = rdata->msg_info.msg->body->data;
73 *pidf_len = rdata->msg_info.msg->body->len;
76 pj_str_t cid = pj_str(local_uri);
77 pjsip_multipart_part *mp = pjsip_multipart_find_part_by_cid_str(
78 rdata->tp_info.pool, rdata->msg_info.msg->body, &cid);
82 " but the associated multipart part was not found in the message body. Skipping URI",
83 session_name, geoloc_uri);
86 *pidf_body = mp->body->data;
87 *pidf_len = mp->body->len;
90 " but no pidf document with that content id was found. Skipping URI",
91 session_name, geoloc_uri);
109 "%s: Couldn't allocate a geoloc datastore\n", session_name);
122 "%s: Couldn't add eprofile '%s' to datastore\n", session_name,
144 char *geoloc_hdr_value =
NULL;
145 char *geoloc_routing_hdr_value =
NULL;
146 char *geoloc_uri =
NULL;
149 pjsip_generic_string_hdr *geoloc_hdr =
NULL;
150 pjsip_generic_string_hdr *geoloc_routing_hdr =
NULL;
177 geoloc_routing_hdr = pjsip_msg_find_hdr_by_name(rdata->msg_info.msg,
181 ast_trace(4,
"%s: Message has no Geolocation header\n", session_name);
191 "Done.\n", session_name,
195 "Done.\n", session_name);
200 if (!config_profile) {
203 PJSTR_PRINTF_SPEC "' but endpoint's geoloc_incoming_call_profile doesn't exist. "
204 "Done.\n", session_name,
208 " an invalid geoloc_incoming_call_profile. Done.\n", session_name);
219 if (!config_eprofile) {
224 if (config_eprofile && config_eprofile->effective_location) {
225 ast_trace(4,
"%s: config eprofile '%s' has effective location\n",
226 session_name, config_eprofile->id);
231 ast_trace(4,
"%s: config eprofile '%s' is being used\n",
232 session_name, config_eprofile->id);
244 "%s: Couldn't add config eprofile '%s' to datastore. Fail.\n", session_name,
245 config_eprofile->id);
256 ast_trace(4,
"%s: Either config_eprofile didn't exist or it had no effective location\n",
260 config_eprofile =
NULL;
288 geoloc_hdr_value =
ast_alloca(geoloc_hdr->hvalue.slen + 1);
289 ast_copy_pj_str(geoloc_hdr_value, &geoloc_hdr->hvalue, geoloc_hdr->hvalue.slen + 1);
296 while (geoloc_hdr_value && !incoming_eprofile) {
297 char *pidf_body =
NULL;
298 unsigned int pidf_len = 0;
299 struct ast_xml_doc *incoming_doc =
NULL;
304 if (
ast_strlen_zero(geoloc_uri) || geoloc_uri[0] !=
'<' || strchr(geoloc_uri,
'>') ==
NULL) {
305 ast_log(
LOG_WARNING,
"%s: Geolocation header has no or bad URI '%s'. Skipping\n", session_name,
306 S_OR(geoloc_uri,
"<empty>"));
310 ast_trace(4,
"Processing URI '%s'\n", geoloc_uri);
313 ast_trace(4,
"Processing URI '%s'\n", geoloc_uri);
316 if (!incoming_eprofile) {
317 ast_log(
LOG_WARNING,
"%s: Unable to create effective profile for URI '%s'. Skipping\n",
318 session_name, geoloc_uri);
322 ast_trace(4,
"Processing PIDF-LO '%s'\n", geoloc_uri);
324 rc =
find_pidf(session_name, rdata, geoloc_uri, &pidf_body, &pidf_len);
325 if (rc != 0 || !pidf_body || pidf_len == 0) {
333 session_name, geoloc_uri);
340 if (!incoming_eprofile) {
342 "%s: Couldn't create incoming_eprofile from pidf\n", session_name);
349 if (!incoming_eprofile) {
351 incoming_eprofile = config_eprofile;
354 config_eprofile =
NULL;
355 if (geoloc_routing_hdr) {
356 geoloc_routing_hdr_value =
ast_alloca(geoloc_routing_hdr->hvalue.slen + 1);
358 geoloc_routing_hdr->hvalue.slen + 1);
359 incoming_eprofile->allow_routing_use =
ast_true(geoloc_routing_hdr_value);
363 if (incoming_eprofile) {
367 "%s: Couldn't add eprofile '%s' to channel. Fail.\n", session_name,
368 incoming_eprofile->id);
372 session_name, incoming_eprofile->id);
379 struct pjsip_tx_data *tdata,
struct ast_str **
buf,
const char *session_name)
381 static const pj_str_t from_name = {
"From", 4};
382 static const pj_str_t cid_name = {
"Content-ID", 10 };
384 pjsip_sip_uri *sip_uri;
385 pjsip_generic_string_hdr *cid;
387 pjsip_from_hdr *from = pjsip_msg_find_hdr_by_name(tdata->msg, &from_name,
NULL);
388 pjsip_sdp_info *tdata_sdp_info;
389 pjsip_msg_body *multipart_body =
NULL;
390 pjsip_multipart_part *pidf_part;
391 pj_str_t pidf_body_text;
395 const char *final_doc;
405 ast_trace(5,
"Final pidf: \n%s\n", final_doc);
409 " eprofile '%s'\n\n", session_name, eprofile->
id);
426 tdata_sdp_info = pjsip_tdata_get_sdp_info(tdata);
427 if (tdata_sdp_info->sdp) {
428 ast_trace(4,
"body: %p %u\n", tdata_sdp_info->sdp, (
unsigned)tdata_sdp_info->sdp_err);
430 rc = pjsip_create_multipart_sdp_body(tdata->pool, tdata_sdp_info->sdp, &multipart_body);
431 if (rc != PJ_SUCCESS) {
439 pidf_part = pjsip_multipart_create_part(tdata->pool);
440 pj_cstr(&pidf_body_text, final_doc);
444 pjsip_multipart_add_part(tdata->pool, multipart_body, pidf_part);
446 sip_uri = (pjsip_sip_uri *)pjsip_uri_get_uri(from->uri);
447 alloc_size =
sizeof(
id) + pj_strlen(&sip_uri->host) + 2;
449 sprintf(base_cid,
"%s@%.*s",
451 (
int) pj_strlen(&sip_uri->host), pj_strbuf(&sip_uri->host));
456 cid_value.ptr = pj_pool_alloc(tdata->pool, alloc_size);
457 cid_value.slen = sprintf(cid_value.ptr,
"<%s>", base_cid);
459 cid = pjsip_generic_string_hdr_create(tdata->pool, &cid_name, &cid_value);
461 pj_list_insert_after(&pidf_part->hdr, cid);
463 tdata->msg->body = multipart_body;
479 pjsip_msg_body *orig_body =
NULL;
480 pjsip_generic_string_hdr *geoloc_hdr =
NULL;
481 int eprofile_count = 0;
497 SCOPE_EXIT_RTN(
"%s: Endpoint has no geoloc_outgoing_call_profile. Skipping.\n",
502 if (!config_profile) {
504 "Geolocation info discarded.\n", session_name);
508 if (!config_eprofile) {
513 if (!config_eprofile->effective_location) {
518 ast_trace(4,
"%s: There was no effective location for config profile '%s'\n",
521 config_eprofile =
NULL;
526 ast_trace(4,
"%s: There was no geoloc datastore on the channel\n", session_name);
529 ast_trace(4,
"%s: There are %d geoloc profiles on this channel\n", session_name,
538 ast_trace(4,
"%s: Profile precedence: %s\n\n", session_name,
539 ast_geoloc_precedence_to_name(config_profile->precedence));
541 switch (config_profile->precedence) {
543 final_eprofile = config_eprofile;
545 incoming_eprofile =
NULL;
548 if (incoming_eprofile) {
549 final_eprofile = incoming_eprofile;
551 config_eprofile =
NULL;
553 final_eprofile = config_eprofile;
557 final_eprofile = incoming_eprofile;
559 config_eprofile =
NULL;
562 if (config_eprofile) {
563 final_eprofile = config_eprofile;
565 incoming_eprofile =
NULL;
567 final_eprofile = incoming_eprofile;
572 if (!final_eprofile) {
590 session_name, final_eprofile->
id);
593 orig_body = tdata->msg->body;
596 tdata->msg->body = orig_body;
598 session_name, final_eprofile->
id);
607 ast_trace(4,
"%s: Using URI '%s'\n", session_name, uri);
611 if (geoloc_hdr ==
NULL) {
613 tdata->msg->body = orig_body;
620 tdata->msg->body = orig_body;
622 pj_list_erase(geoloc_hdr);
665 .
requires =
"res_geolocation,res_pjsip,res_pjsip_session,chan_pjsip",
Asterisk main include file. File version handling, generic pbx functions.
static struct ast_mansession session
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
#define ast_strdupa(s)
duplicate a string in memory from the stack
#define ast_malloc(len)
A wrapper for malloc()
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
#define ast_channel_lock(chan)
#define ast_channel_unlock(chan)
int ast_datastore_free(struct ast_datastore *datastore)
Free a data store object.
#define SCOPE_EXIT_RTN(...)
#define SCOPE_EXIT_RTN_VALUE(__return_value,...)
#define SCOPE_EXIT_LOG_RTN_VALUE(__value, __log_level,...)
#define SCOPE_ENTER(level,...)
#define SCOPE_EXIT_LOG_RTN(__log_level,...)
#define ast_trace(level,...)
struct ast_str * ast_variable_list_join(const struct ast_variable *head, const char *item_separator, const char *name_value_separator, const char *quote_char, struct ast_str **str)
Join an ast_variable list with specified separators and quoted values.
Asterisk module definitions.
@ AST_MODFLAG_GLOBAL_SYMBOLS
#define AST_MODULE_INFO(keystr, flags_to_set, desc, fields...)
@ AST_MODPRI_CHANNEL_DEPEND
@ AST_MODULE_SUPPORT_CORE
#define ASTERISK_GPL_KEY
The text the key() function should return.
@ AST_GEOLOC_PRECED_DISCARD_CONFIG
@ AST_GEOLOC_PRECED_PREFER_CONFIG
@ AST_GEOLOC_PRECED_DISCARD_INCOMING
@ AST_GEOLOC_PRECED_PREFER_INCOMING
int ast_geoloc_eprofile_refresh_location(struct ast_geoloc_eprofile *eprofile)
Refresh the effective profile with any changed info.
struct ast_geoloc_eprofile * ast_geoloc_datastore_get_eprofile(struct ast_datastore *ds, int ix)
Retrieve a specific eprofile from a datastore by index.
const char * ast_geoloc_eprofile_to_uri(struct ast_geoloc_eprofile *eprofile, struct ast_channel *chan, struct ast_str **buf, const char *ref_string)
Convert a URI eprofile to a URI string.
struct ast_geoloc_eprofile * ast_geoloc_eprofile_create_from_pidf(struct ast_xml_doc *pidf_xmldoc, const char *geoloc_uri, const char *reference_string)
Allocate a new effective profile from an XML PIDF-LO document.
struct ast_geoloc_eprofile * ast_geoloc_eprofile_create_from_uri(const char *uri, const char *reference_string)
Allocate a new effective profile from a URI.
struct ast_geoloc_profile * ast_geoloc_get_profile(const char *id)
Retrieve a geolocation profile by id.
struct ast_datastore * ast_geoloc_datastore_create(const char *id)
Create an empty geoloc datastore.
int ast_geoloc_datastore_set_inheritance(struct ast_datastore *ds, int inherit)
Sets the inheritance flag on the datastore.
int ast_geoloc_datastore_add_eprofile(struct ast_datastore *ds, struct ast_geoloc_eprofile *eprofile)
Add an eprofile to a datastore.
const char * ast_geoloc_eprofile_to_pidf(struct ast_geoloc_eprofile *eprofile, struct ast_channel *chan, struct ast_str **buf, const char *ref_string)
Convert a single eprofile to a PIDF-LO document.
int ast_geoloc_datastore_size(struct ast_datastore *ds)
Retrieves the number of eprofiles in the datastore.
struct ast_datastore * ast_geoloc_datastore_find(struct ast_channel *chan)
Retrieves the geoloc datastore from a channel, if any.
struct ast_geoloc_eprofile * ast_geoloc_eprofile_create_from_profile(struct ast_geoloc_profile *profile)
Allocate a new effective profile from an existing profile.
pjsip_generic_string_hdr * ast_sip_add_header2(pjsip_tx_data *tdata, const char *name, const char *value)
Add a header to an outbound SIP message, returning a pointer to the header.
pjsip_media_type pjsip_media_type_application_pidf_xml
@ AST_SIP_SUPPLEMENT_PRIORITY_CHANNEL
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.
int ast_sip_are_media_types_equal(pjsip_media_type *a, pjsip_media_type *b)
Compare pjsip media types.
pjsip_media_type pjsip_media_type_multipart_mixed
int ast_sip_add_header(pjsip_tx_data *tdata, const char *name, const char *value)
Add a header to an outbound SIP message.
#define PJSTR_PRINTF_VAR(_v)
#define PJSTR_PRINTF_SPEC
static pj_str_t GEOLOCATION_ROUTING_HDR
static void handle_outgoing_request(struct ast_sip_session *session, struct pjsip_tx_data *tdata)
static int add_eprofile_to_channel(struct ast_sip_session *session, struct ast_geoloc_eprofile *eprofile, struct ast_str *buf)
static const char * add_eprofile_to_tdata(struct ast_geoloc_eprofile *eprofile, struct ast_channel *channel, struct pjsip_tx_data *tdata, struct ast_str **buf, const char *session_name)
static int handle_incoming_request(struct ast_sip_session *session, struct pjsip_rx_data *rdata)
static pj_str_t GEOLOCATION_HDR
static int reload_module(void)
static int find_pidf(const char *session_name, struct pjsip_rx_data *rdata, char *geoloc_uri, char **pidf_body, unsigned int *pidf_len)
static struct ast_sip_session_supplement geolocation_supplement
static int load_module(void)
static int unload_module(void)
#define ast_sip_session_register_supplement(supplement)
void ast_sip_session_unregister_supplement(struct ast_sip_session_supplement *supplement)
Unregister a an supplement to SIP session processing.
const char * ast_sip_session_get_name(const struct ast_sip_session *session)
Get the channel or endpoint name associated with the session.
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one.
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true"....
static force_inline int attribute_pure ast_strlen_zero(const char *s)
void ast_str_reset(struct ast_str *buf)
Reset the content of a dynamic string. Useful before a series of ast_str_append.
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
static int force_inline attribute_pure ast_begins_with(const char *str, const char *prefix)
Checks whether a string begins with another.
char * ast_generate_random_string(char *buf, size_t size)
Create a pseudo-random string of a fixed length.
char * ast_strsep(char **s, const char sep, uint32_t flags)
Act like strsep but ignore separators inside quotes.
Main Channel structure associated with a channel.
Structure for a data store object.
struct ast_variable * effective_location
enum ast_geoloc_format format
const ast_string_field id
An entity with which Asterisk communicates.
A supplement to SIP message processing.
A structure describing a SIP session.
Support for dynamic strings.
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Asterisk XML abstraction layer.
void ast_xml_close(struct ast_xml_doc *doc)
Close an already open document and free the used structure.
struct ast_xml_doc * ast_xml_read_memory(char *buffer, size_t size)
Open an XML document that resides in memory.