ims_registrar_scscf: added a new registrar event, notification improvements
authorAleksandar Yosifov <alexyosifov@gmail.com>
Fri, 17 Jul 2020 07:45:00 +0000 (10:45 +0300)
committerHenning Westerholt <hw@skalatan.de>
Tue, 21 Jul 2020 20:07:30 +0000 (22:07 +0200)
    - Added a new IMS registrar event: IMS_REGISTRAR_SUBSEQUENT_SUBSCRIBE -
      used to skip NOTIFY msg after receiving of subsequent subscribe msg.
    - Added a new parameter in event_reg(), create_notifications() and
      notify_subscribers() methods: c_passed contact - used to mainly in
      create_notification().
    - Changes in create_notification() - the checks for sending NOTIFY
      msgs have been expanded and the new parameter c_passed is used for
      that.
    - Changes in subscribe_to_reg() - sending NOTIFY only for the
      initial subscriptions.
    - Changes in generate_reginfo_full() - the old functionality with
      all contacts in NOTIFY msg has been returned based on RFC3680. Added
      mechanism to change all contact states from
      CONTACT_EXPIRE_PENDING_NOTIFY to CONTACT_NOTIFY_READY after reginfo
      generation.

src/modules/ims_registrar_scscf/cxdx_callbacks.c
src/modules/ims_registrar_scscf/reg_rpc.c
src/modules/ims_registrar_scscf/registrar_notify.c
src/modules/ims_registrar_scscf/registrar_notify.h
src/modules/ims_registrar_scscf/save.c
src/modules/ims_registrar_scscf/usrloc_cb.c

index 98aed40..ca601bd 100644 (file)
@@ -93,7 +93,7 @@ AAAMessage* cxdx_process_rtr(AAAMessage *rtr) {
                        impucontact->contact->state = CONTACT_DELETE_PENDING;
                        if (r->shead) {
                                //send NOTIFY to all subscribers of this IMPU.
-                               notify_subscribers(r, 0, 0, IMS_REGISTRAR_CONTACT_UNREGISTERED);
+                               notify_subscribers(r, impucontact->contact, 0, 0, IMS_REGISTRAR_CONTACT_UNREGISTERED);
                        }
                        impucontact->contact->state = CONTACT_DELETED;
                        ul.unlock_contact_slot_i(impucontact->contact->sl);
@@ -122,7 +122,7 @@ AAAMessage* cxdx_process_rtr(AAAMessage *rtr) {
                                impucontact->contact->state = CONTACT_DELETE_PENDING;
                                if (r->shead) {
                                        //send NOTIFY to all subscribers of this IMPU.
-                                       notify_subscribers(r, 0, 0, IMS_REGISTRAR_CONTACT_UNREGISTERED);
+                                       notify_subscribers(r, impucontact->contact, 0, 0, IMS_REGISTRAR_CONTACT_UNREGISTERED);
                                }
                                impucontact->contact->state = CONTACT_DELETED;
                                ul.unlock_contact_slot_i(impucontact->contact->sl);
index a009645..5e5f668 100644 (file)
@@ -66,7 +66,7 @@ static void reg_rpc_dereg_impu(rpc_t* rpc, void* ctx)
                                impucontact->contact->state = CONTACT_DELETE_PENDING;
                                if (impu_rec->shead) {
                                                //send NOTIFY to all subscribers of this IMPU.
-                                               notify_subscribers(impu_rec, 0, 0, IMS_REGISTRAR_CONTACT_UNREGISTERED);
+                                               notify_subscribers(impu_rec, impucontact->contact, 0, 0, IMS_REGISTRAR_CONTACT_UNREGISTERED);
                                }
                                impucontact->contact->state = CONTACT_DELETED;
                                ul.unlock_contact_slot_i(impucontact->contact->sl);
index dfcec90..b2da75a 100644 (file)
@@ -439,7 +439,7 @@ error:
  * called to deliver new event into notification process
  * return 0 on success. anything else failure
  */
-int event_reg(udomain_t* _d, impurecord_t* r_passed, int event_type, str *presentity_uri, str *watcher_contact, str *contact_uri,
+int event_reg(udomain_t* _d, impurecord_t* r_passed, ucontact_t* c_passed, int event_type, str *presentity_uri, str *watcher_contact, str *contact_uri,
                 str *explit_dereg_contact, int num_explit_dereg_contact) {
     impurecord_t* r;
     int num_impus;
@@ -485,7 +485,7 @@ int event_reg(udomain_t* _d, impurecord_t* r_passed, int event_type, str *presen
             ul.unlock_udomain((udomain_t*) _d, presentity_uri);
             LM_DBG("About to create notification\n");
 
-            create_notifications(_d, r_passed, presentity_uri, watcher_contact, contact_uri, impu_list, num_impus, event_type, explit_dereg_contact, num_explit_dereg_contact);
+            create_notifications(_d, r_passed, c_passed, presentity_uri, watcher_contact, contact_uri, impu_list, num_impus, event_type, explit_dereg_contact, num_explit_dereg_contact);
             if (impu_list) {
                     pkg_free(impu_list);
             }
@@ -522,7 +522,7 @@ int event_reg(udomain_t* _d, impurecord_t* r_passed, int event_type, str *presen
                                return 0;
             }
             LM_DBG("About to create notification\n");
-            create_notifications(_d, r_passed, presentity_uri, watcher_contact, contact_uri, impu_list, num_impus, event_type, explit_dereg_contact, num_explit_dereg_contact);
+            create_notifications(_d, r_passed, c_passed, presentity_uri, watcher_contact, contact_uri, impu_list, num_impus, event_type, explit_dereg_contact, num_explit_dereg_contact);
             if (impu_list) {
                     pkg_free(impu_list);
             }
@@ -535,8 +535,8 @@ int event_reg(udomain_t* _d, impurecord_t* r_passed, int event_type, str *presen
     }
 }
 
-int notify_subscribers(impurecord_t* impurecord, str *explit_dereg_contact, int num_explit_dereg_contact, int event_type) {
-    event_reg(0, impurecord, event_type, 0, 0, 0, explit_dereg_contact, num_explit_dereg_contact);
+int notify_subscribers(impurecord_t* impurecord, ucontact_t* contact, str *explit_dereg_contact, int num_explit_dereg_contact, int event_type) {
+    event_reg(0, impurecord, contact, event_type, 0, 0, 0, explit_dereg_contact, num_explit_dereg_contact);
 
     return 0;
 }
@@ -594,7 +594,7 @@ int process_contact(ims_subscription* subscription, udomain_t * _d, int expires,
                         ucontact->state = CONTACT_DELETE_PENDING;
                         if (implicit_impurecord->shead) {
                             //send NOTIFY to all subscribers of this IMPU.
-                            notify_subscribers(implicit_impurecord, 0, 0, IMS_REGISTRAR_CONTACT_UNREGISTERED);
+                            notify_subscribers(implicit_impurecord, ucontact, 0, 0, IMS_REGISTRAR_CONTACT_UNREGISTERED);
                         }
                         ul.unlock_contact_slot(&contact_uri);
                         //                        if (ul.unlink_contact_from_impu(implicit_impurecord, ucontact, 1, 0 /*implicit dereg of contact from IMPU*/) != 0) {
@@ -1071,7 +1071,7 @@ int subscribe_to_reg(struct sip_msg *msg, char *_t, char *str2) {
         LM_DBG("Got to tag from sent response: [%.*s]\n", ttag.len, ttag.s);
         LM_DBG("This is initial subscribe - get presentity URI from req URI\n");
         presentity_uri = cscf_get_public_identity_from_requri(msg);
-
+               event_type = IMS_REGISTRAR_SUBSCRIBE;
     } else {
         LM_DBG("Msg has ttag: [%.*s] - this is subsequent subscribe\n", ttag.len, ttag.s);
         //cscf_get_to_uri(msg, &presentity_uri);
@@ -1085,6 +1085,7 @@ int subscribe_to_reg(struct sip_msg *msg, char *_t, char *str2) {
             ret = CSCF_RETURN_FALSE;
             goto doneorerror;
         }
+               event_type = IMS_REGISTRAR_SUBSEQUENT_SUBSCRIBE;
     }
 
     //get cseq
@@ -1147,7 +1148,6 @@ int subscribe_to_reg(struct sip_msg *msg, char *_t, char *str2) {
 
     if (expires > 0) {
         LM_DBG("expires is more than zero - SUBSCRIBE\n");
-        event_type = IMS_REGISTRAR_SUBSCRIBE;
 
         if (expires < subscription_min_expires) expires = subscription_min_expires;
         if (expires > subscription_max_expires) expires = subscription_max_expires;
@@ -1220,14 +1220,16 @@ int subscribe_to_reg(struct sip_msg *msg, char *_t, char *str2) {
         LM_DBG("Sending 200 OK to subscribing user\n");
         subscribe_reply(msg, 200, MSG_REG_SUBSCRIBE_OK, &expires, &scscf_name_str);
 
-        //do reg event every time you get a subscribe
-        if (event_reg(domain, 0, event_type, &presentity_uri, &watcher_contact, 0, 0, 0) != 0) {
-            LM_ERR("failed adding notification for reg events\n");
-            ret = CSCF_RETURN_ERROR;
-            goto doneorerror;
-        } else {
-            LM_DBG("success adding notification for reg events\n");
-        }
+               if(event_type == IMS_REGISTRAR_SUBSCRIBE) {
+                       //do reg event only for the initial subscribe
+                       if (event_reg(domain, 0, 0, event_type, &presentity_uri, &watcher_contact, 0, 0, 0) != 0) {
+                               LM_ERR("failed adding notification for reg events\n");
+                               ret = CSCF_RETURN_ERROR;
+                               goto doneorerror;
+                       } else {
+                               LM_DBG("success adding notification for reg events\n");
+                       }
+               }
     } else {
         event_type = IMS_REGISTRAR_UNSUBSCRIBE;
         LM_DBG("expires is zero or less - UNSUBSCRIBE\n");
@@ -1467,7 +1469,7 @@ static str subs_active = {"active;expires=", 15};
  * @param content - the body content
  * @param expires - the remaining subcription expiration time in seconds
  */
-void create_notifications(udomain_t* _t, impurecord_t* r_passed, str *presentity_uri, str *watcher_contact, str *contact_uri,
+void create_notifications(udomain_t* _t, impurecord_t* r_passed, ucontact_t* c_passed, str *presentity_uri, str *watcher_contact, str *contact_uri,
                             str* impus, int num_impus, int event_type, str *explit_dereg_contact, int num_explit_dereg_contact) {
 
     reg_notification *n;
@@ -1534,26 +1536,34 @@ void create_notifications(udomain_t* _t, impurecord_t* r_passed, str *presentity
                 LM_DBG("This is a fix to ensure that we only send full reg info XML to the UE that just subscribed.\n");
                 create_notification = 1;
             }
-        } else {
-            if (event_type == IMS_REGISTRAR_CONTACT_REGISTERED) {
-                if(contact_match(contact_uri, &s->watcher_contact) &&
-                    (r_passed->public_identity.len == s->presentity_uri.len) && (memcmp(s->presentity_uri.s, r_passed->public_identity.s, r_passed->public_identity.len) == 0)) {
-                    LM_DBG("This is a fix to ensure that we only send full reg info XML to the UE that just subscribed.\n");
-                    create_notification = 1;
-                }
-            } else {
-            //TODO: we must make this optimisation to not send NOTIFYs back to UE's *(they may have disappeared)
-            //            if (event_type == IMS_REGISTRAR_CONTACT_UNREGISTERED && !ue_unsubscribe_on_dereg /*&&
-            //                    (contact_port_ip_match(&c_passed->c, &s->watcher_contact) */
-            //                    && (r_passed->public_identity.len == s->presentity_uri.len) && (memcmp(s->presentity_uri.s, r_passed->public_identity.s, r_passed->public_identity.len) == 0)) {
-            //                //if this is UNREGISTER and the UEs do not unsubscribe to dereg and this is a UE subscribing to its own reg event
-            //                //then we do not send notifications
-            //                LM_DBG("This is a UNREGISTER event for a UE that subscribed to its own state that does not unsubscribe to dereg - therefore no notification");
-            //            } else {
-            //            }
+        } else if (event_type == IMS_REGISTRAR_CONTACT_REGISTERED || event_type == IMS_REGISTRAR_CONTACT_REFRESHED) {
+                       if(contact_match(contact_uri, &s->watcher_contact) &&
+                               (r_passed->public_identity.len == s->presentity_uri.len) && (memcmp(s->presentity_uri.s, r_passed->public_identity.s, r_passed->public_identity.len) == 0)) {
+                               LM_DBG("This is a fix to ensure that we only send full reg info XML to the UE that just registered.\n");
                                create_notification = 1;
                        }
-        }
+               } else if (event_type == IMS_REGISTRAR_CONTACT_EXPIRED || event_type == IMS_REGISTRAR_CONTACT_UNREGISTERED) {
+                       if(!ue_unsubscribe_on_dereg &&
+                               contact_port_ip_match(&c_passed->c, &s->watcher_contact) && alias_port_ip_match(&c_passed->c, &s->watcher_contact) &&
+                               r_passed->public_identity.len == s->presentity_uri.len &&
+                               memcmp(s->presentity_uri.s, r_passed->public_identity.s, r_passed->public_identity.len) == 0) {
+                               LM_DBG("This is a UNREGISTER/EXPIRE event for a UE that subscribed to its own state that does not unsubscribe to dereg - therefore no notification\n");
+
+                               if(r->linked_contacts.numcontacts < 2) {
+                                       // marking the contact as Notify ready if there aren't other linked contacts to the current impu record
+                                       ul.lock_contact_slot_i(c_passed->sl);
+                                       if(c_passed->state == CONTACT_EXPIRE_PENDING_NOTIFY) {
+                                               LM_DBG("Setting contact state from CONTACT_EXPIRE_PENDING_NOTIFY to CONTACT_NOTIFY_READY for contact [%.*s]\n", c_passed->c.len, c_passed->c.s);
+                                               c_passed->state = CONTACT_NOTIFY_READY;
+                                       }
+                                       ul.unlock_contact_slot_i(c_passed->sl);
+                               }
+                       } else {
+                               create_notification = 1;
+                       }
+               } else {
+                       create_notification = 1;
+               }
 
         if(create_notification) {
             LM_DBG("About to make new notification! We always increment the local cseq and version before we send a new notification\n");
@@ -1750,7 +1760,7 @@ str generate_reginfo_full(udomain_t* _t, str* impu_list, int num_impus, str *exp
     str buf, pad;
     char bufc[MAX_REGINFO_SIZE], padc[MAX_REGINFO_SIZE];
     impurecord_t *r;
-    int i, k, res, added_contacts;
+    int i, k, res;
     ucontact_t* ptr;
 
     buf.s = bufc;
@@ -1762,6 +1772,10 @@ str generate_reginfo_full(udomain_t* _t, str* impu_list, int num_impus, str *exp
     int terminate_impu = 1;
        impu_contact_t *impucontact;
 
+       unsigned int num_pending_notify_contacts = 0;
+       unsigned int max_num_pending_notify_contacts = 0;
+       ucontact_t** pending_notify_contacts = 0;
+
     LM_DBG("Getting reginfo_full\n");
 
     STR_APPEND(buf, xml_start);
@@ -1769,6 +1783,28 @@ str generate_reginfo_full(udomain_t* _t, str* impu_list, int num_impus, str *exp
     pad.len = strlen(pad.s);
     STR_APPEND(buf, pad);
 
+       // reserve memory for all contacts for all impus
+       for (i = 0; i < num_impus; i++) {
+               ul.lock_udomain(_t, &impu_list[i]);
+
+               res = ul.get_impurecord(_t, (&impu_list[i]), &r);
+               if (res != 0) {
+                       LM_DBG("impu disappeared, ignoring it\n");
+                       ul.unlock_udomain(_t, &impu_list[i]);
+                       continue;
+               }
+
+               max_num_pending_notify_contacts += r->linked_contacts.numcontacts;
+
+               ul.unlock_udomain(_t, &impu_list[i]);
+       }
+
+       pending_notify_contacts = (ucontact_t**)pkg_malloc(max_num_pending_notify_contacts*sizeof(ucontact_t**));
+       if (!pending_notify_contacts) {
+               LM_WARN("no more pkg mem trying to allocate [%lu] bytes\n", max_num_pending_notify_contacts*sizeof(ucontact_t**));
+               max_num_pending_notify_contacts = 0;
+       }
+
     for (i = 0; i < num_impus; i++) {
         LM_DBG("Scrolling through public identities, current one <%.*s>\n", impu_list[i].len, impu_list[i].s);
         //        if (primary_locked && strncasecmp(impu_list[i].s, primary_impu->s, impu_list[i].len) == 0) {
@@ -1834,31 +1870,20 @@ str generate_reginfo_full(udomain_t* _t, str* impu_list, int num_impus, str *exp
         }
 
                impucontact = r->linked_contacts.head;
-               added_contacts = 0;
                while (impucontact) {
                        ptr = impucontact->contact;
 
-                       // Prevent multiple contacts in Notify message body <registration> tags
-                       // 1. Compare contact->contact IP and PORT with subscriber->watcher_contact IP and PORT
-                       // 2. Compare contact->contact alias IP and PORT with subscriber->watcher_contact alias IP and PORT without PROTO
-                       // This is because of IPv6 and IPv4 family
-                       // When we have a case like: UE <--IPv6--> P-CSCF <--IPv4--> S-CSCF
-                       // Then scscf contact->contact alias proto is 2(IPv6) but scscf subscriber->watcher_contact alias proto is 1(IPv4)
-                       if(contact_port_ip_match(&ptr->c, watcher_contact) && alias_port_ip_match(&ptr->c, watcher_contact)){
-                               process_xml_for_contact(&buf, &pad, ptr);
-                               ++added_contacts;
-                       }
-                       impucontact = impucontact->next;
-               }
+                       ul.lock_contact_slot_i(ptr->sl);
 
-               // For pcscf or other AS subscriptions add all contacts
-               if(added_contacts == 0) {
-                       impucontact = r->linked_contacts.head;
-                       while (impucontact) {
-                               ptr = impucontact->contact;
-                               process_xml_for_contact(&buf, &pad, ptr);
-                               impucontact = impucontact->next;
+                       process_xml_for_contact(&buf, &pad, ptr);
+
+                       if (ptr->state == CONTACT_EXPIRE_PENDING_NOTIFY && num_pending_notify_contacts < max_num_pending_notify_contacts) {
+                               pending_notify_contacts[num_pending_notify_contacts++] = ptr;
                        }
+
+                       ul.unlock_contact_slot_i(ptr->sl);
+
+                       impucontact = impucontact->next;
                }
 
         STR_APPEND(buf, registration_e);
@@ -1868,6 +1893,23 @@ str generate_reginfo_full(udomain_t* _t, str* impu_list, int num_impus, str *exp
         //        }
     }
 
+       // set all expire pending notify contacts to notify ready state
+       for (i = 0; i < num_pending_notify_contacts; ++i) {
+               ptr = pending_notify_contacts[i];
+               ul.lock_contact_slot_i(ptr->sl);
+
+               if(ptr->state == CONTACT_EXPIRE_PENDING_NOTIFY) {
+                       LM_DBG("Setting contact state from CONTACT_EXPIRE_PENDING_NOTIFY to CONTACT_NOTIFY_READY for contact [%.*s]\n", ptr->c.len, ptr->c.s);
+                       ptr->state = CONTACT_NOTIFY_READY;
+               }
+
+               ul.unlock_contact_slot_i(ptr->sl);
+       }
+
+       if (pending_notify_contacts){
+               pkg_free(pending_notify_contacts);
+       }
+
     STR_APPEND(buf, r_reginfo_e);
 
     x.s = pkg_malloc(buf.len + 1);
index eb1e759..6bfc6d3 100644 (file)
@@ -79,7 +79,7 @@ typedef struct _reg_notification {
     
     str *explit_dereg_contact;
     int num_explit_dereg_contact;
-    
+
     struct _reg_notification *next; /**< next notification in the list */
     struct _reg_notification *prev; /**< previous notification in the list     */
 } reg_notification;
@@ -116,6 +116,7 @@ typedef enum {
     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_SUBSEQUENT_SUBSCRIBE
 } IMS_Registrar_events_enum_t;
 
 extern IMS_Registrar_events_enum_t IMS_Registrar_events;
@@ -132,7 +133,7 @@ int publish_reg(struct sip_msg *msg, char *str1, char *str2);
 
 int subscribe_reply(struct sip_msg *msg, int code, char *text, int *expires, str *contact);
 
-int event_reg(udomain_t* _d, impurecord_t* r_passed, int event_type, str *presentity_uri, str *watcher_contact, str *contact_uri,
+int event_reg(udomain_t* _d, impurecord_t* r_passed, ucontact_t* c_passed, int event_type, str *presentity_uri, str *watcher_contact, str *contact_uri,
                 str *explit_dereg_contact, int num_explit_dereg_contact);
 
 
@@ -140,7 +141,7 @@ str generate_reginfo_full(udomain_t* _t, str* impu_list, int new_subscription, s
 
 str get_reginfo_partial(impurecord_t *r, ucontact_t *c, int event_type, unsigned int reginfo_version);
 
-void create_notifications(udomain_t* _t, impurecord_t* r_passed, str *presentity_uri, str *watcher_contact, str *contact_uri,
+void create_notifications(udomain_t* _t, impurecord_t* r_passed, ucontact_t* c_passed, str *presentity_uri, str *watcher_contact, str *contact_uri,
                             str* impus, int num_impus, int event_type, str *explit_dereg_contact, int num_explit_dereg_contact);
 
 void notification_event_process();
@@ -163,6 +164,6 @@ void notify_destroy();
 int aor_to_contact(str* aor, str* contact);
 int contact_port_ip_match(str *c1, str *c2);
 
-int notify_subscribers(impurecord_t* impurecord, str *explit_dereg_contact, int num_explit_dereg_contact, int event_type);
+int notify_subscribers(impurecord_t* impurecord, ucontact_t* contact, str *explit_dereg_contact, int num_explit_dereg_contact, int event_type);
 
 #endif //S_CSCF_REGISTRAR_NOTIFY_H_
index 9f7dac9..877d507 100644 (file)
@@ -777,6 +777,9 @@ int update_contacts(struct sip_msg* msg, udomain_t* _d,
     int first_unbarred_impu = 1; //this is used to flag the IMPU as anchor for implicit set
     int is_primary_impu = 0;
     int ret = 1;
+       str callid = {0, 0};
+       str path = {0, 0};
+       ucontact_t* ucontact;
 
     int num_explicit_dereg_contact = 0;
     str *explicit_dereg_contact = 0;
@@ -835,7 +838,12 @@ int update_contacts(struct sip_msg* msg, udomain_t* _d,
             for (h = msg->contact; h; h = h->next) {
                 if (h->type == HDR_CONTACT_T && h->parsed) {
                     for (chi = ((contact_body_t*) h->parsed)->contacts; chi; chi = chi->next) {
-                        event_reg(0, impu_rec, IMS_REGISTRAR_CONTACT_REGISTERED, 0, 0, &chi->uri, 0, 0);
+                                               if (ul.get_ucontact(&chi->uri, &callid, &path, 0, &ucontact) != 0) {
+                                                       LM_DBG("Contact does not exist <%.*s>\n", chi->uri.len, chi->uri.s);
+                                                       goto error;
+                                               }
+                        event_reg(0, impu_rec, ucontact, IMS_REGISTRAR_CONTACT_REGISTERED, 0, 0, &chi->uri, 0, 0);
+                                               ul.release_ucontact(ucontact);
                     }
                 }
             }
@@ -927,7 +935,12 @@ int update_contacts(struct sip_msg* msg, udomain_t* _d,
             for (h = msg->contact; h; h = h->next) {
                 if (h->type == HDR_CONTACT_T && h->parsed) {
                     for (chi = ((contact_body_t*) h->parsed)->contacts; chi; chi = chi->next) {
-                        event_reg(0, impu_rec, IMS_REGISTRAR_CONTACT_REGISTERED, 0, 0, &chi->uri, 0, 0);
+                                               if (ul.get_ucontact(&chi->uri, &callid, &path, 0, &ucontact) != 0) {
+                                                       LM_DBG("Contact does not exist <%.*s>\n", chi->uri.len, chi->uri.s);
+                                                       goto error;
+                                               }
+                        event_reg(0, impu_rec, ucontact, IMS_REGISTRAR_CONTACT_REFRESHED, 0, 0, &chi->uri, 0, 0);
+                                               ul.release_ucontact(ucontact);
                     }
                 }
             }
@@ -1029,11 +1042,17 @@ int update_contacts(struct sip_msg* msg, udomain_t* _d,
                         //                                s = s->next;
                         //                            }
                         //                        }
-                        notify_subscribers(tmp_impu_rec, (str*) explicit_dereg_contact, num_explicit_dereg_contact, IMS_REGISTRAR_CONTACT_UNREGISTERED);
 
                         for (h = msg->contact; h; h = h->next) {
                             if (h->type == HDR_CONTACT_T && h->parsed) {
                                 for (chi = ((contact_body_t*) h->parsed)->contacts; chi; chi = chi->next) {
+                                                                       if (ul.get_ucontact(&chi->uri, &callid, &path, 0, &ucontact) != 0) {
+                                                                               LM_DBG("Contact does not exist <%.*s>\n", chi->uri.len, chi->uri.s);
+                                                                               goto error;
+                                                                       }
+                                                                       notify_subscribers(tmp_impu_rec, ucontact, (str*) explicit_dereg_contact, num_explicit_dereg_contact, IMS_REGISTRAR_CONTACT_UNREGISTERED);
+                                                                       ul.release_ucontact(ucontact);
+
                                     if (calc_contact_q(chi->q, &qvalue) != 0) {
                                         LM_ERR("error on <%.*s>\n", chi->uri.len, chi->uri.s);
                                         ul.unlock_udomain(_d, &pi->public_identity);
index 13dcde5..d560704 100644 (file)
@@ -94,6 +94,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\n");
-        event_reg(0, r, IMS_REGISTRAR_CONTACT_UNREGISTERED, 0, 0, 0, 0, 0);
+        event_reg(0, r, c, IMS_REGISTRAR_CONTACT_UNREGISTERED, 0, 0, 0, 0, 0);
+    } else if (type == UL_IMPU_EXPIRE_CONTACT) {
+        LM_DBG("Received notification of UL CONTACT EXPIRED\n");
+        event_reg(0, r, c, IMS_REGISTRAR_CONTACT_EXPIRED, 0, 0, 0, 0, 0);
     }
 }