mirror of
				https://github.com/asterisk/asterisk.git
				synced 2025-10-31 02:37:10 +00:00 
			
		
		
		
	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:
		
				
					committed by
					
						 Joshua Colp
						Joshua Colp
					
				
			
			
				
	
			
			
			
						parent
						
							44fba00ca4
						
					
				
				
					commit
					a621dd5e96
				
			| @@ -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) | ||||
| @@ -168,7 +169,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]; | ||||
| @@ -191,6 +192,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) | ||||
| { | ||||
| @@ -274,7 +293,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) | ||||
| { | ||||
| @@ -311,6 +330,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); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user