[sr-dev] git:master: core/tcp: support for receiving MSRP messages

Daniel-Constantin Mierla miconda at gmail.com
Mon Jan 16 22:45:49 CET 2012


Module: sip-router
Branch: master
Commit: 122e01f35390aed08961726c18bc96dce3971234
URL:    http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=122e01f35390aed08961726c18bc96dce3971234

Author: Daniel-Constantin Mierla <miconda at gmail.com>
Committer: Daniel-Constantin Mierla <miconda at gmail.com>
Date:   Fri Jan 13 12:17:24 2012 +0100

core/tcp: support for receiving MSRP messages

- controlled by define READ_MSRP, on by default now, can be turned off
  by defininf NO_READ_MSRP

---

 tcp_conn.h |   17 +++++-
 tcp_read.c |  169 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 178 insertions(+), 8 deletions(-)

diff --git a/tcp_conn.h b/tcp_conn.h
index 4328208..fe9cc00 100644
--- a/tcp_conn.h
+++ b/tcp_conn.h
@@ -80,10 +80,15 @@
 #define READ_HTTP11
 #endif
 
+#ifndef NO_READ_MSRP
+#define READ_MSRP
+#endif
+
 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_EMPTY_CR_FOUND, H_SKIP_EMPTY_CRLF_FOUND, H_SKIP_EMPTY_CRLFCR_FOUND,
-			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, 
@@ -93,6 +98,9 @@ enum tcp_req_states {	H_SKIP_EMPTY, H_SKIP_EMPTY_CR_FOUND, H_SKIP_EMPTY_CRLF_FOU
 		, H_HTTP11_CHUNK_START, H_HTTP11_CHUNK_SIZE,
 		H_HTTP11_CHUNK_BODY, H_HTTP11_CHUNK_END, H_HTTP11_CHUNK_FINISH
 #endif
+#ifdef READ_MSRP
+		, H_MSRP_BODY, H_MSRP_BODY_LF, H_MSRP_BODY_END, H_MSRP_FINISH
+#endif
 	};
 
 enum tcp_conn_states { S_CONN_ERROR=-2, S_CONN_BAD=-1,
@@ -151,6 +159,11 @@ struct tcp_req{
 #ifdef READ_HTTP11
 #define F_TCP_REQ_BCHUNKED 4
 #endif
+#ifdef READ_MSRP
+#define F_TCP_REQ_MSRP_NO     8
+#define F_TCP_REQ_MSRP_FRAME  16
+#define F_TCP_REQ_MSRP_BODY   32
+#endif
 
 #define TCP_REQ_HAS_CLEN(tr)  ((tr)->flags & F_TCP_REQ_HAS_CLEN)
 #define TCP_REQ_COMPLETE(tr)  ((tr)->flags & F_TCP_REQ_COMPLETE)
diff --git a/tcp_read.c b/tcp_read.c
index dde2f94..bdbd041 100644
--- a/tcp_read.c
+++ b/tcp_read.c
@@ -79,6 +79,7 @@
 #include "timer.h"
 #include "local_timer.h"
 #include "ut.h"
+#include "trim.h"
 #include "pt.h"
 #include "cfg/cfg_struct.h"
 #ifdef CORE_TLS
@@ -170,6 +171,11 @@ int tcp_http11_continue(struct tcp_connection *c)
 
 	msg.s = c->req.start;
 	msg.len = c->req.pos - c->req.start;
+#ifdef READ_MSRP
+	/* skip if MSRP message */
+	if(c->req.flags&F_TCP_REQ_MSRP_FRAME)
+		return 0;
+#endif
 	p = parse_first_line(msg.s, msg.len, &fline);
 	if(p==NULL)
 		return 0;
@@ -366,12 +372,17 @@ int tcp_read_headers(struct tcp_connection *c, int* read_flags)
 	int bytes, remaining;
 	char *p;
 	struct tcp_req* r;
-	
+
 #ifdef USE_STUN
 	unsigned int mc;   /* magic cookie */
 	unsigned short body_len;
 #endif
-	
+
+#ifdef READ_MSRP
+	char *mfline;
+	str msessid;
+#endif
+
 	#define crlf_default_skip_case \
 					case '\n': \
 						r->state=H_LF; \
@@ -446,6 +457,19 @@ int tcp_read_headers(struct tcp_connection *c, int* read_flags)
 				 * in anything till end of line*/
 				p=q_memchr(p, '\n', r->pos-p);
 				if (p){
+#ifdef READ_MSRP
+					/* catch if it is MSRP or not with first '\n' */
+					if(!((r->flags&F_TCP_REQ_MSRP_NO)
+								|| (r->flags&F_TCP_REQ_MSRP_FRAME))) {
+						if((r->pos - r->start)>5
+									&& strncmp(r->start, "MSRP ", 5)==0)
+						{
+							r->flags |= F_TCP_REQ_MSRP_FRAME;
+						} else {
+							r->flags |= F_TCP_REQ_MSRP_NO;
+						}
+					}
+#endif
 					p++;
 					r->state=H_LF;
 				}else{
@@ -476,6 +500,18 @@ int tcp_read_headers(struct tcp_connection *c, int* read_flags)
 							r->error=TCP_REQ_BAD_LEN;
 						}
 						break;
+					case '-':
+						r->state=H_SKIP;
+#ifdef READ_MSRP
+						/* catch end of MSRP frame without body
+						 *     '-------sessid$\r\n'
+						 * follows headers wihtout extra CRLF */
+						if(r->flags&F_TCP_REQ_MSRP_FRAME) {
+							p--;
+							r->state=H_MSRP_BODY_END;
+						}
+#endif
+						break;
 					content_len_beg_case;
 					default: 
 						r->state=H_SKIP;
@@ -500,6 +536,20 @@ int tcp_read_headers(struct tcp_connection *c, int* read_flags)
 						}
 					}else{
 						if (cfg_get(tcp, tcp_cfg, accept_no_cl)!=0) {
+#ifdef READ_MSRP
+							/* if MSRP message */
+							if(c->req.flags&F_TCP_REQ_MSRP_FRAME)
+							{
+								r->body=p+1;
+								/* at least 3 bytes: 0\r\n */
+								r->bytes_to_go=3;
+								p++;
+								r->content_len = 0;
+								r->state=H_MSRP_BODY;
+								break;
+							}
+#endif
+
 #ifdef READ_HTTP11
 							if(TCP_REQ_BCHUNKED(r)) {
 								r->body=p+1;
@@ -851,6 +901,82 @@ int tcp_read_headers(struct tcp_connection *c, int* read_flags)
 				p++;
 				break;
 #endif
+#ifdef READ_MSRP
+			case H_MSRP_BODY: /* body of msrp frame */
+				/* find lf, we are in this state if we are not interested
+				 * in anything till end of line*/
+				r->flags |= F_TCP_REQ_MSRP_BODY;
+				p = q_memchr(p, '\n', r->pos-p);
+				if (p) {
+					p++;
+					r->state=H_MSRP_BODY_LF;
+				} else {
+					p=r->pos;
+				}
+				break;
+			case H_MSRP_BODY_LF: /* LF in body of msrp frame */
+				switch (*p) {
+					case '-':
+							p--;
+							r->state=H_MSRP_BODY_END;
+						break;
+					default:
+						r->state=H_MSRP_BODY;
+				}
+				p++;
+				break;
+			case H_MSRP_BODY_END: /* end of body for msrp frame */
+				/* find LF and check if it is end-line */
+				p = q_memchr(p, '\n', r->pos-p);
+				if (p) {
+					/* check if it is end line '-------sessid$\r\n' */
+					if(r->pos - r->start < 10) {
+						LM_ERR("weird situation when reading MSRP frame"
+								" - continue reading\n");
+						p++;
+						r->state=H_MSRP_BODY;
+						break;
+					}
+					if(*(p-1)!='\r') {
+						/* not ending in '\r\n' - not end-line */
+						p++;
+						r->state=H_MSRP_BODY;
+						break;
+					}
+					/* locate session id in first line
+					 * -- first line exists, that's why we are here */
+					mfline =  q_memchr(r->start, '\n', r->pos-r->start);
+					msessid.s = q_memchr(r->start + 5 /* 'MSRP ' */, ' ',
+							mfline - r->start);
+					msessid.len = msessid.s - r->start - 5;
+					msessid.s = r->start + 5;
+					trim(&msessid);
+					if(memcmp(msessid.s,
+							p - 1 /*\r*/ - 1 /* '+'|'#'|'$' */ - msessid.len,
+							msessid.len)!=0) {
+						/* no match on session id - not end-line */
+						p++;
+						r->state=H_MSRP_BODY;
+						break;
+					}
+					if(memcmp(p - 1 /*\r*/ - 1 /* '+'|'#'|'$' */ - msessid.len
+								- 7 /* 7 x '-' */ - 1 /* '\n' */, "\n-------",
+								8)!=0) {
+						/* no match on "\n-------" - not end-line */
+						p++;
+						r->state=H_MSRP_BODY;
+						break;
+					}
+					r->state=H_MSRP_FINISH;
+					r->flags|=F_TCP_REQ_COMPLETE;
+					p++;
+					goto skip;
+
+				} else {
+					p=r->pos;
+				}
+				break;
+#endif
 
 			default:
 				LOG(L_CRIT, "BUG: tcp_read_headers: unexpected state %d\n",
@@ -864,6 +990,15 @@ skip:
 }
 
 
+#ifdef READ_MSRP
+int msrp_process_msg(char* tcpbuf, unsigned int len,
+		struct receive_info* rcv_info, struct tcp_connection* con)
+{
+	LM_DBG("MSRP Message: [[>>>\n%.*s<<<]]\n", len, tcpbuf);
+	return 0;
+}
+#endif
+
 /**
  * @brief wrapper around receive_msg() to clone the tcpbuf content
  *
@@ -872,7 +1007,8 @@ skip:
  * the content of the stream. Safer, make a clone of buf content in a local
  * buffer and give that to receive_msg() to link to msg->buf
  */
-int receive_tcp_msg(char* tcpbuf, unsigned int len, struct receive_info* rcv_info)
+int receive_tcp_msg(char* tcpbuf, unsigned int len,
+		struct receive_info* rcv_info, struct tcp_connection* con)
 {
 #ifdef TCP_CLONE_RCVBUF
 #ifdef DYN_BUF
@@ -884,8 +1020,13 @@ int receive_tcp_msg(char* tcpbuf, unsigned int len, struct receive_info* rcv_inf
 	int blen;
 
 	/* cloning is disabled via parameter */
-	if(likely(tcp_clone_rcvbuf==0))
+	if(likely(tcp_clone_rcvbuf==0)) {
+#ifdef READ_MSRP
+		if(unlikely(con->req.flags&F_TCP_REQ_MSRP_FRAME))
+			return msrp_process_msg(tcpbuf, len, rcv_info, con);
+#endif
 		return receive_msg(tcpbuf, len, rcv_info);
+	}
 
 	/* min buffer size is BUF_SIZE */
 	blen = len;
@@ -923,8 +1064,16 @@ int receive_tcp_msg(char* tcpbuf, unsigned int len, struct receive_info* rcv_inf
 
 	memcpy(buf, tcpbuf, len);
 	buf[len] = '\0';
+#ifdef READ_MSRP
+	if(unlikely(con->req.flags&F_TCP_REQ_MSRP_FRAME))
+		return msrp_process_msg(buf, len, rcv_info, con);
+#endif
 	return receive_msg(buf, len, rcv_info);
 #else /* TCP_CLONE_RCVBUF */
+#ifdef READ_MSRP
+	if(unlikely(con->req.flags&F_TCP_REQ_MSRP_FRAME))
+		return msrp_process_msg(tcpbuf, len, rcv_info, con);
+#endif
 	return receive_msg(tcpbuf, len, rcv_info);
 #endif /* TCP_CLONE_RCVBUF */
 }
@@ -1046,17 +1195,25 @@ again:
 									 &con->rcv);
 			}else
 #endif
+#ifdef READ_MSRP
+			// if (unlikely(req->flags&F_TCP_REQ_MSRP_FRAME)){
+			if (unlikely(req->state==H_MSRP_FINISH)){
+				/* msrp frame */
+				ret = receive_tcp_msg(req->start, req->parsed-req->start,
+									&con->rcv, con);
+			}else
+#endif
 #ifdef READ_HTTP11
 			if (unlikely(req->state==H_HTTP11_CHUNK_FINISH)){
 				/* http chunked request */
 				req->body[req->content_len] = 0;
 				ret = receive_tcp_msg(req->start,
 						req->body + req->content_len - req->start,
-						&con->rcv);
+						&con->rcv, con);
 			}else
 #endif
 				ret = receive_tcp_msg(req->start, req->parsed-req->start,
-									&con->rcv);
+									&con->rcv, con);
 				
 			if (unlikely(ret < 0)) {
 				*req->parsed=c;




More information about the sr-dev mailing list