summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatt Jordan <mjordan@digium.com>2015-11-02 06:57:22 -0600
committerMatt Jordan <mjordan@digium.com>2015-11-02 07:52:34 -0600
commit11e54b1932b62a084722cb547a51a5fc2ca4d423 (patch)
treed5d7723896e6290bbe8ad1065e9c1894a03e8efe
parent9a021a42adaee95d115aa3200467943fecd1f13a (diff)
pjsip_options: Schedule/unschedule qualifies on AoR creation/destruction
When an AoR is created or destroyed dynamically, the scheduled OPTIONS requests that qualify the contacts on the AoR are not necessarily started or destroyed, particularly for persistent contacts created for that AoR. This patch adds create/update/delete sorcery observers for an AoR, which schedule/unschedule the qualifies as expected. Change-Id: Ic287ed2e2952a7808ee068776fe966f9554bdf7d
-rw-r--r--res/res_pjsip/pjsip_options.c46
1 files changed, 46 insertions, 0 deletions
diff --git a/res/res_pjsip/pjsip_options.c b/res/res_pjsip/pjsip_options.c
index f888cc451..32ee401ea 100644
--- a/res/res_pjsip/pjsip_options.c
+++ b/res/res_pjsip/pjsip_options.c
@@ -1026,6 +1026,7 @@ static int qualify_and_schedule_cb(void *obj, void *arg, int flags)
initial_interval = (int)((initial_interval * 1000) * ast_random_double());
+ unschedule_qualify(contact);
if (contact->qualify_frequency) {
schedule_qualify(contact, initial_interval);
} else {
@@ -1155,6 +1156,43 @@ static struct ast_sip_endpoint_formatter contact_status_formatter = {
.format_ami = format_ami_contact_status
};
+static void aor_observer_modified(const void *obj)
+{
+ struct ast_sip_aor *aor = (void *)obj;
+ struct ao2_container *contacts;
+
+ contacts = ast_sip_location_retrieve_aor_contacts(aor);
+ if (contacts) {
+ ao2_callback(contacts, OBJ_NODATA, qualify_and_schedule_cb, aor);
+ ao2_ref(contacts, -1);
+ }
+}
+
+static int unschedule_contact_cb(void *obj, void *arg, int flags)
+{
+ unschedule_qualify(obj);
+
+ return CMP_MATCH;
+}
+
+static void aor_observer_deleted(const void *obj)
+{
+ const struct ast_sip_aor *aor = obj;
+ struct ao2_container *contacts;
+
+ contacts = ast_sip_location_retrieve_aor_contacts(aor);
+ if (contacts) {
+ ao2_callback(contacts, OBJ_NODATA, unschedule_contact_cb, NULL);
+ ao2_ref(contacts, -1);
+ }
+}
+
+static const struct ast_sorcery_observer observer_callbacks_options = {
+ .created = aor_observer_modified,
+ .updated = aor_observer_modified,
+ .deleted = aor_observer_deleted
+};
+
int ast_res_pjsip_init_options_handling(int reload)
{
static const pj_str_t STR_OPTIONS = { "OPTIONS", 7 };
@@ -1185,6 +1223,13 @@ int ast_res_pjsip_init_options_handling(int reload)
return -1;
}
+ if (ast_sorcery_observer_add(ast_sip_get_sorcery(), "aor", &observer_callbacks_options)) {
+ pjsip_endpt_unregister_module(ast_sip_get_pjsip_endpoint(), &options_module);
+ ao2_cleanup(sched_qualifies);
+ sched_qualifies = NULL;
+ return -1;
+ }
+
internal_sip_register_endpoint_formatter(&contact_status_formatter);
ast_manager_register2("PJSIPQualify", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, ami_sip_qualify, NULL, NULL, NULL);
ast_cli_register_multiple(cli_options, ARRAY_LEN(cli_options));
@@ -1200,6 +1245,7 @@ void ast_res_pjsip_cleanup_options_handling(void)
ast_manager_unregister("PJSIPQualify");
internal_sip_unregister_endpoint_formatter(&contact_status_formatter);
+ ast_sorcery_observer_remove(ast_sip_get_sorcery(), "aor", &observer_callbacks_options);
pjsip_endpt_unregister_module(ast_sip_get_pjsip_endpoint(), &options_module);
ao2_cleanup(sched_qualifies);
sched_qualifies = NULL;