Browse Source

usrloc: process keepalive response

Daniel-Constantin Mierla 5 years ago
parent
commit
87c5d45a66

+ 180 - 3
src/modules/usrloc/ul_keepalive.c

@@ -43,9 +43,9 @@ static int ul_ka_send(str *kamsg, dest_info_t *kadst);
 /**
  * 
 _KAMETHOD_ _URI_ SIP/2.0\r\n
-Via: SIP/2.0/_PROTO_ _IP_:_PORT_\r\n
+Via: SIP/2.0/_PROTO_ _IP_:_PORT_;branch=z9hG4bKx._GCNT_._BCNT_.0\r\n
 __KAROUTES__
-From: <_KAFROM_>;tag=_KAFROMTAG_\r\n
+From: <_KAFROM_>;tag=_RUID_-_AORHASH_-_TIMESEC_-_TIMEUSEC_-_GCNT_._BCNT_\r\n
 To: <sip:_AOR_>\r\n
 Call-ID: _KACALLID_\r\n
 CSeq: 1 _KAMETHOD_\r\n
@@ -73,6 +73,9 @@ extern unsigned int nat_bflag;
 
 static unsigned int _ul_ka_counter = 0;
 
+/**
+ *
+ */
 int ul_ka_urecord(urecord_t *ur)
 {
 	ucontact_t *uc;
@@ -205,6 +208,9 @@ int ul_ka_urecord(urecord_t *ur)
 	return 0;
 }
 
+/**
+ *
+ */
 static int ul_ka_send(str *kamsg, dest_info_t *kadst)
 { 
 	if (kadst->proto == PROTO_UDP) {
@@ -236,4 +242,175 @@ static int ul_ka_send(str *kamsg, dest_info_t *kadst)
 				kadst->proto);
 		return -1;
 	}
-}
+}
+
+/**
+ *
+ */
+unsigned long ul_ka_fromhex(str *shex, int *err)
+{
+    unsigned long v = 0;
+	int i;
+
+	*err = 0;
+    for (i=0; i<shex->len; i++) {
+        char b = shex->s[i];
+        if (b >= '0' && b <= '9') b = b - '0';
+        else if (b >= 'a' && b <='f') b = b - 'a' + 10;
+        else if (b >= 'A' && b <='F') b = b - 'A' + 10;
+		else { *err = 1; return 0; };
+        v = (v << 4) | (b & 0xF);
+    }
+    return v;
+}
+
+/**
+ *
+ */
+int ul_ka_reply_received(sip_msg_t *msg)
+{
+	to_body_t *fb;
+	str ruid;
+	str tok;
+	int err;
+	unsigned int aorhash;
+	char *p;
+	struct timeval tvm;
+	struct timeval tvn;
+	unsigned int tvdiff;
+
+	if(msg->cseq == NULL) {
+		if((parse_headers(msg, HDR_CSEQ_F, 0) == -1) || (msg->cseq == NULL)) {
+			LM_ERR("invalid CSeq header\n");
+			return -1;
+		}
+	}
+
+	if(get_cseq(msg)->method.len != ul_ka_method.len) {
+		return 1;
+	}
+	if(strncmp(get_cseq(msg)->method.s, ul_ka_method.s, ul_ka_method.len) != 0) {
+		return 1;
+	}
+
+	/* there must be no second via */
+	if(!(parse_headers(msg, HDR_VIA2_F, 0) == -1 || (msg->via2 == 0)
+			   || (msg->via2->error != PARSE_OK))) {
+		return 1;
+	}
+
+	/* from uri check */
+	if((parse_from_header(msg)) < 0) {
+		LM_ERR("cannot parse From header\n");
+		return -1;
+	}
+
+	fb = get_from(msg);
+	if(fb->uri.len != ul_ka_from.len
+			|| strncmp(fb->uri.s, ul_ka_from.s, ul_ka_from.len) != 0) {
+		return 1;
+	}
+
+	/* from-tag is: ruid-aorhash-tmsec-tmusec-counter */
+	if(fb->tag_value.len <= 8) {
+		return 1;
+	}
+
+	LM_DBG("checking keepalive reply [%.*s]\n", fb->tag_value.len,
+			fb->tag_value.s);
+
+	/* todo: macro/function to tokenize */
+	/* skip counter */
+	p = q_memrchr(fb->tag_value.s, '-', fb->tag_value.len);
+	if(p == NULL) {
+		LM_DBG("from tag format mismatch [%.*s]\n", fb->tag_value.len,
+				fb->tag_value.s);
+		return 1;
+	}
+
+	/* tv_usec hash */
+	tok.len = p - fb->tag_value.s;
+	p = q_memrchr(fb->tag_value.s, '-', tok.len);
+	if(p == NULL) {
+		LM_DBG("from tag format mismatch [%.*s]\n", fb->tag_value.len,
+				fb->tag_value.s);
+		return 1;
+	}
+	tok.s = p + 1;
+	tok.len = fb->tag_value.s + tok.len - tok.s;
+	if(tok.len <= 0) {
+		LM_DBG("empty token\n");
+		return 1;
+	}
+	LM_DBG("tv usec string is [%.*s] (%d)\n", tok.len, tok.s, tok.len);
+	tvm.tv_usec = ul_ka_fromhex(&tok, &err);
+	if(err==1) {
+		LM_DBG("invalid tv usec value\n");
+		return 1;
+	}
+	LM_DBG("tv usec is [%u]\n", tvm.tv_usec);
+
+	/* tv_sec hash */
+	tok.len = p - fb->tag_value.s;
+	p = q_memrchr(fb->tag_value.s, '-', tok.len);
+	if(p == NULL) {
+		LM_DBG("from tag format mismatch [%.*s]\n", fb->tag_value.len,
+				fb->tag_value.s);
+		return 1;
+	}
+	tok.s = p + 1;
+	tok.len = fb->tag_value.s + tok.len - tok.s;
+	if(tok.len <= 0) {
+		LM_DBG("empty token\n");
+		return 1;
+	}
+	LM_DBG("tv sec string is [%.*s] (%d)\n", tok.len, tok.s, tok.len);
+	tvm.tv_sec = ul_ka_fromhex(&tok, &err);
+	if(err==1) {
+		LM_DBG("invalid tv sec value\n");
+		return 1;
+	}
+	LM_DBG("tv sec is [%lu]\n", tvm.tv_sec);
+
+	/* aor hash */
+	tok.len = p - fb->tag_value.s;
+	p = q_memrchr(fb->tag_value.s, '-', tok.len);
+	if(p == NULL) {
+		LM_DBG("from tag format mismatch [%.*s]\n", fb->tag_value.len,
+				fb->tag_value.s);
+		return 1;
+	}
+	tok.s = p + 1;
+	tok.len = fb->tag_value.s + tok.len - tok.s;
+	if(tok.len <= 0) {
+		LM_DBG("empty token\n");
+		return 1;
+	}
+	LM_DBG("aor hash string is [%.*s] (%d)\n", tok.len, tok.s, tok.len);
+	aorhash = ul_ka_fromhex(&tok, &err);
+	if(err==1) {
+		LM_DBG("invalid aor hash value\n");
+		return 1;
+	}
+	LM_DBG("aor hash is [%u]\n", aorhash);
+
+	ruid.s = fb->tag_value.s;
+	ruid.len = tok.s - ruid.s - 1;
+
+	if(ruid.len <= 0) {
+		LM_DBG("cannot get ruid in [%.*s]\n", fb->tag_value.len,
+				fb->tag_value.s);
+		return 1;
+	}
+
+	gettimeofday(&tvn, NULL);
+	tvdiff = (tvn.tv_sec - tvm.tv_sec) * 1000000
+					+ (tvn.tv_usec - tvm.tv_usec);
+
+	LM_DBG("reply for keepalive of [%.*s:%u] roundtrip: %u.%06usec\n",
+			ruid.len, ruid.s, aorhash, tvdiff/1000000, tvdiff%1000000);
+
+	ul_refresh_keepalive(aorhash, &ruid);
+
+	return 0;
+}

+ 3 - 0
src/modules/usrloc/ul_keepalive.h

@@ -24,8 +24,11 @@
 #ifndef _UL_KEEPALIVE_H_
 #define _UL_KEEPALIVE_H_
 
+#include "../../core/parser/msg_parser.h"
+
 #include "urecord.h"
 
 int ul_ka_urecord(urecord_t *ur);
+int ul_ka_reply_received(sip_msg_t *msg);
 
 #endif

+ 14 - 1
src/modules/usrloc/usrloc_mod.c

@@ -55,6 +55,7 @@
 #include "ucontact.h"        /* update_ucontact */
 #include "ul_rpc.h"
 #include "ul_callback.h"
+#include "ul_keepalive.h"
 #include "usrloc.h"
 
 MODULE_VERSION
@@ -96,6 +97,7 @@ static void ul_core_timer(unsigned int ticks, void* param);  /*!< Core timer han
 static void ul_local_timer(unsigned int ticks, void* param); /*!< Local timer handler */
 static void ul_db_clean_timer(unsigned int ticks, void* param); /*!< DB clean timer handler */
 static int child_init(int rank);                    /*!< Per-child init function */
+static int ul_sip_reply_received(sip_msg_t *msg); /*!< SIP response handling */
 
 #define UL_PRELOAD_SIZE	8
 static char* ul_preload_list[UL_PRELOAD_SIZE];
@@ -268,7 +270,7 @@ struct module_exports exports = {
 	params,          /*!< exported parameters */
 	0,               /*!< exported rpc functions */
 	0,               /*!< exported pseudo-variables */
-	0,               /*!< response handling function */
+	ul_sip_reply_received, /*!< response handling function */
 	mod_init,        /*!< module init function */
 	child_init,      /*!< child init function */
 	destroy          /*!< destroy function */
@@ -484,6 +486,17 @@ static void destroy(void)
 	destroy_ulcb_list();
 }
 
+/*! \brief
+ * Callback to handle the SIP replies
+ */
+static int ul_sip_reply_received(sip_msg_t *msg)
+{
+	if(ul_ka_mode == 0) {
+		return 1;
+	}
+	ul_ka_reply_received(msg);
+	return 1;
+}
 
 /*! \brief
  * Core timer handler