Browse code

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

Daniel-Constantin Mierla authored on 13/01/2012 11:17:24
Showing 2 changed files
... ...
@@ -80,10 +80,15 @@
80 80
 #define READ_HTTP11
81 81
 #endif
82 82
 
83
+#ifndef NO_READ_MSRP
84
+#define READ_MSRP
85
+#endif
86
+
83 87
 enum tcp_req_errors {	TCP_REQ_INIT, TCP_REQ_OK, TCP_READ_ERROR,
84 88
 						TCP_REQ_OVERRUN, TCP_REQ_BAD_LEN };
85
-enum tcp_req_states {	H_SKIP_EMPTY, H_SKIP_EMPTY_CR_FOUND, H_SKIP_EMPTY_CRLF_FOUND, H_SKIP_EMPTY_CRLFCR_FOUND,
86
-			H_SKIP, H_LF, H_LFCR,  H_BODY, H_STARTWS,
89
+enum tcp_req_states {	H_SKIP_EMPTY, H_SKIP_EMPTY_CR_FOUND,
90
+		H_SKIP_EMPTY_CRLF_FOUND, H_SKIP_EMPTY_CRLFCR_FOUND,
91
+		H_SKIP, H_LF, H_LFCR,  H_BODY, H_STARTWS,
87 92
 		H_CONT_LEN1, H_CONT_LEN2, H_CONT_LEN3, H_CONT_LEN4, H_CONT_LEN5,
88 93
 		H_CONT_LEN6, H_CONT_LEN7, H_CONT_LEN8, H_CONT_LEN9, H_CONT_LEN10,
89 94
 		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
93 93
 		, H_HTTP11_CHUNK_START, H_HTTP11_CHUNK_SIZE,
94 94
 		H_HTTP11_CHUNK_BODY, H_HTTP11_CHUNK_END, H_HTTP11_CHUNK_FINISH
95 95
 #endif
96
+#ifdef READ_MSRP
97
+		, H_MSRP_BODY, H_MSRP_BODY_LF, H_MSRP_BODY_END, H_MSRP_FINISH
98
+#endif
96 99
 	};
97 100
 
98 101
 enum tcp_conn_states { S_CONN_ERROR=-2, S_CONN_BAD=-1,
... ...
@@ -151,6 +159,11 @@ struct tcp_req{
151 151
 #ifdef READ_HTTP11
152 152
 #define F_TCP_REQ_BCHUNKED 4
153 153
 #endif
154
+#ifdef READ_MSRP
155
+#define F_TCP_REQ_MSRP_NO     8
156
+#define F_TCP_REQ_MSRP_FRAME  16
157
+#define F_TCP_REQ_MSRP_BODY   32
158
+#endif
154 159
 
155 160
 #define TCP_REQ_HAS_CLEN(tr)  ((tr)->flags & F_TCP_REQ_HAS_CLEN)
156 161
 #define TCP_REQ_COMPLETE(tr)  ((tr)->flags & F_TCP_REQ_COMPLETE)
... ...
@@ -79,6 +79,7 @@
79 79
 #include "timer.h"
80 80
 #include "local_timer.h"
81 81
 #include "ut.h"
82
+#include "trim.h"
82 83
 #include "pt.h"
83 84
 #include "cfg/cfg_struct.h"
84 85
 #ifdef CORE_TLS
... ...
@@ -170,6 +171,11 @@ int tcp_http11_continue(struct tcp_connection *c)
170 170
 
171 171
 	msg.s = c->req.start;
172 172
 	msg.len = c->req.pos - c->req.start;
173
+#ifdef READ_MSRP
174
+	/* skip if MSRP message */
175
+	if(c->req.flags&F_TCP_REQ_MSRP_FRAME)
176
+		return 0;
177
+#endif
173 178
 	p = parse_first_line(msg.s, msg.len, &fline);
174 179
 	if(p==NULL)
175 180
 		return 0;
... ...
@@ -366,12 +372,17 @@ int tcp_read_headers(struct tcp_connection *c, int* read_flags)
366 366
 	int bytes, remaining;
367 367
 	char *p;
368 368
 	struct tcp_req* r;
369
-	
369
+
370 370
 #ifdef USE_STUN
371 371
 	unsigned int mc;   /* magic cookie */
372 372
 	unsigned short body_len;
373 373
 #endif
374
-	
374
+
375
+#ifdef READ_MSRP
376
+	char *mfline;
377
+	str msessid;
378
+#endif
379
+
375 380
 	#define crlf_default_skip_case \
376 381
 					case '\n': \
377 382
 						r->state=H_LF; \
... ...
@@ -446,6 +457,19 @@ int tcp_read_headers(struct tcp_connection *c, int* read_flags)
446 446
 				 * in anything till end of line*/
447 447
 				p=q_memchr(p, '\n', r->pos-p);
448 448
 				if (p){
449
+#ifdef READ_MSRP
450
+					/* catch if it is MSRP or not with first '\n' */
451
+					if(!((r->flags&F_TCP_REQ_MSRP_NO)
452
+								|| (r->flags&F_TCP_REQ_MSRP_FRAME))) {
453
+						if((r->pos - r->start)>5
454
+									&& strncmp(r->start, "MSRP ", 5)==0)
455
+						{
456
+							r->flags |= F_TCP_REQ_MSRP_FRAME;
457
+						} else {
458
+							r->flags |= F_TCP_REQ_MSRP_NO;
459
+						}
460
+					}
461
+#endif
449 462
 					p++;
450 463
 					r->state=H_LF;
451 464
 				}else{
... ...
@@ -476,6 +500,18 @@ int tcp_read_headers(struct tcp_connection *c, int* read_flags)
476 476
 							r->error=TCP_REQ_BAD_LEN;
477 477
 						}
478 478
 						break;
479
+					case '-':
480
+						r->state=H_SKIP;
481
+#ifdef READ_MSRP
482
+						/* catch end of MSRP frame without body
483
+						 *     '-------sessid$\r\n'
484
+						 * follows headers wihtout extra CRLF */
485
+						if(r->flags&F_TCP_REQ_MSRP_FRAME) {
486
+							p--;
487
+							r->state=H_MSRP_BODY_END;
488
+						}
489
+#endif
490
+						break;
479 491
 					content_len_beg_case;
480 492
 					default: 
481 493
 						r->state=H_SKIP;
... ...
@@ -500,6 +536,20 @@ int tcp_read_headers(struct tcp_connection *c, int* read_flags)
500 500
 						}
501 501
 					}else{
502 502
 						if (cfg_get(tcp, tcp_cfg, accept_no_cl)!=0) {
503
+#ifdef READ_MSRP
504
+							/* if MSRP message */
505
+							if(c->req.flags&F_TCP_REQ_MSRP_FRAME)
506
+							{
507
+								r->body=p+1;
508
+								/* at least 3 bytes: 0\r\n */
509
+								r->bytes_to_go=3;
510
+								p++;
511
+								r->content_len = 0;
512
+								r->state=H_MSRP_BODY;
513
+								break;
514
+							}
515
+#endif
516
+
503 517
 #ifdef READ_HTTP11
504 518
 							if(TCP_REQ_BCHUNKED(r)) {
505 519
 								r->body=p+1;
... ...
@@ -851,6 +901,82 @@ int tcp_read_headers(struct tcp_connection *c, int* read_flags)
851 851
 				p++;
852 852
 				break;
853 853
 #endif
854
+#ifdef READ_MSRP
855
+			case H_MSRP_BODY: /* body of msrp frame */
856
+				/* find lf, we are in this state if we are not interested
857
+				 * in anything till end of line*/
858
+				r->flags |= F_TCP_REQ_MSRP_BODY;
859
+				p = q_memchr(p, '\n', r->pos-p);
860
+				if (p) {
861
+					p++;
862
+					r->state=H_MSRP_BODY_LF;
863
+				} else {
864
+					p=r->pos;
865
+				}
866
+				break;
867
+			case H_MSRP_BODY_LF: /* LF in body of msrp frame */
868
+				switch (*p) {
869
+					case '-':
870
+							p--;
871
+							r->state=H_MSRP_BODY_END;
872
+						break;
873
+					default:
874
+						r->state=H_MSRP_BODY;
875
+				}
876
+				p++;
877
+				break;
878
+			case H_MSRP_BODY_END: /* end of body for msrp frame */
879
+				/* find LF and check if it is end-line */
880
+				p = q_memchr(p, '\n', r->pos-p);
881
+				if (p) {
882
+					/* check if it is end line '-------sessid$\r\n' */
883
+					if(r->pos - r->start < 10) {
884
+						LM_ERR("weird situation when reading MSRP frame"
885
+								" - continue reading\n");
886
+						p++;
887
+						r->state=H_MSRP_BODY;
888
+						break;
889
+					}
890
+					if(*(p-1)!='\r') {
891
+						/* not ending in '\r\n' - not end-line */
892
+						p++;
893
+						r->state=H_MSRP_BODY;
894
+						break;
895
+					}
896
+					/* locate session id in first line
897
+					 * -- first line exists, that's why we are here */
898
+					mfline =  q_memchr(r->start, '\n', r->pos-r->start);
899
+					msessid.s = q_memchr(r->start + 5 /* 'MSRP ' */, ' ',
900
+							mfline - r->start);
901
+					msessid.len = msessid.s - r->start - 5;
902
+					msessid.s = r->start + 5;
903
+					trim(&msessid);
904
+					if(memcmp(msessid.s,
905
+							p - 1 /*\r*/ - 1 /* '+'|'#'|'$' */ - msessid.len,
906
+							msessid.len)!=0) {
907
+						/* no match on session id - not end-line */
908
+						p++;
909
+						r->state=H_MSRP_BODY;
910
+						break;
911
+					}
912
+					if(memcmp(p - 1 /*\r*/ - 1 /* '+'|'#'|'$' */ - msessid.len
913
+								- 7 /* 7 x '-' */ - 1 /* '\n' */, "\n-------",
914
+								8)!=0) {
915
+						/* no match on "\n-------" - not end-line */
916
+						p++;
917
+						r->state=H_MSRP_BODY;
918
+						break;
919
+					}
920
+					r->state=H_MSRP_FINISH;
921
+					r->flags|=F_TCP_REQ_COMPLETE;
922
+					p++;
923
+					goto skip;
924
+
925
+				} else {
926
+					p=r->pos;
927
+				}
928
+				break;
929
+#endif
854 930
 
855 931
 			default:
856 932
 				LOG(L_CRIT, "BUG: tcp_read_headers: unexpected state %d\n",
... ...
@@ -864,6 +990,15 @@ skip:
864 864
 }
865 865
 
866 866
 
867
+#ifdef READ_MSRP
868
+int msrp_process_msg(char* tcpbuf, unsigned int len,
869
+		struct receive_info* rcv_info, struct tcp_connection* con)
870
+{
871
+	LM_DBG("MSRP Message: [[>>>\n%.*s<<<]]\n", len, tcpbuf);
872
+	return 0;
873
+}
874
+#endif
875
+
867 876
 /**
868 877
  * @brief wrapper around receive_msg() to clone the tcpbuf content
869 878
  *
... ...
@@ -872,7 +1007,8 @@ skip:
872 872
  * the content of the stream. Safer, make a clone of buf content in a local
873 873
  * buffer and give that to receive_msg() to link to msg->buf
874 874
  */
875
-int receive_tcp_msg(char* tcpbuf, unsigned int len, struct receive_info* rcv_info)
875
+int receive_tcp_msg(char* tcpbuf, unsigned int len,
876
+		struct receive_info* rcv_info, struct tcp_connection* con)
876 877
 {
877 878
 #ifdef TCP_CLONE_RCVBUF
878 879
 #ifdef DYN_BUF
... ...
@@ -884,8 +1020,13 @@ int receive_tcp_msg(char* tcpbuf, unsigned int len, struct receive_info* rcv_inf
884 884
 	int blen;
885 885
 
886 886
 	/* cloning is disabled via parameter */
887
-	if(likely(tcp_clone_rcvbuf==0))
887
+	if(likely(tcp_clone_rcvbuf==0)) {
888
+#ifdef READ_MSRP
889
+		if(unlikely(con->req.flags&F_TCP_REQ_MSRP_FRAME))
890
+			return msrp_process_msg(tcpbuf, len, rcv_info, con);
891
+#endif
888 892
 		return receive_msg(tcpbuf, len, rcv_info);
893
+	}
889 894
 
890 895
 	/* min buffer size is BUF_SIZE */
891 896
 	blen = len;
... ...
@@ -923,8 +1064,16 @@ int receive_tcp_msg(char* tcpbuf, unsigned int len, struct receive_info* rcv_inf
923 923
 
924 924
 	memcpy(buf, tcpbuf, len);
925 925
 	buf[len] = '\0';
926
+#ifdef READ_MSRP
927
+	if(unlikely(con->req.flags&F_TCP_REQ_MSRP_FRAME))
928
+		return msrp_process_msg(buf, len, rcv_info, con);
929
+#endif
926 930
 	return receive_msg(buf, len, rcv_info);
927 931
 #else /* TCP_CLONE_RCVBUF */
932
+#ifdef READ_MSRP
933
+	if(unlikely(con->req.flags&F_TCP_REQ_MSRP_FRAME))
934
+		return msrp_process_msg(tcpbuf, len, rcv_info, con);
935
+#endif
928 936
 	return receive_msg(tcpbuf, len, rcv_info);
929 937
 #endif /* TCP_CLONE_RCVBUF */
930 938
 }
... ...
@@ -1046,17 +1195,25 @@ again:
1046 1046
 									 &con->rcv);
1047 1047
 			}else
1048 1048
 #endif
1049
+#ifdef READ_MSRP
1050
+			// if (unlikely(req->flags&F_TCP_REQ_MSRP_FRAME)){
1051
+			if (unlikely(req->state==H_MSRP_FINISH)){
1052
+				/* msrp frame */
1053
+				ret = receive_tcp_msg(req->start, req->parsed-req->start,
1054
+									&con->rcv, con);
1055
+			}else
1056
+#endif
1049 1057
 #ifdef READ_HTTP11
1050 1058
 			if (unlikely(req->state==H_HTTP11_CHUNK_FINISH)){
1051 1059
 				/* http chunked request */
1052 1060
 				req->body[req->content_len] = 0;
1053 1061
 				ret = receive_tcp_msg(req->start,
1054 1062
 						req->body + req->content_len - req->start,
1055
-						&con->rcv);
1063
+						&con->rcv, con);
1056 1064
 			}else
1057 1065
 #endif
1058 1066
 				ret = receive_tcp_msg(req->start, req->parsed-req->start,
1059
-									&con->rcv);
1067
+									&con->rcv, con);
1060 1068
 				
1061 1069
 			if (unlikely(ret < 0)) {
1062 1070
 				*req->parsed=c;