Hi

I have added support CRLF ping/pong keepalives aka SIP outbound
style (http://tools.ietf.org/html/draft-ietf-sip-outbound-13).
(thanks to Andrei for guidance).


The patch is against SER v2.1 and adds a new configuration item
in tcp_options.crlf_ping which is enabled by default.


the code works by looking for empty double CRLF's in between
SIP messages, and when detected it will respond with a single
CRLF on the same TCP connection.


I have done some brief testing, but this patch needs much
more heavy testing before it is accepted into CVS (if?)


For people interested in SER v2.0 I can also provide a patch.


Please review and test, comments are welcome


/alfred

Index: core_cmd.c
===================================================================
RCS file: /cvsroot/ser/sip_router/core_cmd.c,v
retrieving revision 1.25
diff -u -3 -r1.25 core_cmd.c
--- core_cmd.c	21 Dec 2007 17:58:07 -0000	1.25
+++ core_cmd.c	22 Apr 2008 08:11:10 -0000
@@ -562,7 +562,7 @@
 	if (!tcp_disable){
 		tcp_options_get(&t);
 		rpc->add(c, "{", &handle);
-		rpc->struct_add(handle, "dddddddddddddd",
+		rpc->struct_add(handle, "ddddddddddddddd",
 			"fd_cache",		t.fd_cache,
 			"tcp_buf_write",	t.tcp_buf_write,
 			"tcp_connect_wait",	t.tcp_connect_wait,
@@ -577,7 +577,8 @@
 			"keepalive",	t.keepalive,
 			"keepidle",		t.keepidle,
 			"keepintvl",	t.keepintvl,
-			"keepcnt",		t.keepcnt
+			"keepcnt",		t.keepcnt,
+			"crlf_ping",	t.crlf_ping
 		);
 	}else{
 		rpc->fault(c, 500, "tcp support disabled");
Index: tcp_conn.h
===================================================================
RCS file: /cvsroot/ser/sip_router/tcp_conn.h,v
retrieving revision 1.39
diff -u -3 -r1.39 tcp_conn.h
--- tcp_conn.h	20 Feb 2008 14:37:30 -0000	1.39
+++ tcp_conn.h	22 Apr 2008 08:11:10 -0000
@@ -83,12 +83,13 @@
 
 enum tcp_req_errors {	TCP_REQ_INIT, TCP_REQ_OK, TCP_READ_ERROR,
 						TCP_REQ_OVERRUN, TCP_REQ_BAD_LEN };
-enum tcp_req_states {	H_SKIP_EMPTY, H_SKIP, H_LF, H_LFCR,  H_BODY, H_STARTWS,
+enum tcp_req_states {	H_SKIP_EMPTY, H_SKIP_EMPTY_CR_FOUND, H_SKIP_EMPTY_CRLF_FOUND, H_SKIP_EMPTY_CRLFCR_FOUND,
+			H_SKIP, H_LF, H_LFCR,  H_BODY, H_STARTWS,
 		H_CONT_LEN1, H_CONT_LEN2, H_CONT_LEN3, H_CONT_LEN4, H_CONT_LEN5,
 		H_CONT_LEN6, H_CONT_LEN7, H_CONT_LEN8, H_CONT_LEN9, H_CONT_LEN10,
 		H_CONT_LEN11, H_CONT_LEN12, H_CONT_LEN13, H_L_COLON, 
 		H_CONT_LEN_BODY, H_CONT_LEN_BODY_PARSE,
-		H_STUN_MSG, H_STUN_READ_BODY, H_STUN_FP, H_STUN_END 
+		H_STUN_MSG, H_STUN_READ_BODY, H_STUN_FP, H_STUN_END, H_PING_CRLF
 	};
 
 enum tcp_conn_states { S_CONN_ERROR=-2, S_CONN_BAD=-1, S_CONN_OK=0, 
Index: tcp_options.c
===================================================================
RCS file: /cvsroot/ser/sip_router/tcp_options.c,v
retrieving revision 1.5
diff -u -3 -r1.5 tcp_options.c
--- tcp_options.c	21 Dec 2007 17:58:07 -0000	1.5
+++ tcp_options.c	22 Apr 2008 08:11:10 -0000
@@ -58,6 +58,7 @@
 #ifdef HAVE_TCP_QUICKACK
 	tcp_options.delayed_ack=1;
 #endif
+	tcp_options.crlf_ping=1;
 }
 
 
Index: tcp_options.h
===================================================================
RCS file: /cvsroot/ser/sip_router/tcp_options.h,v
retrieving revision 1.4
diff -u -3 -r1.4 tcp_options.h
--- tcp_options.h	21 Dec 2007 17:58:07 -0000	1.4
+++ tcp_options.h	22 Apr 2008 08:11:10 -0000
@@ -126,6 +126,7 @@
 	int keepidle;   /* idle time (s) before tcp starts sending keepalives */
 	int keepintvl;  /* interval between keep alives */
 	int keepcnt;    /* maximum no. of keepalives before giving up */
+	int crlf_ping;  /* on/off - reply to double CRLF keepalives */
 };
 
 
Index: tcp_read.c
===================================================================
RCS file: /cvsroot/ser/sip_router/tcp_read.c,v
retrieving revision 1.49
diff -u -3 -r1.49 tcp_read.c
--- tcp_read.c	5 Feb 2008 21:47:29 -0000	1.49
+++ tcp_read.c	22 Apr 2008 08:11:10 -0000
@@ -78,6 +78,7 @@
 #include "io_wait.h"
 #include <fcntl.h> /* must be included after io_wait.h if SIGIO_RT is used */
 #include "tsend.h"
+#include "forward.h"
 
 #ifdef USE_STUN
 #include "ser_stun.h"
@@ -325,7 +326,13 @@
 			case H_SKIP_EMPTY:
 				switch (*p){
 					case '\n':
+						break;
 					case '\r':
+						if (tcp_options.crlf_ping) {
+							r->state=H_SKIP_EMPTY_CR_FOUND;
+							r->start=p;
+						}
+						break;
 					case ' ':
 					case '\t':
 						/* skip empty lines */
@@ -358,6 +365,36 @@
 				};
 				p++;
 				break;
+
+			case H_SKIP_EMPTY_CR_FOUND:
+				if (*p=='\n'){
+					r->state=H_SKIP_EMPTY_CRLF_FOUND;
+					p++;
+				}else{
+					r->state=H_SKIP_EMPTY;
+				}
+				break;
+
+			case H_SKIP_EMPTY_CRLF_FOUND:
+				if (*p=='\r'){
+					r->state = H_SKIP_EMPTY_CRLFCR_FOUND;
+					p++;
+				}else{
+					r->state = H_SKIP_EMPTY;
+				}
+				break;
+
+			case H_SKIP_EMPTY_CRLFCR_FOUND:
+				if (*p=='\n'){
+					r->state = H_PING_CRLF;
+					r->complete = 1;
+					r->has_content_len = 1; /* hack to avoid error check */
+					p++;
+					goto skip;
+				}else{
+					r->state = H_SKIP_EMPTY;
+				}
+				break;
 #ifdef USE_STUN
 			case H_STUN_MSG:
 				if ((r->pos - r->body) >= sizeof(struct stun_hdr)) {
@@ -539,6 +576,7 @@
 	int resp;
 	long size;
 	struct tcp_req* req;
+	struct dest_info dst;
 	int s;
 	char c;
 	int ret;
@@ -639,6 +677,15 @@
 							   previous char, req->parsed should be ok
 							   because we always alloc BUF_SIZE+1 */
 			*req->parsed=0;
+
+			if (req->state==H_PING_CRLF) {
+				init_dst_from_rcv(&dst, &con->rcv);
+
+				if (tcp_send(&dst, 0, CRLF, CRLF_LEN) < 0) {
+					LOG(L_ERR, "CRLF ping: tcp_send() failed\n");
+				}
+				ret = 0;
+			}else
 #ifdef USE_STUN
 			if (unlikely(req->state==H_STUN_END)){
 				/* stun request */
_______________________________________________
Serdev mailing list
[email protected]
http://lists.iptel.org/mailman/listinfo/serdev

Reply via email to