[Asterisk-code-review] res pjsip registrar: blocked threads on reliable transport s... (asterisk[13])

Kevin Harwell asteriskteam at digium.com
Wed Feb 20 11:06:31 CST 2019


Kevin Harwell has uploaded this change for review. ( https://gerrit.asterisk.org/11014


Change subject: res_pjsip_registrar: blocked threads on reliable transport shutdown take 3
......................................................................

res_pjsip_registrar: blocked threads on reliable transport shutdown take 3

When a contact was removed by the registrar it did not always check to see if
the circumstances involved a monitored reliable transport. For instance, if the
'remove_existing' option was set to 'true' then when existing contacts were
removed due to 'max_contacts' being reached, those existing contacts being
removed did not unregister the transport monitor.

Also, it was possible to add more than one monitor on a reliable transport for
a given aor and contact.

This patch makes it so all contact removals done by the registrar also remove
any associated transport monitors if necessary. It also makes it so duplicate
monitors cannot be added for a given transport.

ASTERISK-28213

Change-Id: I94b06f9026ed177d6adfd538317c784a42c1b17a
---
M include/asterisk/res_pjsip.h
M res/res_pjsip/pjsip_transport_events.c
M res/res_pjsip_registrar.c
3 files changed, 127 insertions(+), 83 deletions(-)



  git pull ssh://gerrit.asterisk.org:29418/asterisk refs/changes/14/11014/1

diff --git a/include/asterisk/res_pjsip.h b/include/asterisk/res_pjsip.h
index 7854df7..84ff1c7 100644
--- a/include/asterisk/res_pjsip.h
+++ b/include/asterisk/res_pjsip.h
@@ -3169,6 +3169,27 @@
 	ast_transport_monitor_shutdown_cb cb, void *ao2_data);
 
 /*!
+ * \brief Register a reliable transport shutdown monitor callback replacing any duplicate.
+ *
+ * \param transport Transport to monitor for shutdown.
+ * \param cb Who to call when transport is shutdown.
+ * \param ao2_data Data to pass with the callback.
+ * \param matches Matcher function that returns true if data matches a previously
+ *                registered data object
+ *
+ * \note The data object passed will have its reference count automatically
+ * incremented by this call and automatically decremented after the callback
+ * runs or when the callback is unregistered.
+ *
+ * This function checks for duplicates, and overwrites/replaces the old monitor
+ * with the given one.
+ *
+ * \return enum ast_transport_monitor_reg
+ */
+enum ast_transport_monitor_reg ast_sip_transport_monitor_register_replace(pjsip_transport *transport,
+	ast_transport_monitor_shutdown_cb cb, void *ao2_data, ast_transport_monitor_data_matcher matches);
+
+/*!
  * \brief Unregister a reliable transport shutdown monitor
  * \since 13.20.0
  *
diff --git a/res/res_pjsip/pjsip_transport_events.c b/res/res_pjsip/pjsip_transport_events.c
index cc7b7c0..5eb9868 100644
--- a/res/res_pjsip/pjsip_transport_events.c
+++ b/res/res_pjsip/pjsip_transport_events.c
@@ -306,6 +306,12 @@
 enum ast_transport_monitor_reg ast_sip_transport_monitor_register(pjsip_transport *transport,
 	ast_transport_monitor_shutdown_cb cb, void *ao2_data)
 {
+	return ast_sip_transport_monitor_register_replace(transport, cb, ao2_data, NULL);
+}
+
+enum ast_transport_monitor_reg ast_sip_transport_monitor_register_replace(pjsip_transport *transport,
+	ast_transport_monitor_shutdown_cb cb, void *ao2_data, ast_transport_monitor_data_matcher matches)
+{
 	struct ao2_container *transports;
 	struct transport_monitor *monitored;
 	enum ast_transport_monitor_reg res = AST_TRANSPORT_MONITOR_REG_NOT_FOUND;
@@ -321,6 +327,13 @@
 	monitored = ao2_find(transports, transport->obj_name, OBJ_SEARCH_KEY | OBJ_NOLOCK);
 	if (monitored) {
 		struct transport_monitor_notifier new_monitor;
+		struct callback_data cb_data = {
+			.cb = cb,
+			.data = ao2_data,
+			.matches = matches ?: ptr_matcher,
+		};
+
+		transport_monitor_unregister_cb(monitored, &cb_data, 0);
 
 		/* Add new monitor to vector */
 		new_monitor.cb = cb;
diff --git a/res/res_pjsip_registrar.c b/res/res_pjsip_registrar.c
index ced5dca..cf488cb 100644
--- a/res/res_pjsip_registrar.c
+++ b/res/res_pjsip_registrar.c
@@ -197,30 +197,22 @@
 	return 0;
 }
 
+enum contact_delete_type {
+	CONTACT_DELETE_ERROR,
+	CONTACT_DELETE_EXISTING,
+	CONTACT_DELETE_EXPIRE,
+	CONTACT_DELETE_REQUEST,
+	CONTACT_DELETE_SHUTDOWN,
+};
+
+static int registrar_contact_delete(enum contact_delete_type type, pjsip_transport *transport,
+	struct ast_sip_contact *contact, const char *aor_name);
+
 /*! \brief Internal function used to delete a contact from an AOR */
 static int registrar_delete_contact(void *obj, void *arg, int flags)
 {
-	struct ast_sip_contact *contact = obj;
-	const char *aor_name = arg;
-
-	/* Permanent contacts can't be deleted */
-	if (ast_tvzero(contact->expiration_time)) {
-		return 0;
-	}
-
-	ast_sip_location_delete_contact(contact);
-	if (!ast_strlen_zero(aor_name)) {
-		ast_verb(3, "Removed contact '%s' from AOR '%s' due to request\n", contact->uri, aor_name);
-		ast_test_suite_event_notify("AOR_CONTACT_REMOVED",
-				"Contact: %s\r\n"
-				"AOR: %s\r\n"
-				"UserAgent: %s",
-				contact->uri,
-				aor_name,
-				contact->user_agent);
-	}
-
-	return CMP_MATCH;
+	return registrar_contact_delete(
+		CONTACT_DELETE_REQUEST, NULL, obj, arg) ? 0 : CMP_MATCH;
 }
 
 /*! \brief Internal function which adds a contact to a response */
@@ -352,16 +344,7 @@
 
 	contact = ast_sip_location_retrieve_contact(monitor->contact_name);
 	if (contact) {
-		ast_sip_location_delete_contact(contact);
-		ast_verb(3, "Removed contact '%s' from AOR '%s' due to transport shutdown\n",
-			contact->uri, monitor->aor_name);
-		ast_test_suite_event_notify("AOR_CONTACT_REMOVED",
-			"Contact: %s\r\n"
-			"AOR: %s\r\n"
-			"UserAgent: %s",
-			contact->uri,
-			monitor->aor_name,
-			contact->user_agent);
+		registrar_contact_delete(CONTACT_DELETE_SHUTDOWN, NULL, contact, monitor->aor_name);
 		ao2_ref(contact, -1);
 	}
 
@@ -415,6 +398,77 @@
 	ao2_unlock(monitor);
 }
 
+
+static int registrar_contact_delete(enum contact_delete_type type, pjsip_transport *transport,
+	struct ast_sip_contact *contact, const char *aor_name)
+{
+	int aor_size;
+
+	/* Permanent contacts can't be deleted */
+	if (ast_tvzero(contact->expiration_time)) {
+		return -1;
+	}
+
+	aor_size = aor_name ? strlen(aor_name) : 0;
+	if (contact->prune_on_boot && type != CONTACT_DELETE_SHUTDOWN && aor_size) {
+		const char *contact_name = ast_sorcery_object_get_id(contact);
+		struct contact_transport_monitor *monitor = ast_alloca(
+			sizeof(*monitor) + 2 + aor_size + strlen(contact_name));
+
+		strcpy(monitor->aor_name, aor_name); /* Safe */
+		monitor->contact_name = monitor->aor_name + aor_size + 1;
+		strcpy(monitor->contact_name, contact_name); /* Safe */
+
+		if (transport) {
+			ast_sip_transport_monitor_unregister(transport,
+				register_contact_transport_shutdown_cb,	monitor,
+				contact_transport_monitor_matcher);
+		} else {
+			ast_sip_transport_monitor_unregister_all(register_contact_transport_shutdown_cb,
+				monitor, contact_transport_monitor_matcher);
+		}
+	}
+
+	ast_sip_location_delete_contact(contact);
+
+	if (aor_size) {
+		if (VERBOSITY_ATLEAST(3)) {
+			const char *reason = "none";
+
+			switch (type) {
+			case CONTACT_DELETE_ERROR:
+				reason = "error";
+				break;
+			case CONTACT_DELETE_EXISTING:
+				reason = "remove existing";
+				break;
+			case CONTACT_DELETE_EXPIRE:
+				reason = "expiration";
+				break;
+			case CONTACT_DELETE_REQUEST:
+				reason = "request";
+				break;
+			case CONTACT_DELETE_SHUTDOWN:
+				reason = "shutdown";
+				break;
+			}
+
+			ast_verb(3, "Removed contact '%s' from AOR '%s' due to %s\n",
+					 contact->uri, aor_name, reason);
+		}
+
+		ast_test_suite_event_notify("AOR_CONTACT_REMOVED",
+				"Contact: %s\r\n"
+				"AOR: %s\r\n"
+				"UserAgent: %s",
+				contact->uri,
+				aor_name,
+				contact->user_agent);
+	}
+
+	return 0;
+}
+
 AST_VECTOR(excess_contact_vector, struct ast_sip_contact *);
 
 static int vec_contact_cmp(struct ast_sip_contact *left, struct ast_sip_contact *right)
@@ -491,16 +545,7 @@
 
 		contact = AST_VECTOR_GET(&contact_vec, to_remove);
 
-		ast_sip_location_delete_contact(contact);
-		ast_verb(3, "Removed contact '%s' from AOR '%s' due to remove_existing\n",
-			contact->uri, contact->aor);
-		ast_test_suite_event_notify("AOR_CONTACT_REMOVED",
-			"Contact: %s\r\n"
-			"AOR: %s\r\n"
-			"UserAgent: %s",
-			contact->uri,
-			contact->aor,
-			contact->user_agent);
+		registrar_contact_delete(CONTACT_DELETE_EXISTING, NULL, contact, contact->aor);
 
 		ao2_unlink(response_contacts, contact);
 	}
@@ -730,8 +775,8 @@
 					monitor->contact_name = monitor->aor_name + strlen(aor_name) + 1;
 					strcpy(monitor->contact_name, contact_name);/* Safe */
 
-					ast_sip_transport_monitor_register(rdata->tp_info.transport,
-						register_contact_transport_shutdown_cb, monitor);
+					ast_sip_transport_monitor_register_replace(rdata->tp_info.transport,
+						register_contact_transport_shutdown_cb, monitor, contact_transport_monitor_matcher);
 					ao2_ref(monitor, -1);
 				}
 			}
@@ -775,7 +820,8 @@
 			if (ast_sip_location_update_contact(contact_update)) {
 				ast_log(LOG_ERROR, "Failed to update contact '%s' expiration time to %d seconds.\n",
 					contact->uri, expiration);
-				ast_sip_location_delete_contact(contact);
+				registrar_contact_delete(CONTACT_DELETE_ERROR, rdata->tp_info.transport,
+					contact, aor_name);
 				continue;
 			}
 			ast_debug(3, "Refreshed contact '%s' on AOR '%s' with new expiration of %d seconds\n",
@@ -792,31 +838,8 @@
 			ao2_link(contacts, contact_update);
 			ao2_cleanup(contact_update);
 		} else {
-			if (contact->prune_on_boot) {
-				struct contact_transport_monitor *monitor;
-				const char *contact_name =
-					ast_sorcery_object_get_id(contact);
-
-				monitor = ast_alloca(sizeof(*monitor) + 2 + strlen(aor_name)
-					+ strlen(contact_name));
-				strcpy(monitor->aor_name, aor_name);/* Safe */
-				monitor->contact_name = monitor->aor_name + strlen(aor_name) + 1;
-				strcpy(monitor->contact_name, contact_name);/* Safe */
-
-				ast_sip_transport_monitor_unregister(rdata->tp_info.transport,
-					register_contact_transport_shutdown_cb, monitor, contact_transport_monitor_matcher);
-			}
-
-			/* We want to report the user agent that was actually in the removed contact */
-			ast_sip_location_delete_contact(contact);
-			ast_verb(3, "Removed contact '%s' from AOR '%s' due to request\n", contact_uri, aor_name);
-			ast_test_suite_event_notify("AOR_CONTACT_REMOVED",
-					"Contact: %s\r\n"
-					"AOR: %s\r\n"
-					"UserAgent: %s",
-					contact_uri,
-					aor_name,
-					contact->user_agent);
+			registrar_contact_delete(CONTACT_DELETE_REQUEST, rdata->tp_info.transport,
+					contact, aor_name);
 		}
 	}
 
@@ -1223,20 +1246,7 @@
 	 */
 	ao2_lock(lock);
 	if (ast_tvdiff_ms(ast_tvnow(), contact->expiration_time) > 0) {
-		if (contact->prune_on_boot) {
-			struct contact_transport_monitor *monitor;
-			const char *contact_name = ast_sorcery_object_get_id(contact);
-
-			monitor = ast_alloca(sizeof(*monitor) + 2 + strlen(contact->aor)
-				+ strlen(contact_name));
-			strcpy(monitor->aor_name, contact->aor);/* Safe */
-			monitor->contact_name = monitor->aor_name + strlen(contact->aor) + 1;
-			strcpy(monitor->contact_name, contact_name);/* Safe */
-
-			ast_sip_transport_monitor_unregister_all(register_contact_transport_shutdown_cb,
-				monitor, contact_transport_monitor_matcher);
-		}
-		ast_sip_location_delete_contact(contact);
+		registrar_contact_delete(CONTACT_DELETE_EXPIRE, NULL, contact, contact->aor);
 	}
 	ao2_unlock(lock);
 	ast_named_lock_put(lock);

-- 
To view, visit https://gerrit.asterisk.org/11014
To unsubscribe, or for help writing mail filters, visit https://gerrit.asterisk.org/settings

Gerrit-Project: asterisk
Gerrit-Branch: 13
Gerrit-MessageType: newchange
Gerrit-Change-Id: I94b06f9026ed177d6adfd538317c784a42c1b17a
Gerrit-Change-Number: 11014
Gerrit-PatchSet: 1
Gerrit-Owner: Kevin Harwell <kharwell at digium.com>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.digium.com/pipermail/asterisk-code-review/attachments/20190220/e8dd3512/attachment-0001.html>


More information about the asterisk-code-review mailing list