diff options
author | zuul <zuul@gerrit.asterisk.org> | 2016-09-14 12:54:24 -0500 |
---|---|---|
committer | Gerrit Code Review <gerrit2@gerrit.digium.api> | 2016-09-14 12:54:24 -0500 |
commit | a5f7b07579093c22e5b2397451b46c5073d09810 (patch) | |
tree | c5fa80d7589604be6455c6e64388764bd4cfff6b /res | |
parent | efba4a7b9cc19ca10b11057da8dd4793355088a3 (diff) | |
parent | 30af92e78d36523f8012da5eb9aee16687d8fe61 (diff) |
Merge "res_pjsip: Add ignore_uri_user_options option." into 13
Diffstat (limited to 'res')
-rw-r--r-- | res/res_pjsip.c | 24 | ||||
-rw-r--r-- | res/res_pjsip/config_global.c | 20 | ||||
-rw-r--r-- | res/res_pjsip/pjsip_options.c | 12 | ||||
-rw-r--r-- | res/res_pjsip_caller_id.c | 18 | ||||
-rw-r--r-- | res/res_pjsip_diversion.c | 25 | ||||
-rw-r--r-- | res/res_pjsip_endpoint_identifier_user.c | 12 | ||||
-rw-r--r-- | res/res_pjsip_messaging.c | 25 | ||||
-rw-r--r-- | res/res_pjsip_path.c | 22 | ||||
-rw-r--r-- | res/res_pjsip_pubsub.c | 18 | ||||
-rw-r--r-- | res/res_pjsip_refer.c | 7 | ||||
-rw-r--r-- | res/res_pjsip_registrar.c | 6 | ||||
-rw-r--r-- | res/res_pjsip_session.c | 13 |
12 files changed, 185 insertions, 17 deletions
diff --git a/res/res_pjsip.c b/res/res_pjsip.c index 96c07d501..039495d55 100644 --- a/res/res_pjsip.c +++ b/res/res_pjsip.c @@ -1544,6 +1544,30 @@ </para> </description> </configOption> + <configOption name="ignore_uri_user_options"> + <synopsis>Enable/Disable ignoring SIP URI user field options.</synopsis> + <description> + <para>If you have this option enabled and there are semicolons + in the user field of a SIP URI then the field is truncated + at the first semicolon. This effectively makes the semicolon + a non-usable character for PJSIP endpoint names, extensions, + and AORs. This can be useful for improving compatability with + an ITSP that likes to use user options for whatever reason. + </para> + <example title="Sample SIP URI"> + sip:1235557890;phone-context=national@x.x.x.x;user=phone + </example> + <example title="Sample SIP URI user field"> + 1235557890;phone-context=national + </example> + <example title="Sample SIP URI user field truncated"> + 1235557890 + </example> + <note><para>The caller-id and redirecting number strings + obtained from incoming SIP URI user fields are always truncated + at the first semicolon.</para></note> + </description> + </configOption> </configObject> </configFile> </configInfo> diff --git a/res/res_pjsip/config_global.c b/res/res_pjsip/config_global.c index 281630ae4..fc1227d25 100644 --- a/res/res_pjsip/config_global.c +++ b/res/res_pjsip/config_global.c @@ -47,6 +47,7 @@ #define DEFAULT_MWI_TPS_QUEUE_HIGH AST_TASKPROCESSOR_HIGH_WATER_LEVEL #define DEFAULT_MWI_TPS_QUEUE_LOW -1 #define DEFAULT_MWI_DISABLE_INITIAL_UNSOLICITED 0 +#define DEFAULT_IGNORE_URI_USER_OPTIONS 0 /*! * \brief Cached global config object @@ -100,6 +101,8 @@ struct global_config { /*! Nonzero to disable sending unsolicited mwi to all endpoints on startup */ unsigned int disable_initial_unsolicited; } mwi; + /*! Nonzero if URI user field options are ignored. */ + unsigned int ignore_uri_user_options; }; static void global_destructor(void *obj) @@ -384,6 +387,20 @@ unsigned int ast_sip_get_mwi_disable_initial_unsolicited(void) return disable_initial_unsolicited; } +unsigned int ast_sip_get_ignore_uri_user_options(void) +{ + unsigned int ignore_uri_user_options; + struct global_config *cfg; + + cfg = get_global_cfg(); + if (!cfg) { + return DEFAULT_IGNORE_URI_USER_OPTIONS; + } + + ignore_uri_user_options = cfg->ignore_uri_user_options; + ao2_ref(cfg, -1); + return ignore_uri_user_options; +} /*! * \internal @@ -533,6 +550,9 @@ int ast_sip_initialize_sorcery_global(void) ast_sorcery_object_field_register(sorcery, "global", "mwi_disable_initial_unsolicited", DEFAULT_MWI_DISABLE_INITIAL_UNSOLICITED ? "yes" : "no", OPT_BOOL_T, 1, FLDSET(struct global_config, mwi.disable_initial_unsolicited)); + ast_sorcery_object_field_register(sorcery, "global", "ignore_uri_user_options", + DEFAULT_IGNORE_URI_USER_OPTIONS ? "yes" : "no", + OPT_BOOL_T, 1, FLDSET(struct global_config, ignore_uri_user_options)); if (ast_sorcery_instance_observer_add(sorcery, &observer_callbacks_global)) { return -1; diff --git a/res/res_pjsip/pjsip_options.c b/res/res_pjsip/pjsip_options.c index d87188363..8c8836fd9 100644 --- a/res/res_pjsip/pjsip_options.c +++ b/res/res_pjsip/pjsip_options.c @@ -760,8 +760,7 @@ static pj_bool_t options_on_rx_request(pjsip_rx_data *rdata) pjsip_sip_uri *sip_ruri; char exten[AST_MAX_EXTENSION]; - if (pjsip_method_cmp(&rdata->msg_info.msg->line.req.method, - &pjsip_options_method)) { + if (pjsip_method_cmp(&rdata->msg_info.msg->line.req.method, &pjsip_options_method)) { return PJ_FALSE; } @@ -778,13 +777,20 @@ static pj_bool_t options_on_rx_request(pjsip_rx_data *rdata) sip_ruri = pjsip_uri_get_uri(ruri); ast_copy_pj_str(exten, &sip_ruri->user, sizeof(exten)); + /* + * We may want to match in the dialplan without any user + * options getting in the way. + */ + AST_SIP_USER_OPTIONS_TRUNCATE_CHECK(exten); + if (ast_shutting_down()) { /* * Not taking any new calls at this time. * Likely a server availability OPTIONS poll. */ send_options_response(rdata, 503); - } else if (!ast_strlen_zero(exten) && !ast_exists_extension(NULL, endpoint->context, exten, 1, NULL)) { + } else if (!ast_strlen_zero(exten) + && !ast_exists_extension(NULL, endpoint->context, exten, 1, NULL)) { send_options_response(rdata, 404); } else { send_options_response(rdata, 200); diff --git a/res/res_pjsip_caller_id.c b/res/res_pjsip_caller_id.c index 4d9f09237..c3aa338ae 100644 --- a/res/res_pjsip_caller_id.c +++ b/res/res_pjsip_caller_id.c @@ -46,11 +46,29 @@ static void set_id_from_hdr(pjsip_fromto_hdr *hdr, struct ast_party_id *id) char cid_num[AST_CHANNEL_NAME]; pjsip_sip_uri *uri; pjsip_name_addr *id_name_addr = (pjsip_name_addr *) hdr->uri; + char *semi; uri = pjsip_uri_get_uri(id_name_addr); ast_copy_pj_str(cid_name, &id_name_addr->display, sizeof(cid_name)); ast_copy_pj_str(cid_num, &uri->user, sizeof(cid_num)); + /* Always truncate caller-id number at a semicolon. */ + semi = strchr(cid_num, ';'); + if (semi) { + /* + * We need to be able to handle URI's looking like + * "sip:1235557890;phone-context=national@x.x.x.x;user=phone" + * + * Where the uri->user field will result in: + * "1235557890;phone-context=national" + * + * People don't care about anything after the semicolon + * showing up on their displays even though the RFC + * allows the semicolon. + */ + *semi = '\0'; + } + ast_free(id->name.str); id->name.str = ast_strdup(cid_name); if (!ast_strlen_zero(cid_name)) { diff --git a/res/res_pjsip_diversion.c b/res/res_pjsip_diversion.c index 99d18da44..b9225de9c 100644 --- a/res/res_pjsip_diversion.c +++ b/res/res_pjsip_diversion.c @@ -148,11 +148,32 @@ static void set_redirecting_id(pjsip_name_addr *name_addr, struct ast_party_id * struct ast_set_party_id *update) { pjsip_sip_uri *uri = pjsip_uri_get_uri(name_addr->uri); + char *semi; + pj_str_t uri_user; + + uri_user = uri->user; + + /* Always truncate redirecting number at a semicolon. */ + semi = pj_strchr(&uri_user, ';'); + if (semi) { + /* + * We need to be able to handle URI's looking like + * "sip:1235557890;phone-context=national@x.x.x.x;user=phone" + * + * Where the uri->user field will result in: + * "1235557890;phone-context=national" + * + * People don't care about anything after the semicolon + * showing up on their displays even though the RFC + * allows the semicolon. + */ + pj_strset(&uri_user, (char *) pj_strbuf(&uri_user), semi - pj_strbuf(&uri_user)); + } - if (pj_strlen(&uri->user)) { + if (pj_strlen(&uri_user)) { update->number = 1; data->number.valid = 1; - set_redirecting_value(&data->number.str, &uri->user); + set_redirecting_value(&data->number.str, &uri_user); } if (pj_strlen(&name_addr->display)) { diff --git a/res/res_pjsip_endpoint_identifier_user.c b/res/res_pjsip_endpoint_identifier_user.c index e018abd61..30da062ed 100644 --- a/res/res_pjsip_endpoint_identifier_user.c +++ b/res/res_pjsip_endpoint_identifier_user.c @@ -33,6 +33,7 @@ static int get_from_header(pjsip_rx_data *rdata, char *username, size_t username { pjsip_uri *from = rdata->msg_info.from->uri; pjsip_sip_uri *sip_from; + if (!PJSIP_URI_SCHEME_IS_SIP(from) && !PJSIP_URI_SCHEME_IS_SIPS(from)) { return -1; } @@ -115,18 +116,25 @@ static struct ast_sip_endpoint *find_endpoint(pjsip_rx_data *rdata, char *endpoi static struct ast_sip_endpoint *username_identify(pjsip_rx_data *rdata) { - char username[64], domain[64]; + char username[64]; + char domain[64]; struct ast_sip_endpoint *endpoint; if (get_from_header(rdata, username, sizeof(username), domain, sizeof(domain))) { return NULL; } + + /* + * We may want to be matched without any user options getting + * in the way. + */ + AST_SIP_USER_OPTIONS_TRUNCATE_CHECK(username); + ast_debug(3, "Attempting identify by From username '%s' domain '%s'\n", username, domain); endpoint = find_endpoint(rdata, username, domain); if (!endpoint) { ast_debug(3, "Endpoint not found for From username '%s' domain '%s'\n", username, domain); - ao2_cleanup(endpoint); return NULL; } if (!(endpoint->ident_method & AST_SIP_ENDPOINT_IDENTIFY_BY_USERNAME)) { diff --git a/res/res_pjsip_messaging.c b/res/res_pjsip_messaging.c index a3cc8afcf..835a38393 100644 --- a/res/res_pjsip_messaging.c +++ b/res/res_pjsip_messaging.c @@ -132,6 +132,12 @@ static struct ast_sip_endpoint *get_outbound_endpoint(const char *to, char **uri } else if ((aor_uri = strchr(name, '@'))) { /* format was 'endpoint@domain' - discard the domain */ *aor_uri = '\0'; + + /* + * We may want to match without any user options getting + * in the way. + */ + AST_SIP_USER_OPTIONS_TRUNCATE_CHECK(name); } /* at this point, if name is not empty then it @@ -467,6 +473,12 @@ static enum pjsip_status_code rx_data_to_ast_msg(pjsip_rx_data *rdata, struct as sip_ruri = pjsip_uri_get_uri(ruri); ast_copy_pj_str(exten, &sip_ruri->user, AST_MAX_EXTENSION); + /* + * We may want to match in the dialplan without any user + * options getting in the way. + */ + AST_SIP_USER_OPTIONS_TRUNCATE_CHECK(exten); + endpt = ast_pjsip_rdata_get_endpoint(rdata); ast_assert(endpt != NULL); @@ -547,7 +559,7 @@ static void msg_data_destroy(void *obj) static struct msg_data *msg_data_create(const struct ast_msg *msg, const char *to, const char *from) { - char *tag; + char *uri_params; struct msg_data *mdata = ao2_alloc(sizeof(*mdata), msg_data_destroy); if (!mdata) { @@ -572,9 +584,14 @@ static struct msg_data *msg_data_create(const struct ast_msg *msg, const char *t return NULL; } - /* sometimes from can still contain the tag at this point, so remove it */ - if ((tag = strchr(mdata->from, ';'))) { - *tag = '\0'; + /* + * Sometimes from URI can contain URI parameters, so remove them. + * + * sip:user;user-options@domain;uri-parameters + */ + uri_params = strchr(mdata->from, '@'); + if (uri_params && (uri_params = strchr(mdata->from, ';'))) { + *uri_params = '\0'; } return mdata; } diff --git a/res/res_pjsip_path.c b/res/res_pjsip_path.c index 47d6a7906..20c9d4366 100644 --- a/res/res_pjsip_path.c +++ b/res/res_pjsip_path.c @@ -40,7 +40,8 @@ static struct ast_sip_aor *find_aor(struct ast_sip_endpoint *endpoint, pjsip_uri char *configured_aors, *aor_name; pjsip_sip_uri *sip_uri; char *domain_name; - RAII_VAR(struct ast_str *, id, NULL, ast_free); + char *username; + struct ast_str *id = NULL; if (ast_strlen_zero(endpoint->aors)) { return NULL; @@ -49,6 +50,14 @@ static struct ast_sip_aor *find_aor(struct ast_sip_endpoint *endpoint, pjsip_uri sip_uri = pjsip_uri_get_uri(uri); domain_name = ast_alloca(sip_uri->host.slen + 1); ast_copy_pj_str(domain_name, &sip_uri->host, sip_uri->host.slen + 1); + username = ast_alloca(sip_uri->user.slen + 1); + ast_copy_pj_str(username, &sip_uri->user, sip_uri->user.slen + 1); + + /* + * We may want to match without any user options getting + * in the way. + */ + AST_SIP_USER_OPTIONS_TRUNCATE_CHECK(username); configured_aors = ast_strdupa(endpoint->aors); @@ -60,15 +69,16 @@ static struct ast_sip_aor *find_aor(struct ast_sip_endpoint *endpoint, pjsip_uri continue; } - if (!pj_strcmp2(&sip_uri->user, aor_name)) { + if (!strcmp(username, aor_name)) { break; } - if (!id && !(id = ast_str_create(sip_uri->user.slen + sip_uri->host.slen + 2))) { - return NULL; + if (!id && !(id = ast_str_create(strlen(username) + sip_uri->host.slen + 2))) { + aor_name = NULL; + break; } - ast_str_set(&id, 0, "%.*s@", (int)sip_uri->user.slen, sip_uri->user.ptr); + ast_str_set(&id, 0, "%s@", username); if ((alias = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "domain_alias", domain_name))) { ast_str_append(&id, 0, "%s", alias->domain); ao2_cleanup(alias); @@ -77,10 +87,10 @@ static struct ast_sip_aor *find_aor(struct ast_sip_endpoint *endpoint, pjsip_uri } if (!strcmp(aor_name, ast_str_buffer(id))) { - ast_free(id); break; } } + ast_free(id); if (ast_strlen_zero(aor_name)) { return NULL; diff --git a/res/res_pjsip_pubsub.c b/res/res_pjsip_pubsub.c index 3ac3f342f..2fa7f34e3 100644 --- a/res/res_pjsip_pubsub.c +++ b/res/res_pjsip_pubsub.c @@ -1400,6 +1400,12 @@ static int sub_persistence_recreate(void *obj) resource = ast_alloca(resource_size); ast_copy_pj_str(resource, &request_uri->user, resource_size); + /* + * We may want to match without any user options getting + * in the way. + */ + AST_SIP_USER_OPTIONS_TRUNCATE_CHECK(resource); + handler = subscription_get_handler_from_rdata(rdata); if (!handler || !handler->notifier) { ast_log(LOG_WARNING, "Failed recreating '%s' subscription: Could not get subscription handler.\n", @@ -2815,6 +2821,12 @@ static pj_bool_t pubsub_on_rx_subscribe_request(pjsip_rx_data *rdata) resource = ast_alloca(resource_size); ast_copy_pj_str(resource, &request_uri_sip->user, resource_size); + /* + * We may want to match without any user options getting + * in the way. + */ + AST_SIP_USER_OPTIONS_TRUNCATE_CHECK(resource); + expires_header = pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_EXPIRES, rdata->msg_info.msg->hdr.next); if (expires_header) { @@ -3028,6 +3040,12 @@ static struct ast_sip_publication *publish_request_initial(struct ast_sip_endpoi resource_name = ast_alloca(resource_size); ast_copy_pj_str(resource_name, &request_uri_sip->user, resource_size); + /* + * We may want to match without any user options getting + * in the way. + */ + AST_SIP_USER_OPTIONS_TRUNCATE_CHECK(resource_name); + resource = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "inbound-publication", resource_name); if (!resource) { ast_debug(1, "No 'inbound-publication' defined for resource '%s'\n", resource_name); diff --git a/res/res_pjsip_refer.c b/res/res_pjsip_refer.c index 8fe4e8477..99295d5f3 100644 --- a/res/res_pjsip_refer.c +++ b/res/res_pjsip_refer.c @@ -814,6 +814,13 @@ static int refer_incoming_blind_request(struct ast_sip_session *session, pjsip_r /* Using the user portion of the target URI see if it exists as a valid extension in their context */ ast_copy_pj_str(exten, &target->user, sizeof(exten)); + + /* + * We may want to match in the dialplan without any user + * options getting in the way. + */ + AST_SIP_USER_OPTIONS_TRUNCATE_CHECK(exten); + if (!ast_exists_extension(NULL, context, exten, 1, NULL)) { ast_log(LOG_ERROR, "Channel '%s' from endpoint '%s' attempted blind transfer to '%s@%s' but target does not exist\n", ast_channel_name(session->channel), ast_sorcery_object_get_id(session->endpoint), exten, context); diff --git a/res/res_pjsip_registrar.c b/res/res_pjsip_registrar.c index 1e0f5ab72..a13f8f86b 100644 --- a/res/res_pjsip_registrar.c +++ b/res/res_pjsip_registrar.c @@ -634,6 +634,12 @@ static struct ast_sip_aor *find_registrar_aor(struct pjsip_rx_data *rdata, struc username = ast_alloca(uri->user.slen + 1); ast_copy_pj_str(username, &uri->user, uri->user.slen + 1); + /* + * We may want to match without any user options getting + * in the way. + */ + AST_SIP_USER_OPTIONS_TRUNCATE_CHECK(username); + aor_name = find_aor_name(username, domain_name, endpoint->aors); if (aor_name) { ast_debug(3, "Matched aor '%s' by To username\n", aor_name); diff --git a/res/res_pjsip_session.c b/res/res_pjsip_session.c index 050970998..8b8e9d114 100644 --- a/res/res_pjsip_session.c +++ b/res/res_pjsip_session.c @@ -1980,6 +1980,12 @@ static enum sip_get_destination_result get_destination(struct ast_sip_session *s sip_ruri = pjsip_uri_get_uri(ruri); ast_copy_pj_str(session->exten, &sip_ruri->user, sizeof(session->exten)); + /* + * We may want to match in the dialplan without any user + * options getting in the way. + */ + AST_SIP_USER_OPTIONS_TRUNCATE_CHECK(session->exten); + pickup_cfg = ast_get_chan_features_pickup_config(session->channel); if (!pickup_cfg) { ast_log(LOG_ERROR, "Unable to retrieve pickup configuration options. Unable to detect call pickup extension\n"); @@ -3059,6 +3065,13 @@ static pjsip_redirect_op session_inv_on_redirected(pjsip_inv_session *inv, const char exten[AST_MAX_EXTENSION]; ast_copy_pj_str(exten, &uri->user, sizeof(exten)); + + /* + * We may want to match in the dialplan without any user + * options getting in the way. + */ + AST_SIP_USER_OPTIONS_TRUNCATE_CHECK(exten); + ast_channel_call_forward_set(session->channel, exten); } else if (session->endpoint->redirect_method == AST_SIP_REDIRECT_URI_CORE) { char target_uri[PJSIP_MAX_URL_SIZE]; |