Browse Source

usrloc(k): keep time of the last keepalive for natted UDP contacts

- new field in the contact structure to keep the timestamp when that
  conctact was refreshed by keepalive or registration update
- it is taken in cosideration to remove contacts that don't reply to nat
  ping requests, so it works only together with nathelper module
- when an UDP contact is not resposive for an interval of time, the
  contact is set to expire is 10 seconds. This process takes place in
  the function that fetches the list of contacts for nat pinging
- last_modified and last_keepalive are exported to mi and rpc list
  commands
Daniel-Constantin Mierla 13 years ago
parent
commit
36845cc575

+ 71 - 0
modules_k/usrloc/dlist.c

@@ -307,6 +307,12 @@ static inline int get_all_mem_ucontacts(void *buf, int len, unsigned int flags,
 	int i = 0;
 	cp = buf;
 	shortage = 0;
+	time_t tnow = 0;
+
+
+	if(ul_keepalive_timeout>0)
+		tnow = time(NULL);
+
 	/* Reserve space for terminating 0000 */
 	len -= sizeof(c->c.len);
 
@@ -333,6 +339,22 @@ static inline int get_all_mem_ucontacts(void *buf, int len, unsigned int flags,
 					 */
 					if ((c->cflags & flags) != flags)
 						continue;
+
+					if(ul_keepalive_timeout>0 && c->last_keepalive>0)
+					{
+						if((c->cflags & nat_bflag) != 0 && c->sock!=NULL
+								&& c->sock->proto==PROTO_UDP)
+						{
+							if(c->last_keepalive+ul_keepalive_timeout < tnow)
+							{
+								/* set contact as expired in 10s */
+								if(c->expires > tnow + 10)
+									c->expires = tnow + 10;
+								continue;
+							}
+						}
+					}
+
 					if (c->received.s) {
 						needed = (int)(sizeof(c->received.len)
 								+ c->received.len
@@ -457,6 +479,55 @@ int get_all_ucontacts(void *buf, int len, unsigned int flags,
 
 
 
+/**
+ *
+ */
+int ul_refresh_keepalive(unsigned int _aorhash, str *_ruid)
+{
+	dlist_t *p;
+	urecord_t *r;
+	ucontact_t *c;
+	int i;
+
+	/* todo: get location domain via param */
+
+	for (p = root; p != NULL; p = p->next)
+	{
+		i = _aorhash&(p->d->size-1);
+		lock_ulslot(p->d, i);
+		if(p->d->table[i].n<=0)
+		{
+			unlock_ulslot(p->d, i);
+			continue;
+		}
+		for (r = p->d->table[i].first; r != NULL; r = r->next)
+		{
+			if(r->aorhash==_aorhash)
+			{
+				for (c = r->contacts; c != NULL; c = c->next)
+				{
+					if (c->c.len <= 0 || c->ruid.len<=0)
+						continue;
+					if(c->ruid.len==_ruid->len
+							&& !memcmp(c->ruid.s, _ruid->s, _ruid->len))
+					{
+						/* found */
+						c->last_keepalive = time(NULL);
+						LM_DBG("updated keepalive for [%.*s:%u] to %u\n",
+								_ruid->len, _ruid->s, _aorhash,
+								(unsigned int)c->last_keepalive);
+						unlock_ulslot(p->d, i);
+						return 0;
+					}
+				}
+			}
+		}
+		unlock_ulslot(p->d, i);
+	}
+
+	return 0;
+}
+
 /*!
  * \brief Create a new domain structure
  * \return 0 if everything went OK, otherwise value < 0 is returned

+ 2 - 0
modules_k/usrloc/ucontact.c

@@ -96,6 +96,7 @@ ucontact_t* new_ucontact(str* _dom, str* _aor, str* _contact, ucontact_info_t* _
 	c->methods = _ci->methods;
 	c->reg_id = _ci->reg_id;
 	c->last_modified = _ci->last_modified;
+	c->last_keepalive = _ci->last_modified;
 
 	return c;
 error:
@@ -250,6 +251,7 @@ int mem_update_ucontact(ucontact_t* _c, ucontact_info_t* _ci)
 	_c->cseq = _ci->cseq;
 	_c->methods = _ci->methods;
 	_c->last_modified = _ci->last_modified;
+	_c->last_keepalive = _ci->last_modified;
 	_c->flags = _ci->flags;
 	_c->cflags = _ci->cflags;
 

+ 15 - 0
modules_k/usrloc/ul_mi.c

@@ -259,6 +259,21 @@ static inline int mi_add_aor_node(struct mi_node *parent, urecord_t* r, time_t t
 		node = add_mi_node_child( cnode, MI_DUP_VALUE, "Reg-Id", 6, p, len);
 		if (node==0)
 			return -1;
+
+		/* last keepalive */
+		p = int2str((unsigned long)c->last_keepalive, &len);
+		node = add_mi_node_child( cnode, MI_DUP_VALUE, "Last-Keepalive",
+					14, p, len);
+		if (node==0)
+			return -1;
+
+		/* last modified */
+		p = int2str((unsigned long)c->last_modified, &len);
+		node = add_mi_node_child( cnode, MI_DUP_VALUE, "Last-Modified",
+					13, p, len);
+		if (node==0)
+			return -1;
+
 	} /* for */
 
 	return 0;

+ 1 - 0
modules_k/usrloc/ul_mod.c

@@ -108,6 +108,7 @@ extern int ul_locks_no;
 int ul_db_update_as_insert = 0;
 int ul_timer_procs = 0;
 int ul_db_check_update = 0;
+int ul_keepalive_timeout = 0;
 
 /* sruid to get internal uid for mi/rpc commands */
 sruid_t _ul_sruid;

+ 7 - 0
modules_k/usrloc/ul_mod.h

@@ -74,6 +74,13 @@ extern int ul_fetch_rows;
 extern int ul_hash_size;
 extern int ul_db_update_as_insert;
 extern int ul_db_check_update;
+extern int ul_keepalive_timeout;
+
+/*! nat branch flag */
+extern unsigned int nat_bflag;
+/*! flag to protect against wrong initialization */
+extern unsigned int init_flag;
+
 
 extern db1_con_t* ul_dbh;   /* Database connection handle */
 extern db_func_t ul_dbf;

+ 16 - 0
modules_k/usrloc/ul_rpc.c

@@ -287,6 +287,22 @@ static void ul_rpc_dump(rpc_t* rpc, void* ctx)
 									"Internal error adding reg_id");
 							return;
 						}
+						if(rpc->struct_add(vh, "d",
+									"Last-Keepalive", (int)c->last_keepalive)<0)
+						{
+							unlock_ulslot( dom, i);
+							rpc->fault(ctx, 500,
+									"Internal error adding reg_id");
+							return;
+						}
+						if(rpc->struct_add(vh, "d",
+									"Last-Modified", (int)c->last_modified)<0)
+						{
+							unlock_ulslot( dom, i);
+							rpc->fault(ctx, 500,
+									"Internal error adding reg_id");
+							return;
+						}
 
 					}
 				}

+ 15 - 5
modules_k/usrloc/usrloc.c

@@ -41,11 +41,6 @@
 #include "../../sr_module.h"
 #include "ul_mod.h"
 
-/*! nat branch flag */
-extern unsigned int nat_bflag;
-/*! flag to protect against wrong initialization */
-extern unsigned int init_flag;
-
 
 /*!
  * \brief usrloc module API export bind function
@@ -83,9 +78,24 @@ int bind_usrloc(usrloc_api_t* api)
 	api->get_urecord_by_ruid      = get_urecord_by_ruid;
 	api->get_ucontact_by_instance = get_ucontact_by_instance;
 
+	api->set_keepalive_timeout    = ul_set_keepalive_timeout;
+	api->refresh_keepalive        = ul_refresh_keepalive;
+
 	api->use_domain = use_domain;
 	api->db_mode    = db_mode;
 	api->nat_flag   = nat_bflag;
 
 	return 0;
 }
+
+/**
+ *
+ */
+int ul_set_keepalive_timeout(int _to)
+{
+	int oto;
+
+	oto = ul_keepalive_timeout;
+	ul_keepalive_timeout = _to;
+	return oto;
+}

+ 10 - 0
modules_k/usrloc/usrloc.h

@@ -83,6 +83,7 @@ typedef struct ucontact {
 	str user_agent;         /*!< User-Agent header field */
 	struct socket_info *sock; /*!< received socket */
 	time_t last_modified;   /*!< When the record was last modified */
+	time_t last_keepalive;  /*!< last keepalive timestamp */
 	unsigned int methods;   /*!< Supported methods */
 	str instance;           /*!< SIP instance value - gruu */
 	unsigned int reg_id;    /*!< reg-id parameters */
@@ -170,6 +171,12 @@ typedef int (*get_udomain_t)(const char* _n, udomain_t** _d);
 typedef unsigned int (*ul_get_aorhash_t)(str *_aor);
 unsigned int ul_get_aorhash(str *_aor);
 
+typedef int (*ul_set_keepalive_timeout_t)(int _to);
+int ul_set_keepalive_timeout(int _to);
+
+typedef int (*ul_refresh_keepalive_t)(unsigned int _aorhash, str *_ruid);
+int ul_refresh_keepalive(unsigned int _aorhash, str *_ruid);
+
 /*! usrloc API export structure */
 typedef struct usrloc_api {
 	int           use_domain; /*! use_domain module parameter */
@@ -198,6 +205,9 @@ typedef struct usrloc_api {
 
 	register_ulcb_t      register_ulcb;
 	ul_get_aorhash_t     get_aorhash;
+
+	ul_set_keepalive_timeout_t set_keepalive_timeout;
+	ul_refresh_keepalive_t     refresh_keepalive;
 } usrloc_api_t;