[asterisk-commits] res pjsip: Move URI validation to use time. (asterisk[certified/13.1])

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Fri Oct 23 06:48:55 CDT 2015


Joshua Colp has submitted this change and it was merged.

Change subject: res_pjsip: Move URI validation to use time.
......................................................................


res_pjsip: Move URI validation to use time.

In a realtime based system with a limited number of threadpool threads
it is possible for a deadlock to occur. This happens when permanent
endpoint state is updated, which will cause database queries to be done.
These queries may result in URI validation being done which is done
synchronously using a PJSIP thread. If all PJSIP threads are in use
processing traffic they themselves may be blocked waiting to get the
permanent endpoint container lock when identifying an endpoint.

This change moves URI validation to occur at use time instead of
configuration time. While this comes at a cost of not seeing a problem
until you use it it does solve the underlying deadlock problem.

ASTERISK-25486 #close

Change-Id: I2d7d167af987d23b3e8199e4a68f3359eba4c76a
---
M include/asterisk/res_pjsip.h
M res/res_pjsip.c
M res/res_pjsip/location.c
M res/res_pjsip/pjsip_configuration.c
4 files changed, 22 insertions(+), 63 deletions(-)

Approvals:
  Kevin Harwell: Looks good to me, but someone else must approve
  Anonymous Coward #1000019: Verified
  Matt Jordan: Looks good to me, but someone else must approve
  Joshua Colp: Looks good to me, approved



diff --git a/include/asterisk/res_pjsip.h b/include/asterisk/res_pjsip.h
index 9760dad..af11ea4 100644
--- a/include/asterisk/res_pjsip.h
+++ b/include/asterisk/res_pjsip.h
@@ -1221,6 +1221,11 @@
  * cause a deadlock. If you are in a SIP servant thread, just call your function
  * in-line.
  *
+ * \warning \b Never hold locks that may be acquired by a SIP servant thread when
+ * calling this function. Doing so may cause a deadlock if all SIP servant threads
+ * are blocked waiting to acquire the lock while the thread holding the lock is
+ * waiting for a free SIP servant thread.
+ *
  * \param serializer The SIP serializer to which the task belongs. May be NULL.
  * \param sip_task The task to execute
  * \param task_data The parameter to pass to the task when it executes
diff --git a/res/res_pjsip.c b/res/res_pjsip.c
index 10e0163..83475a8 100644
--- a/res/res_pjsip.c
+++ b/res/res_pjsip.c
@@ -2406,6 +2406,8 @@
 
 		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;
@@ -2562,6 +2564,7 @@
 	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))) {
@@ -2598,6 +2601,16 @@
 		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",
@@ -2622,8 +2635,9 @@
 	/* 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 05c6ff7..29f186c 100644
--- a/res/res_pjsip/location.c
+++ b/res/res_pjsip/location.c
@@ -236,32 +236,6 @@
 	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;
@@ -308,12 +282,6 @@
 	while ((contact_uri = strsep(&contacts, ","))) {
 		struct ast_sip_contact *contact;
 		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,
diff --git a/res/res_pjsip/pjsip_configuration.c b/res/res_pjsip/pjsip_configuration.c
index 2cf1a7c..866bfaa 100644
--- a/res/res_pjsip/pjsip_configuration.c
+++ b/res/res_pjsip/pjsip_configuration.c
@@ -922,29 +922,6 @@
 	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)
 {
@@ -954,12 +931,7 @@
 		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;

-- 
To view, visit https://gerrit.asterisk.org/1471
To unsubscribe, visit https://gerrit.asterisk.org/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: I2d7d167af987d23b3e8199e4a68f3359eba4c76a
Gerrit-PatchSet: 1
Gerrit-Project: asterisk
Gerrit-Branch: certified/13.1
Gerrit-Owner: Joshua Colp <jcolp at digium.com>
Gerrit-Reviewer: Anonymous Coward #1000019
Gerrit-Reviewer: Joshua Colp <jcolp at digium.com>
Gerrit-Reviewer: Kevin Harwell <kharwell at digium.com>
Gerrit-Reviewer: Matt Jordan <mjordan at digium.com>



More information about the asterisk-commits mailing list