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, 
... ...
@@ -92,6 +97,9 @@ enum tcp_req_states {	H_SKIP_EMPTY, H_SKIP_EMPTY_CR_FOUND, H_SKIP_EMPTY_CRLF_FOU
92 97
 #ifdef READ_HTTP11
93 98
 		, H_HTTP11_CHUNK_START, H_HTTP11_CHUNK_SIZE,
94 99
 		H_HTTP11_CHUNK_BODY, H_HTTP11_CHUNK_END, H_HTTP11_CHUNK_FINISH
100
+#endif
101
+#ifdef READ_MSRP
102
+		, H_MSRP_BODY, H_MSRP_BODY_LF, H_MSRP_BODY_END, H_MSRP_FINISH
95 103
 #endif
96 104
 	};
97 105
 
... ...
@@ -151,6 +159,11 @@ struct tcp_req{
151 159
 #ifdef READ_HTTP11
152 160
 #define F_TCP_REQ_BCHUNKED 4
153 161
 #endif
162
+#ifdef READ_MSRP
163
+#define F_TCP_REQ_MSRP_NO     8
164
+#define F_TCP_REQ_MSRP_FRAME  16
165
+#define F_TCP_REQ_MSRP_BODY   32
166
+#endif
154 167
 
155 168
 #define TCP_REQ_HAS_CLEN(tr)  ((tr)->flags & F_TCP_REQ_HAS_CLEN)
156 169
 #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 171
 
171 172
 	msg.s = c->req.start;
172 173
 	msg.len = c->req.pos - c->req.start;
174
+#ifdef READ_MSRP
175
+	/* skip if MSRP message */
176
+	if(c->req.flags&F_TCP_REQ_MSRP_FRAME)
177
+		return 0;
178
+#endif
173 179
 	p = parse_first_line(msg.s, msg.len, &fline);
174 180
 	if(p==NULL)
175 181
 		return 0;
... ...
@@ -366,12 +372,17 @@ int tcp_read_headers(struct tcp_connection *c, int* read_flags)
366 372
 	int bytes, remaining;
367 373
 	char *p;
368 374
 	struct tcp_req* r;
369
-	
375
+
370 376
 #ifdef USE_STUN
371 377
 	unsigned int mc;   /* magic cookie */
372 378
 	unsigned short body_len;
373 379
 #endif
374
-	
380
+
381
+#ifdef READ_MSRP
382
+	char *mfline;
383
+	str msessid;
384
+#endif
385
+
375 386
 	#define crlf_default_skip_case \
376 387
 					case '\n': \
377 388
 						r->state=H_LF; \
... ...
@@ -446,6 +457,19 @@ int tcp_read_headers(struct tcp_connection *c, int* read_flags)
446 457
 				 * in anything till end of line*/
447 458
 				p=q_memchr(p, '\n', r->pos-p);
448 459
 				if (p){
460
+#ifdef READ_MSRP
461
+					/* catch if it is MSRP or not with first '\n' */
462
+					if(!((r->flags&F_TCP_REQ_MSRP_NO)
463
+								|| (r->flags&F_TCP_REQ_MSRP_FRAME))) {
464
+						if((r->pos - r->start)>5
465
+									&& strncmp(r->start, "MSRP ", 5)==0)
466
+						{
467
+							r->flags |= F_TCP_REQ_MSRP_FRAME;
468
+						} else {
469
+							r->flags |= F_TCP_REQ_MSRP_NO;
470
+						}
471
+					}
472
+#endif
449 473
 					p++;
450 474
 					r->state=H_LF;
451 475
 				}else{
... ...
@@ -476,6 +500,18 @@ int tcp_read_headers(struct tcp_connection *c, int* read_flags)
476 500
 							r->error=TCP_REQ_BAD_LEN;
477 501
 						}
478 502
 						break;
503
+					case '-':
504
+						r->state=H_SKIP;
505
+#ifdef READ_MSRP
506
+						/* catch end of MSRP frame without body
507
+						 *     '-------sessid$\r\n'
508
+						 * follows headers wihtout extra CRLF */
509
+						if(r->flags&F_TCP_REQ_MSRP_FRAME) {
510
+							p--;
511
+							r->state=H_MSRP_BODY_END;
512
+						}
513
+#endif
514
+						break;
479 515
 					content_len_beg_case;
480 516
 					default: 
481 517
 						r->state=H_SKIP;
... ...
@@ -500,6 +536,20 @@ int tcp_read_headers(struct tcp_connection *c, int* read_flags)
500 536
 						}
501 537
 					}else{
502 538
 						if (cfg_get(tcp, tcp_cfg, accept_no_cl)!=0) {
539
+#ifdef READ_MSRP
540
+							/* if MSRP message */
541
+							if(c->req.flags&F_TCP_REQ_MSRP_FRAME)
542
+							{
543
+								r->body=p+1;
544
+								/* at least 3 bytes: 0\r\n */
545
+								r->bytes_to_go=3;
546
+								p++;
547
+								r->content_len = 0;
548
+								r->state=H_MSRP_BODY;
549
+								break;
550
+							}
551
+#endif
552
+
503 553
 #ifdef READ_HTTP11
504 554
 							if(TCP_REQ_BCHUNKED(r)) {
505 555
 								r->body=p+1;
... ...
@@ -851,6 +901,82 @@ int tcp_read_headers(struct tcp_connection *c, int* read_flags)
851 901
 				p++;
852 902
 				break;
853 903
 #endif
904
+#ifdef READ_MSRP
905
+			case H_MSRP_BODY: /* body of msrp frame */
906
+				/* find lf, we are in this state if we are not interested
907
+				 * in anything till end of line*/
908
+				r->flags |= F_TCP_REQ_MSRP_BODY;
909
+				p = q_memchr(p, '\n', r->pos-p);
910
+				if (p) {
911
+					p++;
912
+					r->state=H_MSRP_BODY_LF;
913
+				} else {
914
+					p=r->pos;
915
+				}
916
+				break;
917
+			case H_MSRP_BODY_LF: /* LF in body of msrp frame */
918
+				switch (*p) {
919
+					case '-':
920
+							p--;
921
+							r->state=H_MSRP_BODY_END;
922
+						break;
923
+					default:
924
+						r->state=H_MSRP_BODY;
925
+				}
926
+				p++;
927
+				break;
928
+			case H_MSRP_BODY_END: /* end of body for msrp frame */
929
+				/* find LF and check if it is end-line */
930
+				p = q_memchr(p, '\n', r->pos-p);
931
+				if (p) {
932
+					/* check if it is end line '-------sessid$\r\n' */
933
+					if(r->pos - r->start < 10) {
934
+						LM_ERR("weird situation when reading MSRP frame"
935
+								" - continue reading\n");
936
+						p++;
937
+						r->state=H_MSRP_BODY;
938
+						break;
939
+					}
940
+					if(*(p-1)!='\r') {
941
+						/* not ending in '\r\n' - not end-line */
942
+						p++;
943
+						r->state=H_MSRP_BODY;
944
+						break;
945
+					}
946
+					/* locate session id in first line
947
+					 * -- first line exists, that's why we are here */
948
+					mfline =  q_memchr(r->start, '\n', r->pos-r->start);
949
+					msessid.s = q_memchr(r->start + 5 /* 'MSRP ' */, ' ',
950
+							mfline - r->start);
951
+					msessid.len = msessid.s - r->start - 5;
952
+					msessid.s = r->start + 5;
953
+					trim(&msessid);
954
+					if(memcmp(msessid.s,
955
+							p - 1 /*\r*/ - 1 /* '+'|'#'|'$' */ - msessid.len,
956
+							msessid.len)!=0) {
957
+						/* no match on session id - not end-line */
958
+						p++;
959
+						r->state=H_MSRP_BODY;
960
+						break;
961
+					}
962
+					if(memcmp(p - 1 /*\r*/ - 1 /* '+'|'#'|'$' */ - msessid.len
963
+								- 7 /* 7 x '-' */ - 1 /* '\n' */, "\n-------",
964
+								8)!=0) {
965
+						/* no match on "\n-------" - not end-line */
966
+						p++;
967
+						r->state=H_MSRP_BODY;
968
+						break;
969
+					}
970
+					r->state=H_MSRP_FINISH;
971
+					r->flags|=F_TCP_REQ_COMPLETE;
972
+					p++;
973
+					goto skip;
974
+
975
+				} else {
976
+					p=r->pos;
977
+				}
978
+				break;
979
+#endif
854 980
 
855 981
 			default:
856 982
 				LOG(L_CRIT, "BUG: tcp_read_headers: unexpected state %d\n",
... ...
@@ -864,6 +990,15 @@ skip:
864 990
 }
865 991
 
866 992
 
993
+#ifdef READ_MSRP
994
+int msrp_process_msg(char* tcpbuf, unsigned int len,
995
+		struct receive_info* rcv_info, struct tcp_connection* con)
996
+{
997
+	LM_DBG("MSRP Message: [[>>>\n%.*s<<<]]\n", len, tcpbuf);
998
+	return 0;
999
+}
1000
+#endif
1001
+
867 1002
 /**
868 1003
  * @brief wrapper around receive_msg() to clone the tcpbuf content
869 1004
  *
... ...
@@ -872,7 +1007,8 @@ skip:
872 1007
  * the content of the stream. Safer, make a clone of buf content in a local
873 1008
  * buffer and give that to receive_msg() to link to msg->buf
874 1009
  */
875
-int receive_tcp_msg(char* tcpbuf, unsigned int len, struct receive_info* rcv_info)
1010
+int receive_tcp_msg(char* tcpbuf, unsigned int len,
1011
+		struct receive_info* rcv_info, struct tcp_connection* con)
876 1012
 {
877 1013
 #ifdef TCP_CLONE_RCVBUF
878 1014
 #ifdef DYN_BUF
... ...
@@ -884,8 +1020,13 @@ int receive_tcp_msg(char* tcpbuf, unsigned int len, struct receive_info* rcv_inf
884 1020
 	int blen;
885 1021
 
886 1022
 	/* cloning is disabled via parameter */
887
-	if(likely(tcp_clone_rcvbuf==0))
1023
+	if(likely(tcp_clone_rcvbuf==0)) {
1024
+#ifdef READ_MSRP
1025
+		if(unlikely(con->req.flags&F_TCP_REQ_MSRP_FRAME))
1026
+			return msrp_process_msg(tcpbuf, len, rcv_info, con);
1027
+#endif
888 1028
 		return receive_msg(tcpbuf, len, rcv_info);
1029
+	}
889 1030
 
890 1031
 	/* min buffer size is BUF_SIZE */
891 1032
 	blen = len;
... ...
@@ -923,8 +1064,16 @@ int receive_tcp_msg(char* tcpbuf, unsigned int len, struct receive_info* rcv_inf
923 1064
 
924 1065
 	memcpy(buf, tcpbuf, len);
925 1066
 	buf[len] = '\0';
1067
+#ifdef READ_MSRP
1068
+	if(unlikely(con->req.flags&F_TCP_REQ_MSRP_FRAME))
1069
+		return msrp_process_msg(buf, len, rcv_info, con);
1070
+#endif
926 1071
 	return receive_msg(buf, len, rcv_info);
927 1072
 #else /* TCP_CLONE_RCVBUF */
1073
+#ifdef READ_MSRP
1074
+	if(unlikely(con->req.flags&F_TCP_REQ_MSRP_FRAME))
1075
+		return msrp_process_msg(tcpbuf, len, rcv_info, con);
1076
+#endif
928 1077
 	return receive_msg(tcpbuf, len, rcv_info);
929 1078
 #endif /* TCP_CLONE_RCVBUF */
930 1079
 }
... ...
@@ -1046,17 +1195,25 @@ again:
1046 1195
 									 &con->rcv);
1047 1196
 			}else
1048 1197
 #endif
1198
+#ifdef READ_MSRP
1199
+			// if (unlikely(req->flags&F_TCP_REQ_MSRP_FRAME)){
1200
+			if (unlikely(req->state==H_MSRP_FINISH)){
1201
+				/* msrp frame */
1202
+				ret = receive_tcp_msg(req->start, req->parsed-req->start,
1203
+									&con->rcv, con);
1204
+			}else
1205
+#endif
1049 1206
 #ifdef READ_HTTP11
1050 1207
 			if (unlikely(req->state==H_HTTP11_CHUNK_FINISH)){
1051 1208
 				/* http chunked request */
1052 1209
 				req->body[req->content_len] = 0;
1053 1210
 				ret = receive_tcp_msg(req->start,
1054 1211
 						req->body + req->content_len - req->start,
1055
-						&con->rcv);
1212
+						&con->rcv, con);
1056 1213
 			}else
1057 1214
 #endif
1058 1215
 				ret = receive_tcp_msg(req->start, req->parsed-req->start,
1059
-									&con->rcv);
1216
+									&con->rcv, con);
1060 1217
 				
1061 1218
 			if (unlikely(ret < 0)) {
1062 1219
 				*req->parsed=c;