Browse code

ims_registrar_scscf: added a new registrar event, notification improvements

- 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.

Aleksandar Yosifov authored on 17/07/2020 07:45:00 • Henning Westerholt committed on 21/07/2020 20:07:30
Showing 6 changed files
... ...
@@ -93,7 +93,7 @@ AAAMessage* cxdx_process_rtr(AAAMessage *rtr) {
93 93
 			impucontact->contact->state = CONTACT_DELETE_PENDING;
94 94
 			if (r->shead) {
95 95
 				//send NOTIFY to all subscribers of this IMPU.
96
-				notify_subscribers(r, 0, 0, IMS_REGISTRAR_CONTACT_UNREGISTERED);
96
+				notify_subscribers(r, impucontact->contact, 0, 0, IMS_REGISTRAR_CONTACT_UNREGISTERED);
97 97
 			}
98 98
 			impucontact->contact->state = CONTACT_DELETED;
99 99
 			ul.unlock_contact_slot_i(impucontact->contact->sl);
... ...
@@ -122,7 +122,7 @@ AAAMessage* cxdx_process_rtr(AAAMessage *rtr) {
122 122
 				impucontact->contact->state = CONTACT_DELETE_PENDING;
123 123
 				if (r->shead) {
124 124
 					//send NOTIFY to all subscribers of this IMPU.
125
-					notify_subscribers(r, 0, 0, IMS_REGISTRAR_CONTACT_UNREGISTERED);
125
+					notify_subscribers(r, impucontact->contact, 0, 0, IMS_REGISTRAR_CONTACT_UNREGISTERED);
126 126
 				}
127 127
 				impucontact->contact->state = CONTACT_DELETED;
128 128
 				ul.unlock_contact_slot_i(impucontact->contact->sl);
... ...
@@ -66,7 +66,7 @@ static void reg_rpc_dereg_impu(rpc_t* rpc, void* ctx)
66 66
 				impucontact->contact->state = CONTACT_DELETE_PENDING;
67 67
 				if (impu_rec->shead) {
68 68
 						//send NOTIFY to all subscribers of this IMPU.
69
-						notify_subscribers(impu_rec, 0, 0, IMS_REGISTRAR_CONTACT_UNREGISTERED);
69
+						notify_subscribers(impu_rec, impucontact->contact, 0, 0, IMS_REGISTRAR_CONTACT_UNREGISTERED);
70 70
 				}
71 71
 				impucontact->contact->state = CONTACT_DELETED;
72 72
 				ul.unlock_contact_slot_i(impucontact->contact->sl);
... ...
@@ -439,7 +439,7 @@ error:
439 439
  * called to deliver new event into notification process
440 440
  * return 0 on success. anything else failure
441 441
  */
442
-int event_reg(udomain_t* _d, impurecord_t* r_passed, int event_type, str *presentity_uri, str *watcher_contact, str *contact_uri,
442
+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,
443 443
                 str *explit_dereg_contact, int num_explit_dereg_contact) {
444 444
     impurecord_t* r;
445 445
     int num_impus;
... ...
@@ -485,7 +485,7 @@ int event_reg(udomain_t* _d, impurecord_t* r_passed, int event_type, str *presen
485 485
             ul.unlock_udomain((udomain_t*) _d, presentity_uri);
486 486
             LM_DBG("About to create notification\n");
487 487
 
488
-            create_notifications(_d, r_passed, presentity_uri, watcher_contact, contact_uri, impu_list, num_impus, event_type, explit_dereg_contact, num_explit_dereg_contact);
488
+            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);
489 489
             if (impu_list) {
490 490
                     pkg_free(impu_list);
491 491
             }
... ...
@@ -522,7 +522,7 @@ int event_reg(udomain_t* _d, impurecord_t* r_passed, int event_type, str *presen
522 522
 				return 0;
523 523
             }
524 524
             LM_DBG("About to create notification\n");
525
-            create_notifications(_d, r_passed, presentity_uri, watcher_contact, contact_uri, impu_list, num_impus, event_type, explit_dereg_contact, num_explit_dereg_contact);
525
+            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);
526 526
             if (impu_list) {
527 527
                     pkg_free(impu_list);
528 528
             }
... ...
@@ -535,8 +535,8 @@ int event_reg(udomain_t* _d, impurecord_t* r_passed, int event_type, str *presen
535 535
     }
536 536
 }
537 537
 
538
-int notify_subscribers(impurecord_t* impurecord, str *explit_dereg_contact, int num_explit_dereg_contact, int event_type) {
539
-    event_reg(0, impurecord, event_type, 0, 0, 0, explit_dereg_contact, num_explit_dereg_contact);
538
+int notify_subscribers(impurecord_t* impurecord, ucontact_t* contact, str *explit_dereg_contact, int num_explit_dereg_contact, int event_type) {
539
+    event_reg(0, impurecord, contact, event_type, 0, 0, 0, explit_dereg_contact, num_explit_dereg_contact);
540 540
 
541 541
     return 0;
542 542
 }
... ...
@@ -594,7 +594,7 @@ int process_contact(ims_subscription* subscription, udomain_t * _d, int expires,
594 594
                         ucontact->state = CONTACT_DELETE_PENDING;
595 595
                         if (implicit_impurecord->shead) {
596 596
                             //send NOTIFY to all subscribers of this IMPU.
597
-                            notify_subscribers(implicit_impurecord, 0, 0, IMS_REGISTRAR_CONTACT_UNREGISTERED);
597
+                            notify_subscribers(implicit_impurecord, ucontact, 0, 0, IMS_REGISTRAR_CONTACT_UNREGISTERED);
598 598
                         }
599 599
                         ul.unlock_contact_slot(&contact_uri);
600 600
                         //                        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) {
1071 1071
         LM_DBG("Got to tag from sent response: [%.*s]\n", ttag.len, ttag.s);
1072 1072
         LM_DBG("This is initial subscribe - get presentity URI from req URI\n");
1073 1073
         presentity_uri = cscf_get_public_identity_from_requri(msg);
1074
-
1074
+		event_type = IMS_REGISTRAR_SUBSCRIBE;
1075 1075
     } else {
1076 1076
         LM_DBG("Msg has ttag: [%.*s] - this is subsequent subscribe\n", ttag.len, ttag.s);
1077 1077
         //cscf_get_to_uri(msg, &presentity_uri);
... ...
@@ -1085,6 +1085,7 @@ int subscribe_to_reg(struct sip_msg *msg, char *_t, char *str2) {
1085 1085
             ret = CSCF_RETURN_FALSE;
1086 1086
             goto doneorerror;
1087 1087
         }
1088
+		event_type = IMS_REGISTRAR_SUBSEQUENT_SUBSCRIBE;
1088 1089
     }
1089 1090
 
1090 1091
     //get cseq
... ...
@@ -1147,7 +1148,6 @@ int subscribe_to_reg(struct sip_msg *msg, char *_t, char *str2) {
1147 1148
 
1148 1149
     if (expires > 0) {
1149 1150
         LM_DBG("expires is more than zero - SUBSCRIBE\n");
1150
-        event_type = IMS_REGISTRAR_SUBSCRIBE;
1151 1151
 
1152 1152
         if (expires < subscription_min_expires) expires = subscription_min_expires;
1153 1153
         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) {
1220 1220
         LM_DBG("Sending 200 OK to subscribing user\n");
1221 1221
         subscribe_reply(msg, 200, MSG_REG_SUBSCRIBE_OK, &expires, &scscf_name_str);
1222 1222
 
1223
-        //do reg event every time you get a subscribe
1224
-        if (event_reg(domain, 0, event_type, &presentity_uri, &watcher_contact, 0, 0, 0) != 0) {
1225
-            LM_ERR("failed adding notification for reg events\n");
1226
-            ret = CSCF_RETURN_ERROR;
1227
-            goto doneorerror;
1228
-        } else {
1229
-            LM_DBG("success adding notification for reg events\n");
1230
-        }
1223
+		if(event_type == IMS_REGISTRAR_SUBSCRIBE) {
1224
+			//do reg event only for the initial subscribe
1225
+			if (event_reg(domain, 0, 0, event_type, &presentity_uri, &watcher_contact, 0, 0, 0) != 0) {
1226
+				LM_ERR("failed adding notification for reg events\n");
1227
+				ret = CSCF_RETURN_ERROR;
1228
+				goto doneorerror;
1229
+			} else {
1230
+				LM_DBG("success adding notification for reg events\n");
1231
+			}
1232
+		}
1231 1233
     } else {
1232 1234
         event_type = IMS_REGISTRAR_UNSUBSCRIBE;
1233 1235
         LM_DBG("expires is zero or less - UNSUBSCRIBE\n");
... ...
@@ -1467,7 +1469,7 @@ static str subs_active = {"active;expires=", 15};
1467 1469
  * @param content - the body content
1468 1470
  * @param expires - the remaining subcription expiration time in seconds
1469 1471
  */
1470
-void create_notifications(udomain_t* _t, impurecord_t* r_passed, str *presentity_uri, str *watcher_contact, str *contact_uri,
1472
+void create_notifications(udomain_t* _t, impurecord_t* r_passed, ucontact_t* c_passed, str *presentity_uri, str *watcher_contact, str *contact_uri,
1471 1473
                             str* impus, int num_impus, int event_type, str *explit_dereg_contact, int num_explit_dereg_contact) {
1472 1474
 
1473 1475
     reg_notification *n;
... ...
@@ -1534,26 +1536,34 @@ void create_notifications(udomain_t* _t, impurecord_t* r_passed, str *presentity
1534 1536
                 LM_DBG("This is a fix to ensure that we only send full reg info XML to the UE that just subscribed.\n");
1535 1537
                 create_notification = 1;
1536 1538
             }
1537
-        } else {
1538
-            if (event_type == IMS_REGISTRAR_CONTACT_REGISTERED) {
1539
-                if(contact_match(contact_uri, &s->watcher_contact) &&
1540
-                    (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)) {
1541
-                    LM_DBG("This is a fix to ensure that we only send full reg info XML to the UE that just subscribed.\n");
1542
-                    create_notification = 1;
1543
-                }
1544
-            } else {
1545
-            //TODO: we must make this optimisation to not send NOTIFYs back to UE's *(they may have disappeared)
1546
-            //            if (event_type == IMS_REGISTRAR_CONTACT_UNREGISTERED && !ue_unsubscribe_on_dereg /*&&
1547
-            //                    (contact_port_ip_match(&c_passed->c, &s->watcher_contact) */
1548
-            //                    && (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)) {
1549
-            //                //if this is UNREGISTER and the UEs do not unsubscribe to dereg and this is a UE subscribing to its own reg event
1550
-            //                //then we do not send notifications
1551
-            //                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");
1552
-            //            } else {
1553
-            //            }
1539
+        } else if (event_type == IMS_REGISTRAR_CONTACT_REGISTERED || event_type == IMS_REGISTRAR_CONTACT_REFRESHED) {
1540
+			if(contact_match(contact_uri, &s->watcher_contact) &&
1541
+				(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)) {
1542
+				LM_DBG("This is a fix to ensure that we only send full reg info XML to the UE that just registered.\n");
1554 1543
 				create_notification = 1;
1555 1544
 			}
1556
-        }
1545
+		} else if (event_type == IMS_REGISTRAR_CONTACT_EXPIRED || event_type == IMS_REGISTRAR_CONTACT_UNREGISTERED) {
1546
+			if(!ue_unsubscribe_on_dereg &&
1547
+				contact_port_ip_match(&c_passed->c, &s->watcher_contact) && alias_port_ip_match(&c_passed->c, &s->watcher_contact) &&
1548
+				r_passed->public_identity.len == s->presentity_uri.len &&
1549
+				memcmp(s->presentity_uri.s, r_passed->public_identity.s, r_passed->public_identity.len) == 0) {
1550
+				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");
1551
+
1552
+				if(r->linked_contacts.numcontacts < 2) {
1553
+					// marking the contact as Notify ready if there aren't other linked contacts to the current impu record
1554
+					ul.lock_contact_slot_i(c_passed->sl);
1555
+					if(c_passed->state == CONTACT_EXPIRE_PENDING_NOTIFY) {
1556
+						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);
1557
+						c_passed->state = CONTACT_NOTIFY_READY;
1558
+					}
1559
+					ul.unlock_contact_slot_i(c_passed->sl);
1560
+				}
1561
+			} else {
1562
+				create_notification = 1;
1563
+			}
1564
+		} else {
1565
+			create_notification = 1;
1566
+		}
1557 1567
 
1558 1568
         if(create_notification) {
1559 1569
             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
1750 1760
     str buf, pad;
1751 1761
     char bufc[MAX_REGINFO_SIZE], padc[MAX_REGINFO_SIZE];
1752 1762
     impurecord_t *r;
1753
-    int i, k, res, added_contacts;
1763
+    int i, k, res;
1754 1764
     ucontact_t* ptr;
1755 1765
 
1756 1766
     buf.s = bufc;
... ...
@@ -1762,6 +1772,10 @@ str generate_reginfo_full(udomain_t* _t, str* impu_list, int num_impus, str *exp
1762 1772
     int terminate_impu = 1;
1763 1773
 	impu_contact_t *impucontact;
1764 1774
 
1775
+	unsigned int num_pending_notify_contacts = 0;
1776
+	unsigned int max_num_pending_notify_contacts = 0;
1777
+	ucontact_t** pending_notify_contacts = 0;
1778
+
1765 1779
     LM_DBG("Getting reginfo_full\n");
1766 1780
 
1767 1781
     STR_APPEND(buf, xml_start);
... ...
@@ -1769,6 +1783,28 @@ str generate_reginfo_full(udomain_t* _t, str* impu_list, int num_impus, str *exp
1769 1783
     pad.len = strlen(pad.s);
1770 1784
     STR_APPEND(buf, pad);
1771 1785
 
1786
+	// reserve memory for all contacts for all impus
1787
+	for (i = 0; i < num_impus; i++) {
1788
+		ul.lock_udomain(_t, &impu_list[i]);
1789
+
1790
+		res = ul.get_impurecord(_t, (&impu_list[i]), &r);
1791
+		if (res != 0) {
1792
+			LM_DBG("impu disappeared, ignoring it\n");
1793
+			ul.unlock_udomain(_t, &impu_list[i]);
1794
+			continue;
1795
+		}
1796
+
1797
+		max_num_pending_notify_contacts += r->linked_contacts.numcontacts;
1798
+
1799
+		ul.unlock_udomain(_t, &impu_list[i]);
1800
+	}
1801
+
1802
+	pending_notify_contacts = (ucontact_t**)pkg_malloc(max_num_pending_notify_contacts*sizeof(ucontact_t**));
1803
+	if (!pending_notify_contacts) {
1804
+		LM_WARN("no more pkg mem trying to allocate [%lu] bytes\n", max_num_pending_notify_contacts*sizeof(ucontact_t**));
1805
+		max_num_pending_notify_contacts = 0;
1806
+	}
1807
+
1772 1808
     for (i = 0; i < num_impus; i++) {
1773 1809
         LM_DBG("Scrolling through public identities, current one <%.*s>\n", impu_list[i].len, impu_list[i].s);
1774 1810
         //        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
1834 1870
         }
1835 1871
 
1836 1872
 		impucontact = r->linked_contacts.head;
1837
-		added_contacts = 0;
1838 1873
 		while (impucontact) {
1839 1874
 			ptr = impucontact->contact;
1840 1875
 
1841
-			// Prevent multiple contacts in Notify message body <registration> tags
1842
-			// 1. Compare contact->contact IP and PORT with subscriber->watcher_contact IP and PORT
1843
-			// 2. Compare contact->contact alias IP and PORT with subscriber->watcher_contact alias IP and PORT without PROTO
1844
-			// This is because of IPv6 and IPv4 family
1845
-			// When we have a case like: UE <--IPv6--> P-CSCF <--IPv4--> S-CSCF
1846
-			// Then scscf contact->contact alias proto is 2(IPv6) but scscf subscriber->watcher_contact alias proto is 1(IPv4)
1847
-			if(contact_port_ip_match(&ptr->c, watcher_contact) && alias_port_ip_match(&ptr->c, watcher_contact)){
1848
-				process_xml_for_contact(&buf, &pad, ptr);
1849
-				++added_contacts;
1850
-			}
1851
-			impucontact = impucontact->next;
1852
-		}
1876
+			ul.lock_contact_slot_i(ptr->sl);
1853 1877
 
1854
-		// For pcscf or other AS subscriptions add all contacts
1855
-		if(added_contacts == 0) {
1856
-			impucontact = r->linked_contacts.head;
1857
-			while (impucontact) {
1858
-				ptr = impucontact->contact;
1859
-				process_xml_for_contact(&buf, &pad, ptr);
1860
-				impucontact = impucontact->next;
1878
+			process_xml_for_contact(&buf, &pad, ptr);
1879
+
1880
+			if (ptr->state == CONTACT_EXPIRE_PENDING_NOTIFY && num_pending_notify_contacts < max_num_pending_notify_contacts) {
1881
+				pending_notify_contacts[num_pending_notify_contacts++] = ptr;
1861 1882
 			}
1883
+
1884
+			ul.unlock_contact_slot_i(ptr->sl);
1885
+
1886
+			impucontact = impucontact->next;
1862 1887
 		}
1863 1888
 
1864 1889
         STR_APPEND(buf, registration_e);
... ...
@@ -1868,6 +1893,23 @@ str generate_reginfo_full(udomain_t* _t, str* impu_list, int num_impus, str *exp
1868 1893
         //        }
1869 1894
     }
1870 1895
 
1896
+	// set all expire pending notify contacts to notify ready state
1897
+	for (i = 0; i < num_pending_notify_contacts; ++i) {
1898
+		ptr = pending_notify_contacts[i];
1899
+		ul.lock_contact_slot_i(ptr->sl);
1900
+
1901
+		if(ptr->state == CONTACT_EXPIRE_PENDING_NOTIFY) {
1902
+			LM_DBG("Setting contact state from CONTACT_EXPIRE_PENDING_NOTIFY to CONTACT_NOTIFY_READY for contact [%.*s]\n", ptr->c.len, ptr->c.s);
1903
+			ptr->state = CONTACT_NOTIFY_READY;
1904
+		}
1905
+
1906
+		ul.unlock_contact_slot_i(ptr->sl);
1907
+	}
1908
+
1909
+	if (pending_notify_contacts){
1910
+		pkg_free(pending_notify_contacts);
1911
+	}
1912
+
1871 1913
     STR_APPEND(buf, r_reginfo_e);
1872 1914
 
1873 1915
     x.s = pkg_malloc(buf.len + 1);
... ...
@@ -79,7 +79,7 @@ typedef struct _reg_notification {
79 79
     
80 80
     str *explit_dereg_contact;
81 81
     int num_explit_dereg_contact;
82
-    
82
+
83 83
     struct _reg_notification *next; /**< next notification in the list	*/
84 84
     struct _reg_notification *prev; /**< previous notification in the list	*/
85 85
 } reg_notification;
... ...
@@ -116,6 +116,7 @@ typedef enum {
116 116
     IMS_REGISTRAR_CONTACT_EXPIRED, /**< A contact has expired and will be removed		*/
117 117
     IMS_REGISTRAR_CONTACT_UNREGISTERED, /**< User unregistered with Expires 0				*/
118 118
     IMS_REGISTRAR_CONTACT_UNREGISTERED_IMPLICIT, /**< User unregistered implicitly, ie not via explicit deregister	*/
119
+	IMS_REGISTRAR_SUBSEQUENT_SUBSCRIBE
119 120
 } IMS_Registrar_events_enum_t;
120 121
 
121 122
 extern IMS_Registrar_events_enum_t IMS_Registrar_events;
... ...
@@ -132,7 +133,7 @@ int publish_reg(struct sip_msg *msg, char *str1, char *str2);
132 133
 
133 134
 int subscribe_reply(struct sip_msg *msg, int code, char *text, int *expires, str *contact);
134 135
 
135
-int event_reg(udomain_t* _d, impurecord_t* r_passed, int event_type, str *presentity_uri, str *watcher_contact, str *contact_uri,
136
+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,
136 137
                 str *explit_dereg_contact, int num_explit_dereg_contact);
137 138
 
138 139
 
... ...
@@ -140,7 +141,7 @@ str generate_reginfo_full(udomain_t* _t, str* impu_list, int new_subscription, s
140 141
 
141 142
 str get_reginfo_partial(impurecord_t *r, ucontact_t *c, int event_type, unsigned int reginfo_version);
142 143
 
143
-void create_notifications(udomain_t* _t, impurecord_t* r_passed, str *presentity_uri, str *watcher_contact, str *contact_uri,
144
+void create_notifications(udomain_t* _t, impurecord_t* r_passed, ucontact_t* c_passed, str *presentity_uri, str *watcher_contact, str *contact_uri,
144 145
                             str* impus, int num_impus, int event_type, str *explit_dereg_contact, int num_explit_dereg_contact);
145 146
 
146 147
 void notification_event_process();
... ...
@@ -163,6 +164,6 @@ void notify_destroy();
163 164
 int aor_to_contact(str* aor, str* contact);
164 165
 int contact_port_ip_match(str *c1, str *c2);
165 166
 
166
-int notify_subscribers(impurecord_t* impurecord, str *explit_dereg_contact, int num_explit_dereg_contact, int event_type);
167
+int notify_subscribers(impurecord_t* impurecord, ucontact_t* contact, str *explit_dereg_contact, int num_explit_dereg_contact, int event_type);
167 168
 
168 169
 #endif //S_CSCF_REGISTRAR_NOTIFY_H_
... ...
@@ -777,6 +777,9 @@ int update_contacts(struct sip_msg* msg, udomain_t* _d,
777 777
     int first_unbarred_impu = 1; //this is used to flag the IMPU as anchor for implicit set
778 778
     int is_primary_impu = 0;
779 779
     int ret = 1;
780
+	str callid = {0, 0};
781
+	str path = {0, 0};
782
+	ucontact_t* ucontact;
780 783
 
781 784
     int num_explicit_dereg_contact = 0;
782 785
     str *explicit_dereg_contact = 0;
... ...
@@ -835,7 +838,12 @@ int update_contacts(struct sip_msg* msg, udomain_t* _d,
835 838
             for (h = msg->contact; h; h = h->next) {
836 839
                 if (h->type == HDR_CONTACT_T && h->parsed) {
837 840
                     for (chi = ((contact_body_t*) h->parsed)->contacts; chi; chi = chi->next) {
838
-                        event_reg(0, impu_rec, IMS_REGISTRAR_CONTACT_REGISTERED, 0, 0, &chi->uri, 0, 0);
841
+						if (ul.get_ucontact(&chi->uri, &callid, &path, 0, &ucontact) != 0) {
842
+							LM_DBG("Contact does not exist <%.*s>\n", chi->uri.len, chi->uri.s);
843
+							goto error;
844
+						}
845
+                        event_reg(0, impu_rec, ucontact, IMS_REGISTRAR_CONTACT_REGISTERED, 0, 0, &chi->uri, 0, 0);
846
+						ul.release_ucontact(ucontact);
839 847
                     }
840 848
                 }
841 849
             }
... ...
@@ -927,7 +935,12 @@ int update_contacts(struct sip_msg* msg, udomain_t* _d,
927 935
             for (h = msg->contact; h; h = h->next) {
928 936
                 if (h->type == HDR_CONTACT_T && h->parsed) {
929 937
                     for (chi = ((contact_body_t*) h->parsed)->contacts; chi; chi = chi->next) {
930
-                        event_reg(0, impu_rec, IMS_REGISTRAR_CONTACT_REGISTERED, 0, 0, &chi->uri, 0, 0);
938
+						if (ul.get_ucontact(&chi->uri, &callid, &path, 0, &ucontact) != 0) {
939
+							LM_DBG("Contact does not exist <%.*s>\n", chi->uri.len, chi->uri.s);
940
+							goto error;
941
+						}
942
+                        event_reg(0, impu_rec, ucontact, IMS_REGISTRAR_CONTACT_REFRESHED, 0, 0, &chi->uri, 0, 0);
943
+						ul.release_ucontact(ucontact);
931 944
                     }
932 945
                 }
933 946
             }
... ...
@@ -1029,11 +1042,17 @@ int update_contacts(struct sip_msg* msg, udomain_t* _d,
1029 1042
                         //                                s = s->next;
1030 1043
                         //                            }
1031 1044
                         //                        }
1032
-                        notify_subscribers(tmp_impu_rec, (str*) explicit_dereg_contact, num_explicit_dereg_contact, IMS_REGISTRAR_CONTACT_UNREGISTERED);
1033 1045
 
1034 1046
                         for (h = msg->contact; h; h = h->next) {
1035 1047
                             if (h->type == HDR_CONTACT_T && h->parsed) {
1036 1048
                                 for (chi = ((contact_body_t*) h->parsed)->contacts; chi; chi = chi->next) {
1049
+									if (ul.get_ucontact(&chi->uri, &callid, &path, 0, &ucontact) != 0) {
1050
+										LM_DBG("Contact does not exist <%.*s>\n", chi->uri.len, chi->uri.s);
1051
+										goto error;
1052
+									}
1053
+									notify_subscribers(tmp_impu_rec, ucontact, (str*) explicit_dereg_contact, num_explicit_dereg_contact, IMS_REGISTRAR_CONTACT_UNREGISTERED);
1054
+									ul.release_ucontact(ucontact);
1055
+
1037 1056
                                     if (calc_contact_q(chi->q, &qvalue) != 0) {
1038 1057
                                         LM_ERR("error on <%.*s>\n", chi->uri.len, chi->uri.s);
1039 1058
                                         ul.unlock_udomain(_d, &pi->public_identity);
... ...
@@ -94,6 +94,9 @@ void ul_contact_changed(impurecord_t* r, ucontact_t* c, int type, void* param) {
94 94
 //    
95 95
     if (type == UL_IMPU_DELETE_CONTACT) {
96 96
         LM_DBG("Received notification of UL CONTACT DELETE\n");
97
-        event_reg(0, r, IMS_REGISTRAR_CONTACT_UNREGISTERED, 0, 0, 0, 0, 0);
97
+        event_reg(0, r, c, IMS_REGISTRAR_CONTACT_UNREGISTERED, 0, 0, 0, 0, 0);
98
+    } else if (type == UL_IMPU_EXPIRE_CONTACT) {
99
+        LM_DBG("Received notification of UL CONTACT EXPIRED\n");
100
+        event_reg(0, r, c, IMS_REGISTRAR_CONTACT_EXPIRED, 0, 0, 0, 0, 0);
98 101
     }
99 102
 }