summaryrefslogtreecommitdiff
path: root/res/res_pjsip/location.c
diff options
context:
space:
mode:
authorJoshua Colp <jcolp@digium.com>2017-05-31 15:41:45 +0000
committerJoshua Colp <jcolp@digium.com>2017-06-06 09:46:39 -0500
commit861984eac0d9d3582db6922a89e2d75796ae108f (patch)
treed939381d1a4d848c8395636d6533a94072af3e69 /res/res_pjsip/location.c
parent452e6315bb8be7578937de279aa1d906662faa20 (diff)
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
Diffstat (limited to 'res/res_pjsip/location.c')
-rw-r--r--res/res_pjsip/location.c53
1 files changed, 50 insertions, 3 deletions
diff --git a/res/res_pjsip/location.c b/res/res_pjsip/location.c
index 5abfcabad..6213046e3 100644
--- a/res/res_pjsip/location.c
+++ b/res/res_pjsip/location.c
@@ -177,12 +177,36 @@ static int contact_link_static(void *obj, void *arg, int flags)
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);
@@ -193,6 +217,12 @@ struct ast_sip_contact *ast_sip_location_retrieve_first_aor_contact(const struct
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];
struct ao2_container *contacts;
@@ -211,24 +241,41 @@ struct ao2_container *ast_sip_location_retrieve_aor_contacts_nolock(const struct
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 @@ void ast_sip_location_retrieve_contact_and_aor_from_list(const char *aor_list, s
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;