@@ -65,6 +65,9 @@ struct dlg_set
6565 /* This is the buffer to store this entry in the hash table. */
6666 pj_hash_entry_buf ht_entry ;
6767
68+ /* Entry key in the hash table */
69+ pj_str_t ht_key ;
70+
6871 /* List of dialog in this dialog set. */
6972 struct dlg_set_head dlg_list ;
7073};
@@ -327,15 +330,16 @@ PJ_DEF(pj_status_t) pjsip_ua_register_dlg( pjsip_user_agent *ua,
327330 * Create the dialog set and add this dialog to it.
328331 */
329332 dlg_set = alloc_dlgset_node ();
333+ dlg_set -> ht_key = dlg -> local .info -> tag ;
330334 pj_list_init (& dlg_set -> dlg_list );
331335 pj_list_push_back (& dlg_set -> dlg_list , dlg );
332336
333337 dlg -> dlg_set = dlg_set ;
334338
335339 /* Register the dialog set in the hash table. */
336340 pj_hash_set_np_lower (mod_ua .dlg_table ,
337- dlg -> local . info -> tag .ptr ,
338- (unsigned )dlg -> local . info -> tag .slen ,
341+ dlg_set -> ht_key .ptr ,
342+ (unsigned )dlg_set -> ht_key .slen ,
339343 dlg -> local .tag_hval , dlg_set -> ht_entry ,
340344 dlg_set );
341345 }
@@ -345,14 +349,15 @@ PJ_DEF(pj_status_t) pjsip_ua_register_dlg( pjsip_user_agent *ua,
345349 struct dlg_set * dlg_set ;
346350
347351 dlg_set = alloc_dlgset_node ();
352+ dlg_set -> ht_key = dlg -> local .info -> tag ;
348353 pj_list_init (& dlg_set -> dlg_list );
349354 pj_list_push_back (& dlg_set -> dlg_list , dlg );
350355
351356 dlg -> dlg_set = dlg_set ;
352357
353358 pj_hash_set_np_lower (mod_ua .dlg_table ,
354- dlg -> local . info -> tag .ptr ,
355- (unsigned )dlg -> local . info -> tag .slen ,
359+ dlg_set -> ht_key .ptr ,
360+ (unsigned )dlg_set -> ht_key .slen ,
356361 dlg -> local .tag_hval , dlg_set -> ht_entry , dlg_set );
357362 }
358363
@@ -397,12 +402,43 @@ PJ_DEF(pj_status_t) pjsip_ua_unregister_dlg( pjsip_user_agent *ua,
397402
398403 /* If dialog list is empty, remove the dialog set from the hash table. */
399404 if (pj_list_empty (& dlg_set -> dlg_list )) {
400- pj_hash_set_lower (NULL , mod_ua .dlg_table , dlg -> local .info -> tag .ptr ,
401- (unsigned )dlg -> local .info -> tag .slen ,
405+
406+ /* Verify that the dialog set is valid */
407+ pj_assert (pj_hash_get_lower (mod_ua .dlg_table , dlg_set -> ht_key .ptr ,
408+ (unsigned )dlg_set -> ht_key .slen ,
409+ & dlg -> local .tag_hval ) == dlg_set );
410+
411+ pj_hash_set_lower (NULL , mod_ua .dlg_table , dlg_set -> ht_key .ptr ,
412+ (unsigned )dlg_set -> ht_key .slen ,
402413 dlg -> local .tag_hval , NULL );
403414
404415 /* Return dlg_set to free nodes. */
405416 pj_list_push_back (& mod_ua .free_dlgset_nodes , dlg_set );
417+ } else {
418+ /* If the just unregistered dialog is being used as hash key,
419+ * reset the dlg_set entry with a new key (i.e: from the first dialog
420+ * in dlg_set).
421+ */
422+ if (dlg_set -> ht_key .ptr == dlg -> local .info -> tag .ptr &&
423+ dlg_set -> ht_key .slen == dlg -> local .info -> tag .slen )
424+ {
425+ pjsip_dialog * key_dlg = dlg_set -> dlg_list .next ;
426+
427+ /* Verify that the old & new keys share the hash value */
428+ pj_assert (key_dlg -> local .tag_hval == dlg -> local .tag_hval );
429+
430+ pj_hash_set_lower (NULL , mod_ua .dlg_table , dlg_set -> ht_key .ptr ,
431+ (unsigned )dlg_set -> ht_key .slen ,
432+ dlg -> local .tag_hval , NULL );
433+
434+ dlg_set -> ht_key = key_dlg -> local .info -> tag ;
435+
436+ pj_hash_set_np_lower (mod_ua .dlg_table ,
437+ dlg_set -> ht_key .ptr ,
438+ (unsigned )dlg_set -> ht_key .slen ,
439+ key_dlg -> local .tag_hval , dlg_set -> ht_entry ,
440+ dlg_set );
441+ }
406442 }
407443
408444 /* Unlock user agent. */
0 commit comments