Module: sip-router Branch: master Commit: 122e01f35390aed08961726c18bc96dce3971234 URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=122e01f3...
Author: Daniel-Constantin Mierla miconda@gmail.com Committer: Daniel-Constantin Mierla miconda@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;