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);
 
  609    ast_trace(4, 
"%s: Using URI '%s'\n", session_name, uri);
 
  614    if (geoloc_hdr == 
NULL) {
 
  616            tdata->msg->body = orig_body;
 
  623            tdata->msg->body = orig_body;
 
  625        pj_list_erase(geoloc_hdr);
 
 
  668    .
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_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.
struct ast_geoloc_profile *AST_OPTIONAL_API_NAME() ast_geoloc_get_profile(const char *id)
Retrieve a geolocation profile by id.
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.
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
#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.
char *attribute_pure ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
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.
struct ast_endpoint * endpoint
Structure for a data store object.
struct ast_variable * effective_location
enum ast_geoloc_format format
const ast_string_field id
const ast_string_field location_source
An entity with which Asterisk communicates.
A supplement to SIP message processing.
struct ast_module *const char * method
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.