[Asterisk-code-review] res pjsip: Add support for returning only reachable contacts... (asterisk[14])

Jenkins2 asteriskteam at digium.com
Wed Jun 7 08:29:40 CDT 2017


Jenkins2 has submitted this change and it was merged. ( https://gerrit.asterisk.org/5753 )

Change subject: res_pjsip: Add support for returning only reachable contacts and use it.
......................................................................


res_pjsip: Add support for returning only reachable contacts and use it.

This introduces the ability for PJSIP code to specify filtering flags
when retrieving PJSIP contacts. The first flag for use causes the
query code to only retrieve contacts that are not unreachable. This
change has been leveraged by both the Dial() process and the
PJSIP_DIAL_CONTACTS dialplan function so they will now only attempt
calls to contacts which are not unreachable.

ASTERISK-26281

Change-Id: I8233b4faa21ba3db114f5a42e946e4b191446f6c
---
M CHANGES
M channels/pjsip/dialplan_functions.c
M include/asterisk/res_pjsip.h
M res/res_pjsip.c
M res/res_pjsip/location.c
M res/res_pjsip_session.c
6 files changed, 128 insertions(+), 6 deletions(-)

Approvals:
  Mark Michelson: Looks good to me, but someone else must approve
  George Joseph: Looks good to me, approved
  Jenkins2: Approved for Submit



diff --git a/CHANGES b/CHANGES
index 674105f..709d6c9 100644
--- a/CHANGES
+++ b/CHANGES
@@ -19,6 +19,12 @@
    EAGI provides. If not specified, it will continue to use the default signed
    linear (slin).
 
+chan_pjsip
+------------------
+ * When dialing an endpoint directly or using the PJSIP_DIAL_CONTACTS dialplan
+   function any contact which is considered unreachable due to qualify being
+   enabled will no longer be called.
+
 ------------------------------------------------------------------------------
 --- Functionality changes from Asterisk 14.4.0 to Asterisk 14.5.0 ------------
 ------------------------------------------------------------------------------
diff --git a/channels/pjsip/dialplan_functions.c b/channels/pjsip/dialplan_functions.c
index 0fb8d11..7d73830 100644
--- a/channels/pjsip/dialplan_functions.c
+++ b/channels/pjsip/dialplan_functions.c
@@ -898,7 +898,7 @@
 		if (!aor) {
 			/* If the AOR provided is not found skip it, there may be more */
 			continue;
-		} else if (!(contacts = ast_sip_location_retrieve_aor_contacts(aor))) {
+		} else if (!(contacts = ast_sip_location_retrieve_aor_contacts_filtered(aor, AST_SIP_CONTACT_FILTER_REACHABLE))) {
 			/* No contacts are available, skip it as well */
 			continue;
 		} else if (!ao2_container_count(contacts)) {
diff --git a/include/asterisk/res_pjsip.h b/include/asterisk/res_pjsip.h
index 4206f4b..a7fb921 100644
--- a/include/asterisk/res_pjsip.h
+++ b/include/asterisk/res_pjsip.h
@@ -863,6 +863,17 @@
 };
 
 /*!
+ * \brief Contact retrieval filtering flags
+ */
+enum ast_sip_contact_filter {
+	/*! \brief Default filter flags */
+	AST_SIP_CONTACT_FILTER_DEFAULT = 0,
+
+	/*! \brief Return only reachable or unknown contacts */
+	AST_SIP_CONTACT_FILTER_REACHABLE = (1 << 0),
+};
+
+/*!
  * \brief Register a SIP service in Asterisk.
  *
  * This is more-or-less a wrapper around pjsip_endpt_register_module().
@@ -1048,6 +1059,18 @@
 struct ast_sip_contact *ast_sip_location_retrieve_first_aor_contact(const struct ast_sip_aor *aor);
 
 /*!
+ * \brief Retrieve the first bound contact for an AOR and filter based on flags
+ * \since 13.16.0
+ *
+ * \param aor Pointer to the AOR
+ * \param flags Filtering flags
+ * \retval NULL if no contacts available
+ * \retval non-NULL if contacts available
+ */
+struct ast_sip_contact *ast_sip_location_retrieve_first_aor_contact_filtered(const struct ast_sip_aor *aor,
+	unsigned int flags);
+
+/*!
  * \brief Retrieve all contacts currently available for an AOR
  *
  * \param aor Pointer to the AOR
@@ -1062,6 +1085,23 @@
 struct ao2_container *ast_sip_location_retrieve_aor_contacts(const struct ast_sip_aor *aor);
 
 /*!
+ * \brief Retrieve all contacts currently available for an AOR and filter based on flags
+ * \since 13.16.0
+ *
+ * \param aor Pointer to the AOR
+ * \param flags Filtering flags
+ *
+ * \retval NULL if no contacts available
+ * \retval non-NULL if contacts available
+ *
+ * \warning
+ * Since this function prunes expired contacts before returning, it holds a named write
+ * lock on the aor.  If you already hold the lock, call ast_sip_location_retrieve_aor_contacts_nolock instead.
+ */
+struct ao2_container *ast_sip_location_retrieve_aor_contacts_filtered(const struct ast_sip_aor *aor,
+	unsigned int flags);
+
+/*!
  * \brief Retrieve all contacts currently available for an AOR without locking the AOR
  * \since 13.9.0
  *
@@ -1074,6 +1114,22 @@
  * This function should only be called if you already hold a named write lock on the aor.
  */
 struct ao2_container *ast_sip_location_retrieve_aor_contacts_nolock(const struct ast_sip_aor *aor);
+
+/*!
+ * \brief Retrieve all contacts currently available for an AOR without locking the AOR and filter based on flags
+ * \since 13.16.0
+ *
+ * \param aor Pointer to the AOR
+ * \param flags Filtering flags
+ *
+ * \retval NULL if no contacts available
+ * \retval non-NULL if contacts available
+ *
+ * \warning
+ * This function should only be called if you already hold a named write lock on the aor.
+ */
+struct ao2_container *ast_sip_location_retrieve_aor_contacts_nolock_filtered(const struct ast_sip_aor *aor,
+	unsigned int flags);
 
 /*!
  * \brief Retrieve the first bound contact from a list of AORs
@@ -1104,6 +1160,18 @@
 	struct ast_sip_contact **contact);
 
 /*!
+ * \brief Retrieve the first bound contact AND the AOR chosen from a list of AORs and filter based on flags
+ * \since 13.16.0
+ *
+ * \param aor_list A comma-separated list of AOR names
+ * \param flags Filtering flags
+ * \param aor The chosen AOR
+ * \param contact The chosen contact
+ */
+void ast_sip_location_retrieve_contact_and_aor_from_list_filtered(const char *aor_list, unsigned int flags,
+	struct ast_sip_aor **aor, struct ast_sip_contact **contact);
+
+/*!
  * \brief Retrieve a named contact
  *
  * \param contact_name Name of the contact
diff --git a/res/res_pjsip.c b/res/res_pjsip.c
index c45a0d4..4d92d41 100644
--- a/res/res_pjsip.c
+++ b/res/res_pjsip.c
@@ -3034,7 +3034,7 @@
 	if (res != PJ_SUCCESS) {
 		if (res == PJSIP_EINVALIDURI) {
 			ast_log(LOG_ERROR,
-				"Endpoint '%s': Could not create dialog to invalid URI '%s'.  Is endpoint registered?\n",
+				"Endpoint '%s': Could not create dialog to invalid URI '%s'.  Is endpoint registered and reachable?\n",
 				ast_sorcery_object_get_id(endpoint), uri);
 		}
 		return NULL;
diff --git a/res/res_pjsip/location.c b/res/res_pjsip/location.c
index 5abfcab..6213046 100644
--- a/res/res_pjsip/location.c
+++ b/res/res_pjsip/location.c
@@ -177,12 +177,36 @@
 	return 0;
 }
 
+/*! \brief Internal callback function which removes any contact which is unreachable */
+static int contact_remove_unreachable(void *obj, void *arg, int flags)
+{
+	struct ast_sip_contact *contact = obj;
+	struct ast_sip_contact_status *status;
+	int unreachable;
+
+	status = ast_res_pjsip_find_or_create_contact_status(contact);
+	if (!status) {
+		return 0;
+	}
+
+	unreachable = (status->status == UNAVAILABLE);
+	ao2_ref(status, -1);
+
+	return unreachable ? CMP_MATCH : 0;
+}
+
 struct ast_sip_contact *ast_sip_location_retrieve_first_aor_contact(const struct ast_sip_aor *aor)
+{
+	return ast_sip_location_retrieve_first_aor_contact_filtered(aor, AST_SIP_CONTACT_FILTER_DEFAULT);
+}
+
+struct ast_sip_contact *ast_sip_location_retrieve_first_aor_contact_filtered(const struct ast_sip_aor *aor,
+	unsigned int flags)
 {
 	struct ao2_container *contacts;
 	struct ast_sip_contact *contact = NULL;
 
-	contacts = ast_sip_location_retrieve_aor_contacts(aor);
+	contacts = ast_sip_location_retrieve_aor_contacts_filtered(aor, flags);
 	if (contacts && ao2_container_count(contacts)) {
 		/* Get the first AOR contact in the container. */
 		contact = ao2_callback(contacts, 0, NULL, NULL);
@@ -192,6 +216,12 @@
 }
 
 struct ao2_container *ast_sip_location_retrieve_aor_contacts_nolock(const struct ast_sip_aor *aor)
+{
+	return ast_sip_location_retrieve_aor_contacts_nolock_filtered(aor, AST_SIP_CONTACT_FILTER_DEFAULT);
+}
+
+struct ao2_container *ast_sip_location_retrieve_aor_contacts_nolock_filtered(const struct ast_sip_aor *aor,
+	unsigned int flags)
 {
 	/* Give enough space for ^ at the beginning and ;@ at the end, since that is our object naming scheme */
 	char regex[strlen(ast_sorcery_object_get_id(aor)) + 4];
@@ -211,23 +241,40 @@
 		ao2_callback(aor->permanent_contacts, OBJ_NODATA, contact_link_static, contacts);
 	}
 
+	if (flags & AST_SIP_CONTACT_FILTER_REACHABLE) {
+		ao2_callback(contacts, OBJ_NODATA | OBJ_MULTIPLE | OBJ_UNLINK, contact_remove_unreachable, NULL);
+	}
+
 	return contacts;
 }
 
 struct ao2_container *ast_sip_location_retrieve_aor_contacts(const struct ast_sip_aor *aor)
 {
+	return ast_sip_location_retrieve_aor_contacts_filtered(aor, AST_SIP_CONTACT_FILTER_DEFAULT);
+}
+
+struct ao2_container *ast_sip_location_retrieve_aor_contacts_filtered(const struct ast_sip_aor *aor,
+	unsigned int flags)
+{
 	struct ao2_container *contacts;
 
 	/* ao2_lock / ao2_unlock do not actually write aor since it has an ao2 lockobj. */
 	ao2_lock((void*)aor);
-	contacts = ast_sip_location_retrieve_aor_contacts_nolock(aor);
+	contacts = ast_sip_location_retrieve_aor_contacts_nolock_filtered(aor, flags);
 	ao2_unlock((void*)aor);
 
 	return contacts;
 }
 
+
 void ast_sip_location_retrieve_contact_and_aor_from_list(const char *aor_list, struct ast_sip_aor **aor,
 	struct ast_sip_contact **contact)
+{
+	ast_sip_location_retrieve_contact_and_aor_from_list_filtered(aor_list, AST_SIP_CONTACT_FILTER_DEFAULT, aor, contact);
+}
+
+void ast_sip_location_retrieve_contact_and_aor_from_list_filtered(const char *aor_list, unsigned int flags,
+	struct ast_sip_aor **aor, struct ast_sip_contact **contact)
 {
 	char *aor_name;
 	char *rest;
@@ -247,7 +294,7 @@
 		if (!(*aor)) {
 			continue;
 		}
-		*contact = ast_sip_location_retrieve_first_aor_contact(*aor);
+		*contact = ast_sip_location_retrieve_first_aor_contact_filtered(*aor, flags);
 		/* If a valid contact is available use its URI for dialing */
 		if (*contact) {
 			break;
diff --git a/res/res_pjsip_session.c b/res/res_pjsip_session.c
index 9628c72..eb0d1f0 100644
--- a/res/res_pjsip_session.c
+++ b/res/res_pjsip_session.c
@@ -1717,7 +1717,8 @@
 	if (location || !contact) {
 		location = S_OR(location, endpoint->aors);
 
-		ast_sip_location_retrieve_contact_and_aor_from_list(location, &found_aor, &found_contact);
+		ast_sip_location_retrieve_contact_and_aor_from_list_filtered(location, AST_SIP_CONTACT_FILTER_REACHABLE,
+			&found_aor, &found_contact);
 		if (!found_contact || ast_strlen_zero(found_contact->uri)) {
 			uri = location;
 		} else {

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

Gerrit-MessageType: merged
Gerrit-Change-Id: I8233b4faa21ba3db114f5a42e946e4b191446f6c
Gerrit-PatchSet: 2
Gerrit-Project: asterisk
Gerrit-Branch: 14
Gerrit-Owner: Joshua Colp <jcolp at digium.com>
Gerrit-Reviewer: George Joseph <gjoseph at digium.com>
Gerrit-Reviewer: Jenkins2
Gerrit-Reviewer: Mark Michelson <mmichelson at digium.com>



More information about the asterisk-code-review mailing list