diff options
author | George Joseph <george.joseph@fairview5.com> | 2016-04-01 12:30:56 -0600 |
---|---|---|
committer | Joshua Colp <jcolp@digium.com> | 2016-04-11 13:00:14 -0500 |
commit | fe7e48db03de03c232cc5af28e37ce08c5ccd3d8 (patch) | |
tree | 42c7165686c2d8c4e3ae2d39a760855bfef92956 /res/res_pjsip | |
parent | 736a2c303db533eff296a93a120405d0f2855e27 (diff) |
res_pjsip contact: Lock expiration/addition of contacts
Contact expiration can occur in several places: res_pjsip_registrar,
res_pjsip_registrar_expire, and automatically when anyone calls
ast_sip_location_retrieve_aor_contact. At the same time, res_pjsip_registrar
may also be attempting to renew or add a contact. Since none of this was locked
it was possible for one thread to be renewing a contact and another thread to
expire it immediately because it was working off of stale data. This was the
casue of intermittent registration/inbound/nominal/multiple_contacts test
failures.
Now, the new named lock functionality is used to lock the aor during contact
expire and add operations and res_pjsip_registrar_expire now checks the
expiration with the lock held before deleting the contact.
ASTERISK-25885 #close
Reported-by: Josh Colp
Change-Id: I83d413c46a47796f3ab052ca3b349f21cca47059
Diffstat (limited to 'res/res_pjsip')
-rw-r--r-- | res/res_pjsip/location.c | 44 |
1 files changed, 42 insertions, 2 deletions
diff --git a/res/res_pjsip/location.c b/res/res_pjsip/location.c index 735b18f46..3413708e9 100644 --- a/res/res_pjsip/location.c +++ b/res/res_pjsip/location.c @@ -27,6 +27,7 @@ #include "include/res_pjsip_private.h" #include "asterisk/res_pjsip_cli.h" #include "asterisk/statsd.h" +#include "asterisk/named_locks.h" /*! \brief Destructor for AOR */ static void aor_destroy(void *obj) @@ -173,7 +174,7 @@ struct ast_sip_contact *ast_sip_location_retrieve_first_aor_contact(const struct return contact; } -struct ao2_container *ast_sip_location_retrieve_aor_contacts(const struct ast_sip_aor *aor) +struct ao2_container *ast_sip_location_retrieve_aor_contacts_nolock(const struct ast_sip_aor *aor) { /* 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]; @@ -196,6 +197,24 @@ struct ao2_container *ast_sip_location_retrieve_aor_contacts(const struct ast_si return contacts; } +struct ao2_container *ast_sip_location_retrieve_aor_contacts(const struct ast_sip_aor *aor) +{ + struct ao2_container *contacts; + struct ast_named_lock *lock; + + lock = ast_named_lock_get(AST_NAMED_LOCK_TYPE_RWLOCK, "aor", ast_sorcery_object_get_id(aor)); + if (!lock) { + return NULL; + } + + ao2_wrlock(lock); + contacts = ast_sip_location_retrieve_aor_contacts_nolock(aor); + ao2_unlock(lock); + ast_named_lock_put(lock); + + 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) { @@ -279,7 +298,7 @@ struct ast_sip_contact *ast_sip_location_retrieve_contact(const char *contact_na return ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "contact", contact_name); } -int ast_sip_location_add_contact(struct ast_sip_aor *aor, const char *uri, +int ast_sip_location_add_contact_nolock(struct ast_sip_aor *aor, const char *uri, struct timeval expiration_time, const char *path_info, const char *user_agent, struct ast_sip_endpoint *endpoint) { @@ -316,6 +335,27 @@ int ast_sip_location_add_contact(struct ast_sip_aor *aor, const char *uri, return ast_sorcery_create(ast_sip_get_sorcery(), contact); } +int ast_sip_location_add_contact(struct ast_sip_aor *aor, const char *uri, + struct timeval expiration_time, const char *path_info, const char *user_agent, + struct ast_sip_endpoint *endpoint) +{ + int res; + struct ast_named_lock *lock; + + lock = ast_named_lock_get(AST_NAMED_LOCK_TYPE_RWLOCK, "aor", ast_sorcery_object_get_id(aor)); + if (!lock) { + return -1; + } + + ao2_wrlock(lock); + res = ast_sip_location_add_contact_nolock(aor, uri, expiration_time, path_info, user_agent, + endpoint); + ao2_unlock(lock); + ast_named_lock_put(lock); + + return res; +} + int ast_sip_location_update_contact(struct ast_sip_contact *contact) { return ast_sorcery_update(ast_sip_get_sorcery(), contact); |