summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Michelson <mmichelson@digium.com>2017-02-01 13:54:50 -0600
committerMark Michelson <mmichelson@digium.com>2017-02-01 14:21:04 -0600
commitbbed75c3ba424b63257e1556b79a80242f3b6e2b (patch)
tree88b1d9f613a9d40e6678c6f614bd84d4db03eaf9
parente252aff9ad9e8448ec0bdcd031b3833dd460d7db (diff)
Update qualifies when AOR configuration changes.
Prior to this change, qualifies would only update in the following cases: * A reload of res_pjsip.so was issued. * A dynamic contact was re-registered after its AOR's qualify_frequency had been changed This does not work well if you are using realtime for your AORs. You can update your database to have a new qualify_frequency, but the permanent contacts on that AOR will not have their qualifies updated. And the dynamic contacts on that AOR will not have their qualifies updated until the next registration, which could be a long time. This change seeks to fix this problem by making it so that whenever AOR configuration is applied, the contacts pertaining to that AOR have their qualifies updated. Additions from this patch: * AOR sorcery objects now have an apply handler that calls into a newly added function in the OPTIONS code. This causes all contacts associated with that AOR to re-schedule qualifies. * When it is time to qualify a contact, the OPTIONS code checks to see if the AOR can still be retrieved. If not, then qualification is canceled on the contact. Alterations from this patch: * The registrar code no longer updates contact's qualify_frequence and qualify_timeout. There is no point to this since those values already get updated when the AOR changes. * Reloading res_pjsip.so no longer calls the OPTIONS initialization function. Reloading res_pjsip.so results in re-loading AORs, which results in re-scheduling qualifies. Change-Id: I2e7c3316da28f389c45954f24c4e9389abac1121
-rw-r--r--res/res_pjsip.c1
-rw-r--r--res/res_pjsip/include/res_pjsip_private.h12
-rw-r--r--res/res_pjsip/location.c8
-rw-r--r--res/res_pjsip/pjsip_options.c45
-rw-r--r--res/res_pjsip_registrar.c2
5 files changed, 58 insertions, 10 deletions
diff --git a/res/res_pjsip.c b/res/res_pjsip.c
index a7dd09ee8..ee78732c9 100644
--- a/res/res_pjsip.c
+++ b/res/res_pjsip.c
@@ -4368,7 +4368,6 @@ AST_TEST_DEFINE(xml_sanitization_exceeds_buffer)
static int reload_configuration_task(void *obj)
{
ast_res_pjsip_reload_configuration();
- ast_res_pjsip_init_options_handling(1);
ast_sip_initialize_dns();
return 0;
}
diff --git a/res/res_pjsip/include/res_pjsip_private.h b/res/res_pjsip/include/res_pjsip_private.h
index 0bdb63325..6ddbd1f26 100644
--- a/res/res_pjsip/include/res_pjsip_private.h
+++ b/res/res_pjsip/include/res_pjsip_private.h
@@ -184,6 +184,18 @@ void ast_sip_destroy_global_headers(void);
int ast_res_pjsip_init_options_handling(int reload);
/*!
+ * \internal
+ * \brief Indicate OPTIONS handling for this AOR needs updating.
+ *
+ * When AOR configuration is retrieved, it is possible that the
+ * qualify frequency has changed. The OPTIONs code needs to update
+ * its qualifies to reflect these changes.
+ *
+ * \param aor The AOR that has been retrieved
+ */
+void ast_res_pjsip_update_options(struct ast_sip_aor *aor);
+
+/*!
* \internal Initialize message IP updating handling.
*
* \retval 0 on success
diff --git a/res/res_pjsip/location.c b/res/res_pjsip/location.c
index 5abfcabad..cfe65b18e 100644
--- a/res/res_pjsip/location.c
+++ b/res/res_pjsip/location.c
@@ -1137,6 +1137,12 @@ static int contact_apply_handler(const struct ast_sorcery *sorcery, void *object
return status ? 0 : -1;
}
+static int aor_apply_handler(const struct ast_sorcery *sorcery, void *object)
+{
+ ast_res_pjsip_update_options(object);
+ return 0;
+}
+
/*! \brief Initialize sorcery with location support */
int ast_sip_initialize_sorcery_location(void)
{
@@ -1153,7 +1159,7 @@ int ast_sip_initialize_sorcery_location(void)
ast_sorcery_apply_default(sorcery, "aor", "config", "pjsip.conf,criteria=type=aor");
if (ast_sorcery_object_register(sorcery, "contact", contact_alloc, NULL, contact_apply_handler) ||
- ast_sorcery_object_register(sorcery, "aor", aor_alloc, NULL, NULL)) {
+ ast_sorcery_object_register(sorcery, "aor", aor_alloc, NULL, aor_apply_handler)) {
return -1;
}
diff --git a/res/res_pjsip/pjsip_options.c b/res/res_pjsip/pjsip_options.c
index 6fd3c2575..51987f4de 100644
--- a/res/res_pjsip/pjsip_options.c
+++ b/res/res_pjsip/pjsip_options.c
@@ -518,6 +518,18 @@ static int qualify_contact_task(void *obj)
static int qualify_contact_sched(const void *obj)
{
struct sched_data *data = (struct sched_data *) obj;
+ struct ast_sip_aor *aor;
+
+ /* This helps us to determine if an AOR has been removed
+ * from configuration, and if so, stop qualifying the
+ * contact
+ */
+ aor = ast_sip_location_retrieve_aor(data->contact->aor);
+ if (!aor) {
+ ao2_ref(data, -1);
+ return 0;
+ }
+ ao2_ref(aor, -1);
ao2_ref(data->contact, +1);
if (ast_sip_push_task(NULL, qualify_contact_task, data->contact)) {
@@ -1164,12 +1176,10 @@ static int qualify_and_schedule_all_cb(void *obj, void *arg, int flags)
struct ast_sip_aor *aor = obj;
struct ao2_container *contacts;
- if (aor->permanent_contacts) {
- contacts = ast_sip_location_retrieve_aor_contacts(aor);
- if (contacts) {
- ao2_callback(contacts, OBJ_NODATA, qualify_and_schedule_cb_with_aor, aor);
- ao2_ref(contacts, -1);
- }
+ contacts = ast_sip_location_retrieve_aor_contacts(aor);
+ if (contacts) {
+ ao2_callback(contacts, OBJ_NODATA, qualify_and_schedule_cb_with_aor, aor);
+ ao2_ref(contacts, -1);
}
return 0;
@@ -1496,6 +1506,29 @@ int ast_res_pjsip_init_options_handling(int reload)
return 0;
}
+static int unschedule_for_aor_cb(void *obj, void *arg, int flags)
+{
+ struct sched_data *data = obj;
+ struct ast_sip_aor *aor = arg;
+
+ if (!strcmp(ast_sorcery_object_get_id(aor), data->contact->aor)) {
+ AST_SCHED_DEL_UNREF(sched, data->id, ao2_ref(data, -1));
+ }
+
+ return 0;
+}
+
+void ast_res_pjsip_update_options(struct ast_sip_aor *aor)
+{
+ /* This can happen if an AOR is created and applied before OPTIONs code has been initialized */
+ if (!sched_qualifies) {
+ return;
+ }
+
+ ao2_callback(sched_qualifies, OBJ_NODATA | OBJ_UNLINK, unschedule_for_aor_cb, aor);
+ qualify_and_schedule_all_cb(aor, NULL, 0);
+}
+
void ast_res_pjsip_cleanup_options_handling(void)
{
ast_cli_unregister_multiple(cli_options, ARRAY_LEN(cli_options));
diff --git a/res/res_pjsip_registrar.c b/res/res_pjsip_registrar.c
index 2db753889..d190487ac 100644
--- a/res/res_pjsip_registrar.c
+++ b/res/res_pjsip_registrar.c
@@ -456,8 +456,6 @@ static int register_aor_core(pjsip_rx_data *rdata,
}
contact_update->expiration_time = ast_tvadd(ast_tvnow(), ast_samp2tv(expiration, 1));
- contact_update->qualify_frequency = aor->qualify_frequency;
- contact_update->authenticate_qualify = aor->authenticate_qualify;
if (path_str) {
ast_string_field_set(contact_update, path, ast_str_buffer(path_str));
}