summaryrefslogtreecommitdiff
path: root/res/res_pjsip_outbound_registration.c
diff options
context:
space:
mode:
authorGeorge Joseph <george.joseph@fairview5.com>2015-01-08 17:51:36 +0000
committerGeorge Joseph <george.joseph@fairview5.com>2015-01-08 17:51:36 +0000
commit030facce949c3cdd81237826d46bea876242cb30 (patch)
tree8b7ccaf89345d3411915a45ef211d285f999b38e /res/res_pjsip_outbound_registration.c
parentf8c4909eb7b1b614a0726d35c7c5b6ab00774cd0 (diff)
res_pjsip_outbound_registration: Fix several reload issues
There are 2 issues with reloading registrations... 1. The 'can_reuse_registration' test wasn't considering the intervals or expiration in its determination of whether a registration changed or not so if you changed any of the intervals or the expiration and reloaded, the object would get reloaded but the actual timers wouldn't change. can_reuse_registration now does a sorcery diff on the old and new objects instead of discretely testing certain fields. Now if you change expiration for instance, and reload, the timer is updated and re-registration will occur on the new value. 2. If you mung up your password on an outbound registration you get a permanent failure. If you fix the password (on the outbound_auth object) and reload, nothing tells outbound_registration to try again because the registration itself didn't change. This patch adds an observer on the "auth" object type and if any auth changes, existing registration states are searched and those in a REJECTED_PERMANENT state are retried. Tested-by: George Joseph Review: https://reviewboard.asterisk.org/r/4304/ ........ Merged revisions 430373 from http://svn.asterisk.org/svn/asterisk/branches/13 git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@430374 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'res/res_pjsip_outbound_registration.c')
-rw-r--r--res/res_pjsip_outbound_registration.c80
1 files changed, 65 insertions, 15 deletions
diff --git a/res/res_pjsip_outbound_registration.c b/res/res_pjsip_outbound_registration.c
index 1faa93e5a..6ccb7fcf2 100644
--- a/res/res_pjsip_outbound_registration.c
+++ b/res/res_pjsip_outbound_registration.c
@@ -889,25 +889,27 @@ static int sip_dialog_create_contact(pj_pool_t *pool, pj_str_t *contact, const c
* \param existing The pre-existing outbound registration
* \param applied The newly-created registration
*/
-static int can_reuse_registration(struct sip_outbound_registration *existing, struct sip_outbound_registration *applied)
+static int can_reuse_registration(struct sip_outbound_registration *existing,
+ struct sip_outbound_registration *applied)
{
- int i;
-
- if (strcmp(existing->server_uri, applied->server_uri) || strcmp(existing->client_uri, applied->client_uri) ||
- strcmp(existing->transport, applied->transport) || strcmp(existing->contact_user, applied->contact_user) ||
- strcmp(existing->outbound_proxy, applied->outbound_proxy) ||
- AST_VECTOR_SIZE(&existing->outbound_auths) != AST_VECTOR_SIZE(&applied->outbound_auths) ||
- existing->auth_rejection_permanent != applied->auth_rejection_permanent) {
- return 0;
+ int rc = 1;
+ struct ast_sorcery *sorcery = ast_sip_get_sorcery();
+ struct ast_variable *ve = ast_sorcery_objectset_create(sorcery, existing);
+ struct ast_variable *va = ast_sorcery_objectset_create(sorcery, applied);
+ struct ast_variable *vc = NULL;
+
+ if (ast_sorcery_changeset_create(ve, va, &vc) || vc != NULL) {
+ rc = 0;
+ ast_debug(4, "Registration '%s' changed. Can't re-use.\n", ast_sorcery_object_get_id(existing));
+ } else {
+ ast_debug(4, "Registration '%s' didn't change. Can re-use\n", ast_sorcery_object_get_id(existing));
}
- for (i = 0; i < AST_VECTOR_SIZE(&existing->outbound_auths); ++i) {
- if (strcmp(AST_VECTOR_GET(&existing->outbound_auths, i), AST_VECTOR_GET(&applied->outbound_auths, i))) {
- return 0;
- }
- }
+ ast_variables_destroy(ve);
+ ast_variables_destroy(va);
+ ast_variables_destroy(vc);
- return 1;
+ return rc;
}
/*! \brief Helper function that allocates a pjsip registration client and configures it */
@@ -1051,6 +1053,8 @@ static int sip_outbound_registration_apply(const struct ast_sorcery *sorcery, vo
RAII_VAR(struct sip_outbound_registration_state *, new_state, NULL, ao2_cleanup);
struct sip_outbound_registration *applied = obj;
+ ast_debug(4, "Applying configuration to outbound registration '%s'\n", ast_sorcery_object_get_id(applied));
+
if (ast_strlen_zero(applied->server_uri)) {
ast_log(LOG_ERROR, "No server URI specified on outbound registration '%s'",
ast_sorcery_object_get_id(applied));
@@ -1070,6 +1074,9 @@ static int sip_outbound_registration_apply(const struct ast_sorcery *sorcery, vo
}
if (state && can_reuse_registration(state->registration, applied)) {
+ ast_debug(4,
+ "No change between old configuration and new configuration on outbound registration '%s'. Using previous state\n",
+ ast_sorcery_object_get_id(applied));
ao2_replace(state->registration, applied);
return 0;
}
@@ -1546,9 +1553,50 @@ static struct ast_cli_entry cli_outbound_registration[] = {
static struct ast_sip_cli_formatter_entry *cli_formatter;
+static void auth_observer(const char *type)
+{
+ struct sip_outbound_registration *registration;
+ struct sip_outbound_registration_state *state;
+ struct ao2_container *regs;
+ const char *registration_id;
+ struct ao2_iterator i;
+
+ ast_debug(4, "Auths updated. Checking for any outbound registrations that are in permanent rejected state so they can be retried\n");
+
+ regs = ast_sorcery_retrieve_by_fields(ast_sip_get_sorcery(), "registration",
+ AST_RETRIEVE_FLAG_MULTIPLE | AST_RETRIEVE_FLAG_ALL, NULL);
+ if (!regs || ao2_container_count(regs) == 0) {
+ ao2_cleanup(regs);
+ return;
+ }
+
+ i = ao2_iterator_init(regs, 0);
+ for (; (registration = ao2_iterator_next(&i)); ao2_ref(registration, -1)) {
+ registration_id = ast_sorcery_object_get_id(registration);
+ state = get_state(registration_id);
+ if (state && state->client_state->status == SIP_REGISTRATION_REJECTED_PERMANENT) {
+ ast_debug(4, "Trying outbound registration '%s' again\n", registration_id);
+
+ if (ast_sip_push_task(state->client_state->serializer,
+ sip_outbound_registration_perform, ao2_bump(state))) {
+ ast_log(LOG_ERROR, "Failed to perform outbound registration on '%s'\n", registration_id);
+ ao2_ref(state, -1);
+ }
+ }
+ ao2_cleanup(state);
+ }
+ ao2_iterator_destroy(&i);
+ ao2_cleanup(regs);
+}
+
+const struct ast_sorcery_observer observer_callbacks = {
+ .loaded = auth_observer,
+};
+
static int unload_module(void)
{
ast_sip_unregister_endpoint_identifier(&line_identifier);
+ ast_sorcery_observer_remove(ast_sip_get_sorcery(), "auth", &observer_callbacks);
ast_cli_unregister_multiple(cli_outbound_registration, ARRAY_LEN(cli_outbound_registration));
ast_sip_unregister_cli_formatter(cli_formatter);
ast_manager_unregister("PJSIPShowRegistrationsOutbound");
@@ -1626,6 +1674,8 @@ static int load_module(void)
}
ao2_ref(registrations, -1);
+ ast_sorcery_observer_add(ast_sip_get_sorcery(), "auth", &observer_callbacks);
+
return AST_MODULE_LOAD_SUCCESS;
}