Thanks community for all replies.

I did the second try. Result is in the attachment.

This time a did it in the way proposed by Daniel-Constantin Mierla.
All job is done in timer process when it iterates through all registrations looking for expired ones.

It works for all database modes except DB_ONLY.

I'm not sure about tcpconn_get() / tcpconn_put() functions. tcpconn_get() increments ref counter, but there are several function to decrement it: tcpconn_put(), tcpconn_chld_put() and atomic_dec_and_test(). When I was looking for examples in other modules I saw that tcp_read.c uses tcpconn_chld_put(), but forward.h and msg_translator.c uses only tcpconn_get() without decrementing ref counter at all.

It would be great if somebody more experienced shed some light on this.



diff -uNpr kamailio-4.0.3/ip_addr.h sshfs_kamailio-4.0.3/ip_addr.h
--- kamailio-4.0.3/ip_addr.h	2013-08-15 16:42:39.000000000 +0300
+++ sshfs_kamailio-4.0.3/ip_addr.h	2013-08-28 18:28:08.000000000 +0300
@@ -142,6 +142,7 @@ struct receive_info{
 	struct socket_info* bind_address; /* sock_info structure on which 
 									  the msg was received*/
 	char proto;
+	int tcpconn_id; /* tcp_connnection->id */
 #ifdef USE_COMP
 	short comp; /* compression */
 #endif
diff -uNpr kamailio-4.0.3/modules/registrar/save.c sshfs_kamailio-4.0.3/modules/registrar/save.c
--- kamailio-4.0.3/modules/registrar/save.c	2013-08-15 16:42:39.000000000 +0300
+++ sshfs_kamailio-4.0.3/modules/registrar/save.c	2013-08-29 01:44:11.000000000 +0300
@@ -259,6 +259,14 @@ static inline ucontact_info_t* pack_ci(
 			ci.sock = _m->rcv.bind_address;
 		}
 
+		/* set tcp connection id */
+		if (_m->rcv.proto==PROTO_TCP || _m->rcv.proto==PROTO_TLS
+		        || _m->rcv.proto==PROTO_WS  || _m->rcv.proto==PROTO_WSS) {
+			ci.tcpconn_id = _m->rcv.tcpconn_id;
+		} else {
+			ci.tcpconn_id = -1;
+		}
+
 		/* additional info from message */
 		if (parse_headers(_m, HDR_USERAGENT_F, 0) != -1 && _m->user_agent &&
 		_m->user_agent->body.len>0 && _m->user_agent->body.len<UA_MAX_SIZE) {
@@ -488,7 +496,7 @@ static inline int insert_contacts(struct
 
 		/* hack to work with buggy clients having many contacts with same
 		 * address in one REGISTER - increase CSeq to detect if there was
-		 * one alredy added, then update */
+		 * one already added, then update */
 		ci->cseq++;
 		if ( r->contacts==0
 				|| ul.get_ucontact_by_instance(r, &_c->uri, ci, &c) != 0) {
diff -uNpr kamailio-4.0.3/modules/usrloc/ucontact.c sshfs_kamailio-4.0.3/modules/usrloc/ucontact.c
--- kamailio-4.0.3/modules/usrloc/ucontact.c	2013-08-15 16:42:39.000000000 +0300
+++ sshfs_kamailio-4.0.3/modules/usrloc/ucontact.c	2013-08-29 01:49:56.000000000 +0300
@@ -135,6 +135,7 @@ ucontact_t* new_ucontact(str* _dom, str*
 	c->reg_id = _ci->reg_id;
 	c->last_modified = _ci->last_modified;
 	c->last_keepalive = _ci->last_modified;
+	c->tcpconn_id = _ci->tcpconn_id;
 #ifdef WITH_XAVP
 	ucontact_xavp_store(c);
 #endif
diff -uNpr kamailio-4.0.3/modules/usrloc/ul_mod.c sshfs_kamailio-4.0.3/modules/usrloc/ul_mod.c
--- kamailio-4.0.3/modules/usrloc/ul_mod.c	2013-08-15 16:42:39.000000000 +0300
+++ sshfs_kamailio-4.0.3/modules/usrloc/ul_mod.c	2013-08-29 13:04:13.000000000 +0300
@@ -161,6 +161,7 @@ int timer_interval  = 60;				/*!< Timer
 int db_mode         = 0;				/*!< Database sync scheme: 0-no db, 1-write through, 2-write back, 3-only db */
 int use_domain      = 0;				/*!< Whether usrloc should use domain part of aor */
 int desc_time_order = 0;				/*!< By default do not enable timestamp ordering */
+int handle_lost_tcp = 0;
 
 int ul_fetch_rows = 2000;				/*!< number of rows to fetch from result */
 int ul_hash_size = 9;
@@ -214,6 +215,7 @@ static param_export_t params[] = {
 	{"fetch_rows",          INT_PARAM, &ul_fetch_rows   },
 	{"hash_size",           INT_PARAM, &ul_hash_size    },
 	{"nat_bflag",           INT_PARAM, &nat_bflag       },
+	{"handle_lost_tcp",     INT_PARAM, &handle_lost_tcp },
 	{"preload",             STR_PARAM|USE_FUNC_PARAM, (void*)ul_preload_param},
 	{"db_update_as_insert", INT_PARAM, &ul_db_update_as_insert},
 	{"timer_procs",         INT_PARAM, &ul_timer_procs},
@@ -387,6 +389,10 @@ static int mod_init(void)
 			return -1;
 		}
 	}
+
+	if (handle_lost_tcp && db_mode == DB_ONLY)
+		LM_WARN("handle_lost_tcp option makes nothing in DB_ONLY mode\n");
+
 	init_flag = 1;
 
 	return 0;
diff -uNpr kamailio-4.0.3/modules/usrloc/ul_mod.h sshfs_kamailio-4.0.3/modules/usrloc/ul_mod.h
--- kamailio-4.0.3/modules/usrloc/ul_mod.h	2013-08-15 16:42:38.000000000 +0300
+++ sshfs_kamailio-4.0.3/modules/usrloc/ul_mod.h	2013-08-29 02:06:38.000000000 +0300
@@ -84,6 +84,7 @@ extern int ul_hash_size;
 extern int ul_db_update_as_insert;
 extern int ul_db_check_update;
 extern int ul_keepalive_timeout;
+extern int handle_lost_tcp;
 
 /*! nat branch flag */
 extern unsigned int nat_bflag;
diff -uNpr kamailio-4.0.3/modules/usrloc/urecord.c sshfs_kamailio-4.0.3/modules/usrloc/urecord.c
--- kamailio-4.0.3/modules/usrloc/urecord.c	2013-08-15 16:42:39.000000000 +0300
+++ sshfs_kamailio-4.0.3/modules/usrloc/urecord.c	2013-08-29 13:01:02.000000000 +0300
@@ -40,6 +40,7 @@
 #include "../../dprint.h"
 #include "../../ut.h"
 #include "../../hashes.h"
+#include "../../tcp_conn.h"
 #include "ul_mod.h"
 #include "usrloc.h"
 #include "utime.h"
@@ -221,6 +222,26 @@ void mem_delete_ucontact(urecord_t* _r,
 	free_ucontact(_c);
 }
 
+static inline int is_valid_tcpconn(ucontact_t *c)
+{
+	if (c->tcpconn_id == -1)
+		return 0; /* tcpconn_id is not present */
+	else
+		return 1; /* valid tcpconn_id */
+}
+
+static inline int is_tcp_alive(ucontact_t *c)
+{
+	struct tcp_connection *con = NULL;
+	int rc = 0;
+
+	if ((con = tcpconn_get(c->tcpconn_id, 0, 0, 0, 0))) {
+		tcpconn_put(con); /* refcnt-- */
+		rc = 1;
+	}
+
+	return rc;
+}
 
 /*!
  * \brief Expires timer for NO_DB db_mode
@@ -236,6 +257,11 @@ static inline void nodb_timer(urecord_t*
 	ptr = _r->contacts;
 
 	while(ptr) {
+		if (handle_lost_tcp && is_valid_tcpconn(ptr) && !is_tcp_alive(ptr)) {
+			LM_DBG("tcp connection has been lost, expiring contact %.*s\n", ptr->c.len, ptr->c.s);
+			ptr->expires = UL_EXPIRED_TIME;
+		}
+
 		if (!VALID_CONTACT(ptr, act_time)) {
 			/* run callbacks for EXPIRE event */
 			if (exists_ulcb_type(UL_CONTACT_EXPIRE))
@@ -296,7 +322,6 @@ static inline void wt_timer(urecord_t* _
 	}
 }
 
-
 /*!
  * \brief Write-back timer, used for WRITE_BACK db_mode
  *
@@ -316,6 +341,11 @@ static inline void wb_timer(urecord_t* _
 	ptr = _r->contacts;
 
 	while(ptr) {
+		if (handle_lost_tcp && is_valid_tcpconn(ptr) && !is_tcp_alive(ptr)) {
+			LM_DBG("tcp connection has been lost, expiring contact %.*s\n", ptr->c.len, ptr->c.s);
+			ptr->expires = UL_EXPIRED_TIME;
+		}
+
 		if (!VALID_CONTACT(ptr, act_time)) {
 			/* run callbacks for EXPIRE event */
 			if (exists_ulcb_type(UL_CONTACT_EXPIRE)) {
diff -uNpr kamailio-4.0.3/modules/usrloc/usrloc.h sshfs_kamailio-4.0.3/modules/usrloc/usrloc.h
--- kamailio-4.0.3/modules/usrloc/usrloc.h	2013-08-15 16:42:39.000000000 +0300
+++ sshfs_kamailio-4.0.3/modules/usrloc/usrloc.h	2013-08-28 19:19:27.000000000 +0300
@@ -90,6 +90,7 @@ typedef struct ucontact {
 	unsigned int methods;   /*!< Supported methods */
 	str instance;           /*!< SIP instance value - gruu */
 	unsigned int reg_id;    /*!< reg-id parameters */
+	int tcpconn_id;          /* unique tcp connection id */
 #ifdef WITH_XAVP
 	sr_xavp_t * xavp;       /*!< per contact xavps */
 #endif
@@ -115,6 +116,7 @@ typedef struct ucontact_info {
 	unsigned int methods;     /*!< supported methods */
 	str instance;             /*!< SIP instance value - gruu */
 	unsigned int reg_id;      /*!< reg-id parameters */
+	int tcpconn_id;
 #ifdef WITH_XAVP
 	sr_xavp_t * xavp;         /*!< per contact xavps */
 #endif
diff -uNpr kamailio-4.0.3/tcp_main.c sshfs_kamailio-4.0.3/tcp_main.c
--- kamailio-4.0.3/tcp_main.c	2013-08-15 16:42:39.000000000 +0300
+++ sshfs_kamailio-4.0.3/tcp_main.c	2013-08-28 18:22:53.000000000 +0300
@@ -1102,6 +1102,7 @@ struct tcp_connection* tcpconn_new(int s
 	DBG(     "tcpconn_new: on port %d, type %d\n", c->rcv.src_port, type);
 	init_tcp_req(&c->req, (char*)c+sizeof(struct tcp_connection), rd_b_size);
 	c->id=(*connection_id)++;
+	c->rcv.tcpconn_id = c->id;
 	c->rcv.proto_reserved1=0; /* this will be filled before receive_message*/
 	c->rcv.proto_reserved2=0;
 	c->state=state;
_______________________________________________
SIP Express Router (SER) and Kamailio (OpenSER) - sr-users mailing list
[email protected]
http://lists.sip-router.org/cgi-bin/mailman/listinfo/sr-users

Reply via email to