Forráskód Böngészése

ims_registrar_pcscf: changes for ul db_mode DB_ONLY

Enable registration of pcscf contact callback during download
from db location table and inserting pcontact (normally this
callback is registered during handling of REGISTER).
Refuse REGISTER when pcontact is expired since [0 to 20] seconds.
Within this time window a NOTIFY is expected from scscf and in order
to avoid race time conditions between scscf and pcscf REGISTER
will be refused. Refuse REGISTER when pcontact is expired longer
than 20 seconds - send PUBLISH (contact expired) to scscf to trigger
NOTIFY. In both REGISTER refused scenarios routing script should reply
500 - Deregistration in progress.

undo changes in ul_callback.c & ul_callback.h

corrections after comments from Henning
Annemarie Mandl 4 éve
szülő
commit
38d72c3f82

+ 41 - 0
src/modules/ims_registrar_pcscf/doc/ims_registrar_pcscf_admin.xml

@@ -319,6 +319,47 @@ pcscf_save("location");
 			</para>
 		</listitem>
 		</itemizedlist>
+		<para>The return code may have the following values:</para>
+
+		<itemizedlist>
+		<listitem>
+			<para><emphasis>( 1)</emphasis> OK</para>
+		</listitem>
+		<listitem>
+			<para><emphasis>(-1)</emphasis> Parsing of contact data failed</para>
+		</listitem>
+		<listitem>
+			<para><emphasis>(-2)</emphasis> Deregistration in progress</para>
+		</listitem>
+		</itemizedlist>
+		<para>For db_mode = DB_ONLY (3) setting for ims_usrloc_pcscf module modparam following logic is implemented:</para>
+		<itemizedlist>
+		<listitem>
+		<para>To avoid race time conditions between a REREGISTER and the expiry handler state machine in the scscf
+		 an approach is chosen to refuse a REREGISTER in time window of 20 seconds after pcontact expiry on the
+		 pcscf (thus allowing expiry handling to finish). REREGISTER is refused in this scenario with
+		 return code -2.</para>
+		</listitem>
+		<listitem>
+		<para>In case a REREGISTER arrives at pcscf and the respective pcontact is expired longer than time
+		 window of 20 seconds registration also is refused with return code -2 and additionaly PUBLISH is sent to
+		 scscf with expiry = 0.</para>
+		</listitem>
+		<listitem>
+		<para>The rc -2 shall be handled in register.cfg script as follows:</para>
+		<para>
+		</para>
+			<para>  pcscf_save_pending("location");</para>
+				<para>  switch ($retcode) {</para>
+					<para>case -1:</para>
+						<para>.......</para>
+					<para>case -2:</para>
+						<para>send_reply("500", "Deregister in progress - Please try again");</para>
+						<para>exit;</para>
+						<para>break;</para>
+				<para>}</para>
+		</listitem>
+		</itemizedlist>
   </section>
 
    <section>

+ 7 - 0
src/modules/ims_registrar_pcscf/ims_registrar_pcscf_mod.c

@@ -67,6 +67,7 @@
 #include "async_reginfo.h"
 
 #include "ims_registrar_pcscf_mod.h"
+#include "ul_callback.h"
 #include "save.h"
 #include "service_routes.h"
 MODULE_VERSION
@@ -261,6 +262,12 @@ static int mod_init(void) {
 	if (bind_usrloc(&ul) < 0) {
 		return -1;
 	}
+	if (ul.db_mode == DB_ONLY){
+		if (!(ul.register_ulcb_method(NULL, PCSCF_CONTACT_UPDATE, callback_pcscf_contact_cb, NULL) == 1)){
+			LM_ERR("Can't register ulcb method\n");
+			return -1;
+		}
+	}
 	LM_DBG("Successfully bound to PCSCF Usrloc module\n");
 
 	bind_ipsec_pcscf = (bind_ipsec_pcscf_t) find_export("bind_ims_ipsec_pcscf", 1, 0);

+ 2 - 2
src/modules/ims_registrar_pcscf/notify.c

@@ -113,8 +113,7 @@ int process_contact(udomain_t * _d, int expires, str contact_uri, int contact_st
     expires = local_time_now + expires; //turn expires into correct time since epoch format
     LM_DBG("Changed expires to format time since the epoch: %d", expires);
     ci.expires = expires;
-    ci.reg_state = PCONTACT_REGISTERED;
-
+    ci.reg_state = PCONTACT_ANY;
 
     ul.lock_udomain(_d, &puri.host, puri.port_no, puri.proto);
     ci.aor = contact_uri;
@@ -213,6 +212,7 @@ int process_contact(udomain_t * _d, int expires, str contact_uri, int contact_st
                     TIME_T_CAST(pcontact->expires),
                     expires,
                     expires - local_time_now);
+            ci.reg_state = PCONTACT_REGISTERED;
             if (ul.update_pcontact(_d, &ci, pcontact) != 0) {
                 LM_ERR("failed to update pcscf contact\n");
                 ret = RESULT_ERROR;

+ 35 - 3
src/modules/ims_registrar_pcscf/save.c

@@ -262,13 +262,12 @@ int save_pending(struct sip_msg* _m, udomain_t* _d) {
 	int cexpires = 0;
 	pcontact_t* pcontact;
 	contact_t* c;
-	struct pcontact_info ci;
+	struct pcontact_info ci, ci_;
 	struct via_body* vb;
 	unsigned short port, proto;
 	int_str val;
 	struct sip_uri parsed_received;
 	char srcip[50];
-
 	memset(&ci, 0, sizeof(struct pcontact_info));
         
 	vb = cscf_get_ue_via(_m);
@@ -391,7 +390,25 @@ int save_pending(struct sip_msg* _m, udomain_t* _d) {
 			}
 		}
 	} else { //contact already exists - update
-        LM_DBG("Contact already exists - not doing anything for now\n");
+           if (ul.db_mode == DB_ONLY){
+              const int window_for_notify = 20;
+              if ((pcontact->reg_state==PCONTACT_DEREG_PENDING_PUBLISH) || 
+                  ((pcontact->expires   < local_time_now) &&
+                   (pcontact->expires + window_for_notify  > local_time_now))){
+                  ul.unlock_udomain(_d, &ci.via_host, ci.via_port, ci.via_prot);
+                  return -2;
+              }
+              if((pcontact->expires + window_for_notify ) <= local_time_now){
+                 memset(&ci_, 0, sizeof(struct pcontact_info));
+                 ci_.reg_state = PCONTACT_DEREG_PENDING_PUBLISH;
+                 ci_.num_service_routes = 0;
+                 ul.update_pcontact(_d, &ci_, pcontact);
+                 ul.unlock_udomain(_d, &ci.via_host, ci.via_port, ci.via_prot);
+                 return -2;  
+              }
+           }else{
+               LM_DBG("Contact already exists - not doing anything for now\n");
+           }
 	}
 
 	ul.unlock_udomain(_d, &ci.via_host, ci.via_port, ci.via_prot);
@@ -423,6 +440,8 @@ int save(struct sip_msg* _m, udomain_t* _d, int _cflags) {
 	int contact_has_sos=-1;
 	contact_t* chi; //contact header information
 	struct hdr_field* h;
+	contact_t *ctct;
+	unsigned int expir = 0;
 	//get request from reply
 	req = get_request_from_reply(_m);
 	if (!req) {
@@ -467,6 +486,19 @@ int save(struct sip_msg* _m, udomain_t* _d, int _cflags) {
 		goto error;
 	}
 
+        // skip subscribe, if all contacts have "expires=0" parameter
+	if (cb && (ctct = cb->contacts)) {
+		while (ctct && ctct->expires && ctct->expires->body.len) {
+			expir = 0;
+			str2int(&(ctct->expires->body), (unsigned int*) &expir);
+			if (expir)
+				break;
+			ctct = ctct->next;
+		}
+		if (!ctct)
+			goto done;
+	}
+	
 	if(subscribe_to_reginfo == 1 && contact_has_sos < 1){
 	    
 	    //use the first p_associated_uri - i.e. the default IMPU