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
This commit is contained in:
George Joseph
2016-04-01 12:30:56 -06:00
committed by Joshua Colp
parent 736a2c303d
commit fe7e48db03
4 changed files with 143 additions and 17 deletions

View File

@@ -1004,9 +1004,27 @@ struct ast_sip_contact *ast_sip_location_retrieve_first_aor_contact(const struct
*
* \retval NULL if no contacts available
* \retval non-NULL if contacts available
*
* \warning
* Since this function prunes expired contacts before returning, it holds a named write
* lock on the aor. If you already hold the lock, call ast_sip_location_retrieve_aor_contacts_nolock instead.
*/
struct ao2_container *ast_sip_location_retrieve_aor_contacts(const struct ast_sip_aor *aor);
/*!
* \brief Retrieve all contacts currently available for an AOR without locking the AOR
* \since 13.9.0
*
* \param aor Pointer to the AOR
*
* \retval NULL if no contacts available
* \retval non-NULL if contacts available
*
* \warning
* This function should only be called if you already hold a named write lock on the aor.
*/
struct ao2_container *ast_sip_location_retrieve_aor_contacts_nolock(const struct ast_sip_aor *aor);
/*!
* \brief Retrieve the first bound contact from a list of AORs
*
@@ -1057,11 +1075,36 @@ struct ast_sip_contact *ast_sip_location_retrieve_contact(const char *contact_na
*
* \retval -1 failure
* \retval 0 success
*
* \warning
* This function holds a named write lock on the aor. If you already hold the lock
* you should call ast_sip_location_add_contact_nolock instead.
*/
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);
/*!
* \brief Add a new contact to an AOR without locking the AOR
* \since 13.9.0
*
* \param aor Pointer to the AOR
* \param uri Full contact URI
* \param expiration_time Optional expiration time of the contact
* \param path_info Path information
* \param user_agent User-Agent header from REGISTER request
* \param endpoint The endpoint that resulted in the contact being added
*
* \retval -1 failure
* \retval 0 success
*
* \warning
* This function should only be called if you already hold a named write lock on the aor.
*/
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);
/*!
* \brief Update a contact
*