summaryrefslogtreecommitdiff
path: root/res
diff options
context:
space:
mode:
Diffstat (limited to 'res')
-rw-r--r--res/res_pjsip.c18
-rw-r--r--res/res_pjsip/location.c32
-rw-r--r--res/res_pjsip/pjsip_configuration.c30
-rw-r--r--res/res_pjsip_outbound_registration.c29
4 files changed, 46 insertions, 63 deletions
diff --git a/res/res_pjsip.c b/res/res_pjsip.c
index 5fc59909f..cdaed4ee7 100644
--- a/res/res_pjsip.c
+++ b/res/res_pjsip.c
@@ -2559,6 +2559,8 @@ pjsip_dialog *ast_sip_create_dialog_uac(const struct ast_sip_endpoint *endpoint,
pj_strdup2_with_null(dlg->pool, &tmp, outbound_proxy);
if (!(route = pjsip_parse_hdr(dlg->pool, &ROUTE_HNAME, tmp.ptr, tmp.slen, NULL))) {
+ ast_log(LOG_ERROR, "Could not create dialog to endpoint '%s' as outbound proxy URI '%s' is not valid\n",
+ ast_sorcery_object_get_id(endpoint), outbound_proxy);
dlg->sess_count--;
pjsip_dlg_terminate(dlg);
return NULL;
@@ -2752,6 +2754,7 @@ static int create_out_of_dialog_request(const pjsip_method *method, struct ast_s
pj_str_t from;
pj_pool_t *pool;
pjsip_tpselector selector = { .type = PJSIP_TPSELECTOR_NONE, };
+ pjsip_uri *sip_uri;
if (ast_strlen_zero(uri)) {
if (!endpoint && (!contact || ast_strlen_zero(contact->uri))) {
@@ -2788,6 +2791,16 @@ static int create_out_of_dialog_request(const pjsip_method *method, struct ast_s
return -1;
}
+ sip_uri = pjsip_parse_uri(pool, remote_uri.ptr, remote_uri.slen, 0);
+ if (!sip_uri || (!PJSIP_URI_SCHEME_IS_SIP(sip_uri) && !PJSIP_URI_SCHEME_IS_SIPS(sip_uri))) {
+ ast_log(LOG_ERROR, "Unable to create outbound %.*s request to endpoint %s as URI '%s' is not valid\n",
+ (int) pj_strlen(&method->name), pj_strbuf(&method->name),
+ endpoint ? ast_sorcery_object_get_id(endpoint) : "<none>",
+ pj_strbuf(&remote_uri));
+ pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
+ return -1;
+ }
+
if (sip_dialog_create_from(pool, &from, endpoint ? endpoint->fromuser : NULL,
endpoint ? endpoint->fromdomain : NULL, &remote_uri, &selector)) {
ast_log(LOG_ERROR, "Unable to create From header for %.*s request to endpoint %s\n",
@@ -2812,8 +2825,9 @@ static int create_out_of_dialog_request(const pjsip_method *method, struct ast_s
/* If an outbound proxy is specified on the endpoint apply it to this request */
if (endpoint && !ast_strlen_zero(endpoint->outbound_proxy) &&
ast_sip_set_outbound_proxy((*tdata), endpoint->outbound_proxy)) {
- ast_log(LOG_ERROR, "Unable to apply outbound proxy on request %.*s to endpoint %s\n",
- (int) pj_strlen(&method->name), pj_strbuf(&method->name), ast_sorcery_object_get_id(endpoint));
+ ast_log(LOG_ERROR, "Unable to apply outbound proxy on request %.*s to endpoint %s as outbound proxy URI '%s' is not valid\n",
+ (int) pj_strlen(&method->name), pj_strbuf(&method->name), ast_sorcery_object_get_id(endpoint),
+ endpoint->outbound_proxy);
pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
return -1;
}
diff --git a/res/res_pjsip/location.c b/res/res_pjsip/location.c
index 9625f04ef..331d839a1 100644
--- a/res/res_pjsip/location.c
+++ b/res/res_pjsip/location.c
@@ -319,32 +319,6 @@ static int expiration_struct2str(const void *obj, const intptr_t *args, char **b
return (ast_asprintf(buf, "%ld", contact->expiration_time.tv_sec) < 0) ? -1 : 0;
}
-/*! \brief Helper function which validates a permanent contact */
-static int permanent_contact_validate(void *data)
-{
- const char *value = data;
- pj_pool_t *pool;
- pj_str_t contact_uri;
- static const pj_str_t HCONTACT = { "Contact", 7 };
- pjsip_contact_hdr *contact_hdr;
- int rc = 0;
-
- pool = pjsip_endpt_create_pool(ast_sip_get_pjsip_endpoint(), "Permanent Contact Validation", 256, 256);
- if (!pool) {
- return -1;
- }
-
- pj_strdup2_with_null(pool, &contact_uri, value);
- if (!(contact_hdr = pjsip_parse_hdr(pool, &HCONTACT, contact_uri.ptr, contact_uri.slen, NULL))
- || !(PJSIP_URI_SCHEME_IS_SIP(contact_hdr->uri)
- || PJSIP_URI_SCHEME_IS_SIPS(contact_hdr->uri))) {
- rc = -1;
- }
-
- pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
- return rc;
-}
-
static int permanent_uri_sort_fn(const void *obj_left, const void *obj_right, int flags)
{
const struct ast_sip_contact *object_left = obj_left;
@@ -393,12 +367,6 @@ static int permanent_uri_handler(const struct aco_option *opt, struct ast_variab
struct ast_sip_contact_status *status;
char contact_id[strlen(aor_id) + strlen(contact_uri) + 2 + 1];
- if (ast_sip_push_task_synchronous(NULL, permanent_contact_validate, contact_uri)) {
- ast_log(LOG_ERROR, "Permanent URI on aor '%s' with contact '%s' failed to parse\n",
- ast_sorcery_object_get_id(aor), contact_uri);
- return -1;
- }
-
if (!aor->permanent_contacts) {
aor->permanent_contacts = ao2_container_alloc_list(AO2_ALLOC_OPT_LOCK_NOLOCK,
AO2_CONTAINER_ALLOC_OPT_DUPS_REJECT, permanent_uri_sort_fn, NULL);
diff --git a/res/res_pjsip/pjsip_configuration.c b/res/res_pjsip/pjsip_configuration.c
index cfb17cd8d..57793c903 100644
--- a/res/res_pjsip/pjsip_configuration.c
+++ b/res/res_pjsip/pjsip_configuration.c
@@ -1084,29 +1084,6 @@ static struct ast_endpoint *persistent_endpoint_find_or_create(const struct ast_
return persistent->endpoint;
}
-/*! \brief Helper function which validates an outbound proxy */
-static int outbound_proxy_validate(void *data)
-{
- const char *proxy = data;
- pj_pool_t *pool;
- pj_str_t tmp;
- static const pj_str_t ROUTE_HNAME = { "Route", 5 };
-
- pool = pjsip_endpt_create_pool(ast_sip_get_pjsip_endpoint(), "Outbound Proxy Validation", 256, 256);
- if (!pool) {
- return -1;
- }
-
- pj_strdup2_with_null(pool, &tmp, proxy);
- if (!pjsip_parse_hdr(pool, &ROUTE_HNAME, tmp.ptr, tmp.slen, NULL)) {
- pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
- return -1;
- }
-
- pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
- return 0;
-}
-
/*! \brief Callback function for when an object is finalized */
static int sip_endpoint_apply_handler(const struct ast_sorcery *sorcery, void *obj)
{
@@ -1116,12 +1093,7 @@ static int sip_endpoint_apply_handler(const struct ast_sorcery *sorcery, void *o
return -1;
}
- if (!ast_strlen_zero(endpoint->outbound_proxy) &&
- ast_sip_push_task_synchronous(NULL, outbound_proxy_validate, (char*)endpoint->outbound_proxy)) {
- ast_log(LOG_ERROR, "Invalid outbound proxy '%s' specified on endpoint '%s'\n",
- endpoint->outbound_proxy, ast_sorcery_object_get_id(endpoint));
- return -1;
- } else if (endpoint->extensions.timer.min_se < 90) {
+ if (endpoint->extensions.timer.min_se < 90) {
ast_log(LOG_ERROR, "Session timer minimum expires time must be 90 or greater on endpoint '%s'\n",
ast_sorcery_object_get_id(endpoint));
return -1;
diff --git a/res/res_pjsip_outbound_registration.c b/res/res_pjsip_outbound_registration.c
index 6bdba5624..038cc0b20 100644
--- a/res/res_pjsip_outbound_registration.c
+++ b/res/res_pjsip_outbound_registration.c
@@ -100,6 +100,21 @@
buggy registrars.
</para></description>
</configOption>
+ <configOption name="fatal_retry_interval" default="0">
+ <synopsis>Interval used when receiving a Fatal response.</synopsis>
+ <description><para>
+ If a fatal response is received, chan_pjsip will wait
+ <replaceable>fatal_retry_interval</replaceable> seconds before
+ attempting registration again. If 0 is specified, chan_pjsip will not
+ retry after receiving a fatal (non-temporary 4xx, 5xx, 6xx) response.
+ Setting this to a non-zero value may go against a "SHOULD NOT" in RFC3261,
+ but can be used to work around buggy registrars.</para>
+ <note><para>if also set the <replaceable>forbidden_retry_interval</replaceable>
+ takes precedence over this one when a 403 is received.
+ Also, if <replaceable>auth_rejection_permanent</replaceable> equals 'yes' then
+ a 401 and 407 become subject to this retry interval.</para></note>
+ </description>
+ </configOption>
<configOption name="server_uri">
<synopsis>SIP URI of the server to register against</synopsis>
<description><para>
@@ -277,6 +292,8 @@ struct sip_outbound_registration {
unsigned int retry_interval;
/*! \brief Interval at which retries should occur for permanent responses */
unsigned int forbidden_retry_interval;
+ /*! \brief Interval at which retries should occur for all permanent responses */
+ unsigned int fatal_retry_interval;
/*! \brief Treat authentication challenges that we cannot handle as permanent failures */
unsigned int auth_rejection_permanent;
/*! \brief Maximum number of retries permitted */
@@ -312,6 +329,8 @@ struct sip_outbound_registration_client_state {
unsigned int retry_interval;
/*! \brief Interval at which retries should occur for permanent responses */
unsigned int forbidden_retry_interval;
+ /*! \brief Interval at which retries should occur for all permanent responses */
+ unsigned int fatal_retry_interval;
/*! \brief Treat authentication challenges that we cannot handle as permanent failures */
unsigned int auth_rejection_permanent;
/*! \brief Determines whether SIP Path support should be advertised */
@@ -799,6 +818,14 @@ static int handle_registration_response(void *data)
schedule_registration(response->client_state, response->client_state->forbidden_retry_interval);
ast_log(LOG_WARNING, "403 Forbidden fatal response received from '%s' on registration attempt to '%s', retrying in '%u' seconds\n",
server_uri, client_uri, response->client_state->forbidden_retry_interval);
+ } else if (response->client_state->fatal_retry_interval
+ && response->client_state->retries < response->client_state->max_retries) {
+ /* Some kind of fatal failure response received, so retry according to configured interval */
+ response->client_state->status = SIP_REGISTRATION_REJECTED_TEMPORARY;
+ response->client_state->retries++;
+ schedule_registration(response->client_state, response->client_state->fatal_retry_interval);
+ ast_log(LOG_WARNING, "'%d' fatal response received from '%s' on registration attempt to '%s', retrying in '%u' seconds\n",
+ response->code, server_uri, client_uri, response->client_state->fatal_retry_interval);
} else {
/* Finally if there's no hope of registering give up */
response->client_state->status = SIP_REGISTRATION_REJECTED_PERMANENT;
@@ -1186,6 +1213,7 @@ static int sip_outbound_registration_perform(void *data)
}
state->client_state->retry_interval = registration->retry_interval;
state->client_state->forbidden_retry_interval = registration->forbidden_retry_interval;
+ state->client_state->fatal_retry_interval = registration->fatal_retry_interval;
state->client_state->max_retries = registration->max_retries;
state->client_state->retries = 0;
state->client_state->support_path = registration->support_path;
@@ -1909,6 +1937,7 @@ static int load_module(void)
ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "expiration", "3600", OPT_UINT_T, 0, FLDSET(struct sip_outbound_registration, expiration));
ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "retry_interval", "60", OPT_UINT_T, 0, FLDSET(struct sip_outbound_registration, retry_interval));
ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "forbidden_retry_interval", "0", OPT_UINT_T, 0, FLDSET(struct sip_outbound_registration, forbidden_retry_interval));
+ ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "fatal_retry_interval", "0", OPT_UINT_T, 0, FLDSET(struct sip_outbound_registration, fatal_retry_interval));
ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "max_retries", "10", OPT_UINT_T, 0, FLDSET(struct sip_outbound_registration, max_retries));
ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "auth_rejection_permanent", "yes", OPT_BOOL_T, 1, FLDSET(struct sip_outbound_registration, auth_rejection_permanent));
ast_sorcery_object_field_register_custom(ast_sip_get_sorcery(), "registration", "outbound_auth", "", outbound_auth_handler, outbound_auths_to_str, outbound_auths_to_var_list, 0, 0);