Selaa lähdekoodia

modules/ims_usrloc_scscf, ims_registrar_scscf: distinguish between implicit/explicit contact removal

jaybeepee 10 vuotta sitten
vanhempi
commit
728e52f366

+ 3 - 2
modules/ims_registrar_scscf/registrar_notify.c

@@ -499,6 +499,7 @@ int event_reg(udomain_t* _d, impurecord_t* r_passed, ucontact_t* c_passed, int e
 
             //richard: we only use reg unreg expired and refresh
         case IMS_REGISTRAR_CONTACT_UNREGISTERED:
+        case IMS_REGISTRAR_CONTACT_UNREGISTERED_IMPLICIT:
         case IMS_REGISTRAR_CONTACT_REGISTERED:
         case IMS_REGISTRAR_CONTACT_REFRESHED:
         case IMS_REGISTRAR_CONTACT_EXPIRED:
@@ -599,7 +600,7 @@ int process_contact(impurecord_t* presentity_impurecord, udomain_t * _d, int exp
                         //delete contact
                         LM_DBG("This contact <%.*s> is in state terminated and is in usrloc so removing it from usrloc\n", contact_uri.len, contact_uri.s);
                         ul.lock_contact_slot(&contact_uri);
-                        if (ul.unlink_contact_from_impu(implicit_impurecord, ucontact, 1) != 0) {
+                        if (ul.unlink_contact_from_impu(implicit_impurecord, ucontact, 1, 0 /*implicit dereg of contact from IMPU*/) != 0) {
                             LM_ERR("Failed to delete ucontact <%.*s> from implicit IMPU\n", contact_uri.len, contact_uri.s);
                             ul.unlock_contact_slot(&contact_uri);
                             ul.release_ucontact(ucontact);
@@ -636,7 +637,7 @@ next_implicit_impu:
                 //delete contact
                 LM_DBG("This contact <%.*s> is in state terminated and is in usrloc so removing it from usrloc\n", contact_uri.len, contact_uri.s);
                 ul.lock_contact_slot(&contact_uri);
-                if (ul.unlink_contact_from_impu(presentity_impurecord, ucontact, 1) != 0) {
+                if (ul.unlink_contact_from_impu(presentity_impurecord, ucontact, 1, 0 /*implicit dereg of contact from IMPU */) != 0) {
                     LM_ERR("Failed to delete ucontact <%.*s>\n", contact_uri.len, contact_uri.s);
                     ret = CSCF_RETURN_FALSE;
                     ul.unlock_contact_slot(&contact_uri);

+ 1 - 0
modules/ims_registrar_scscf/registrar_notify.h

@@ -109,6 +109,7 @@ enum {
     IMS_REGISTRAR_CONTACT_REFRESHED, /**< The expiration was refreshed					*/
     IMS_REGISTRAR_CONTACT_EXPIRED, /**< A contact has expired and will be removed		*/
     IMS_REGISTRAR_CONTACT_UNREGISTERED, /**< User unregistered with Expires 0				*/
+    IMS_REGISTRAR_CONTACT_UNREGISTERED_IMPLICIT, /**< User unregistered implicitly, ie not via explicit deregister	*/
 } IMS_Registrar_events;
 
 

+ 1 - 1
modules/ims_registrar_scscf/save.c

@@ -668,7 +668,7 @@ static inline int unregister_contact(udomain_t* _d, str* public_identity, impure
 
     //    if (ul.delete_ucontact(impu_rec, ucontact) != 0) {
     ul.lock_contact_slot_i(ucontact->sl);
-    if (ul.unlink_contact_from_impu(impu_rec, ucontact, 1) != 0) {
+    if (ul.unlink_contact_from_impu(impu_rec, ucontact, 1, 1/*explicit dereg of contact*/) != 0) {
         LM_ERR("Failed to delete ucontact <%.*s>\n", chi->uri.len, chi->uri.s);
     }
     ul.unlock_contact_slot_i(ucontact->sl);

+ 4 - 1
modules/ims_registrar_scscf/usrloc_cb.c

@@ -54,7 +54,7 @@ void ul_impu_inserted(impurecord_t* r, ucontact_t* c, int type, void* param) {
 
     LM_DBG("Registering for callbacks on this IMPU for contact insert, update, delete or expire to send notifications if there are any subscriptions");
     ul.register_ulcb(r, 0, UL_IMPU_NEW_CONTACT, ul_contact_changed, 0); //this allows us to receive cbs on new contact for IMPU
-    ul.register_ulcb(r, 0, UL_IMPU_UPDATE_CONTACT | UL_IMPU_EXPIRE_CONTACT | UL_IMPU_DELETE_CONTACT, ul_contact_changed, 0);
+    ul.register_ulcb(r, 0, UL_IMPU_UPDATE_CONTACT | UL_IMPU_EXPIRE_CONTACT | UL_IMPU_DELETE_CONTACT | UL_IMPU_DELETE_CONTACT_IMPLICIT, ul_contact_changed, 0);
 
     LM_DBG("Selectively asking for expire or no contact delete callbacks only on the anchor of the implicit set so that we only send one SAR per implicit set");
     if (r->is_primary) {
@@ -95,6 +95,9 @@ void ul_contact_changed(impurecord_t* r, ucontact_t* c, int type, void* param) {
     if (type == UL_IMPU_DELETE_CONTACT) {
         LM_DBG("Received notification of UL CONTACT DELETE");
         event_reg(0, r, c, IMS_REGISTRAR_CONTACT_UNREGISTERED, 0, 0);
+    } else if (type == UL_IMPU_DELETE_CONTACT_IMPLICIT) {
+        LM_DBG("Received notification of UL CONTACT_DELETE_IMPLICIT");
+        event_reg(0, r, c, IMS_REGISTRAR_CONTACT_UNREGISTERED_IMPLICIT, 0, 0);
     } else if (type == UL_IMPU_EXPIRE_CONTACT) {
         LM_DBG("Received notification of UL CONTACT EXPIRE");
         event_reg(0, r, c, IMS_REGISTRAR_CONTACT_EXPIRED, 0, 0);

+ 24 - 18
modules/ims_usrloc_scscf/impurecord.c

@@ -395,7 +395,7 @@ static inline void process_impurecord(impurecord_t* _r) {
             LM_DBG("\t\texpiring contact %i: [%.*s] in slot [%d]\n", n, contacts_to_expire[n]->c.len, contacts_to_expire[n]->c.s, contacts_to_expire[n]->sl);
             sl = ptr->sl;
             lock_contact_slot_i(sl);
-            unlink_contact_from_impu(_r, ptr, 1);
+            unlink_contact_from_impu(_r, ptr, 1, 0 /*implicit dereg of contact from IMPU*/);
             unlock_contact_slot_i(sl);
         }
     }
@@ -1002,7 +1002,7 @@ int link_contact_to_impu(impurecord_t* impu, ucontact_t* contact, int write_to_d
     if (i < MAX_CONTACTS_PER_IMPU) {
         LM_DBG("contact [%.*s] needs to be linked to impu [%.*s] at position %d\n", contact->c.len, contact->c.s, impu->public_identity.len, impu->public_identity.s, i);
         if (overwrite)
-            unlink_contact_from_impu(impu, impu->newcontacts[i], write_to_db); //unlink the contact we are overwriting
+            unlink_contact_from_impu(impu, impu->newcontacts[i], write_to_db, 0 /*implicit dereg of contact */); //unlink the contact we are overwriting
 
         impu->num_contacts = i + 1; //we always bump this - as unlink (in overwrite would have decremented)
         impu->newcontacts[i] = contact;
@@ -1019,8 +1019,8 @@ int link_contact_to_impu(impurecord_t* impu, ucontact_t* contact, int write_to_d
     return 0;
 }
 
-int unlink_contact_from_impu(impurecord_t* impu, ucontact_t* contact, int write_to_db) {
-    ucontact_t* ptr;
+int unlink_contact_from_impu(impurecord_t* impu, ucontact_t* contact, int write_to_db, int is_explicit) {
+    ucontact_t* ptr, *found_contact;
     int i;
     i = 0;
     int found = 0;
@@ -1035,29 +1035,35 @@ int unlink_contact_from_impu(impurecord_t* impu, ucontact_t* contact, int write_
         } else {
             if (ptr == contact) {
                 LM_DBG("unlinking contact [%.*s] from impu [%.*s]\n", contact->c.len, contact->c.s, impu->public_identity.len, impu->public_identity.s);
-
-                if (exists_ulcb_type(impu->cbs, UL_IMPU_DELETE_CONTACT)) {
-                    LM_DBG("Running callback UL_IMPU_DELETE_CONTACT for contact [%.*s] and impu [%.*s]\n", ptr->c.len, ptr->c.s, impu->public_identity.len, impu->public_identity.s);
-                    run_ul_callbacks(impu->cbs, UL_IMPU_DELETE_CONTACT, impu, ptr);
-                }
-
                 found = 1;
+                found_contact = ptr;
                 impu->newcontacts[i] = 0;
                 impu->num_contacts--;
-                unref_contact_unsafe(contact); //should we lock the actual contact? safe version maybe?
-
-                if (write_to_db && db_mode == WRITE_THROUGH && db_unlink_contact_from_impu(impu, contact) != 0) {
-                    LM_ERR("Failed to un-link DB contact [%.*s] from IMPU [%.*s]...continuing but db will be out of sync!\n", contact->c.len, contact->c.s, impu->public_identity.len, impu->public_identity.s);
-                }
             }
         }
         i++;
         ptr = impu->newcontacts[i];
     }
 
-    if (found && i < MAX_CONTACTS_PER_IMPU) {
-        LM_DBG("zero'ing last pointer to contact in the list\n");
-        impu->newcontacts[i - 1] = 0;
+    if (found) {
+        if (i < MAX_CONTACTS_PER_IMPU) {
+            LM_DBG("zero'ing last pointer to contact in the list\n");
+            impu->newcontacts[i - 1] = 0;
+        }
+        LM_DBG("unlinking contact [%.*s] from impu [%.*s]\n", found_contact->c.len, found_contact->c.s, impu->public_identity.len, impu->public_identity.s);
+        if (is_explicit && exists_ulcb_type(impu->cbs, UL_IMPU_DELETE_CONTACT)) {
+            LM_DBG("Running callback UL_IMPU_DELETE_CONTACT for contact [%.*s] and impu [%.*s]\n", found_contact->c.len, found_contact->c.s, impu->public_identity.len, impu->public_identity.s);
+            run_ul_callbacks(impu->cbs, UL_IMPU_DELETE_CONTACT, impu, found_contact);
+        }
+        if (!is_explicit && exists_ulcb_type(impu->cbs, UL_IMPU_DELETE_CONTACT_IMPLICIT)) {
+            LM_DBG("Running callback UL_IMPU_DELETE_CONTACT_IMPLICIT for contact [%.*s] and impu [%.*s]\n", found_contact->c.len, found_contact->c.s, impu->public_identity.len, impu->public_identity.s);
+            run_ul_callbacks(impu->cbs, UL_IMPU_DELETE_CONTACT_IMPLICIT, impu, found_contact);
+        }
+
+        if (write_to_db && db_mode == WRITE_THROUGH && db_unlink_contact_from_impu(impu, found_contact) != 0) {
+            LM_ERR("Failed to un-link DB contact [%.*s] from IMPU [%.*s]...continuing but db will be out of sync!\n", found_contact->c.len, found_contact->c.s, impu->public_identity.len, impu->public_identity.s);
+        }
+        unref_contact_unsafe(found_contact); //should we lock the actual contact? safe version maybe?
     } else {
         LM_DBG("contact [%.*s] did not exist in IMPU list [%.*s] while trying to unlink\n", contact->c.len, contact->c.s, impu->public_identity.len, impu->public_identity.s);
     }

+ 1 - 1
modules/ims_usrloc_scscf/impurecord.h

@@ -173,7 +173,7 @@ int get_ucontact(impurecord_t* _r, str* _c, str* _callid, str* _path,
 int update_impurecord(struct udomain* _d, str* public_identity, impurecord_t* impu_rec, int reg_state, int send_sar_on_delete, int barring, int is_primary, ims_subscription** s, str* ccf1, str* ccf2, str* ecf1, str* ecf2, struct impurecord** _r);
 
 int link_contact_to_impu(impurecord_t* impu, ucontact_t* contact, int write_to_db);
-int unlink_contact_from_impu(impurecord_t* impu, ucontact_t* contact, int write_to_db);
+int unlink_contact_from_impu(impurecord_t* impu, ucontact_t* contact, int write_to_db, int is_explicit);
 
 void ref_subscription_unsafe(ims_subscription* s);
 void unref_subscription_unsafe(ims_subscription* s);

+ 5 - 4
modules/ims_usrloc_scscf/ul_callback.h

@@ -63,10 +63,11 @@ struct impurecord;
 #define UL_IMPU_INSERT		   	(1<<8)		/* new IMPU record has been added */
 #define UL_IMPU_UPDATE		   	(1<<9)		/* IMPU record has been updated */
 #define UL_IMPU_NEW_CONTACT		(1<<10)		/* a new contact has been inserted for this IMPU */
-#define UL_IMPU_UPDATE_CONTACT		(1<<11)		/* a new contact has been inserted for this IMPU */
-#define UL_IMPU_DELETE_CONTACT		(1<<12)		/* a new contact has been inserted for this IMPU */
-#define UL_IMPU_EXPIRE_CONTACT		(1<<13)		/* a new contact has been inserted for this IMPU */
-#define ULCB_MAX               	((1<<14)-1)
+#define UL_IMPU_UPDATE_CONTACT		(1<<11)		/* contact has been updated */
+#define UL_IMPU_DELETE_CONTACT		(1<<12)		/* explciti contact delete from IMPU (dereg) */
+#define UL_IMPU_DELETE_CONTACT_IMPLICIT	(1<<13)		/* implicit contact delete frim IMPU (expiry, etc) */
+#define UL_IMPU_EXPIRE_CONTACT		(1<<14)		/* a new contact has been inserted for this IMPU */
+#define ULCB_MAX               	((1<<15)-1)
 
 /*! \brief callback function prototype */
 typedef void (ul_cb) (struct impurecord* r, struct ucontact *c, int type, void *param);

+ 1 - 1
modules/ims_usrloc_scscf/usrloc.h

@@ -459,7 +459,7 @@ typedef int (*update_ucontact_t)(struct impurecord* _r, struct ucontact* _c, str
 
 typedef int (*expire_ucontact_t)(struct impurecord* _r, struct ucontact* _c);
 
-typedef int (*unlink_contact_from_impu_t)(struct impurecord* _r, struct ucontact* _c, int write_to_db);
+typedef int (*unlink_contact_from_impu_t)(struct impurecord* _r, struct ucontact* _c, int write_to_db, int is_explicit);
 
 typedef int (*link_contact_to_impu_t)(struct impurecord* _r, struct ucontact* _c, int wirte_to_db);