Browse code

core: Changed WS from being a flag on a TCP/TLS connection to a protocol in its own right

- Also added ;transport=ws parameter parsing for URIs

Peter Dunkley authored on 29/06/2012 16:44:15
Showing 12 changed files
... ...
@@ -526,6 +526,7 @@ TCP			"tcp"|"TCP"
526 526
 TLS			"tls"|"TLS"
527 527
 SCTP		"sctp"|"SCTP"
528 528
 WS		"ws"|"WS"
529
+WSS		"wss"|"WSS"
529 530
 INET		"inet"|"INET"
530 531
 INET6		"inet6"|"INET6"
531 532
 SSLv23			"sslv23"|"SSLv23"|"SSLV23"
... ...
@@ -1165,6 +1166,7 @@ IMPORTFILE      "import_file"
1165 1165
 <INITIAL>{TLS}			{ count(); return TLS; }
1166 1166
 <INITIAL>{SCTP}			{ count(); return SCTP; }
1167 1167
 <INITIAL>{WS}			{ count(); return WS; }
1168
+<INITIAL>{WSS}			{ count(); return WSS; }
1168 1169
 <INITIAL>{INET}			{ count(); yylval.intval=AF_INET;
1169 1170
 							yy_number_str=yytext; return NUMBER; }
1170 1171
 <INITIAL>{INET6}		{ count();
... ...
@@ -392,6 +392,7 @@ extern char *finame;
392 392
 %token TLS
393 393
 %token SCTP
394 394
 %token WS
395
+%token WSS
395 396
 
396 397
 /* config vars. */
397 398
 %token DEBUG_V
... ...
@@ -657,7 +658,7 @@ extern char *finame;
657 657
 %type <sockid>  id_lst
658 658
 %type <sockid>  phostport
659 659
 %type <sockid>  listen_phostport
660
-%type <intval> proto port
660
+%type <intval> proto eqproto port
661 661
 %type <intval> equalop strop cmpop rve_cmpop rve_equalop
662 662
 %type <intval> uri_type
663 663
 %type <attr> attr_id
... ...
@@ -772,6 +773,15 @@ proto:
772 772
 	| SCTP	{ $$=PROTO_SCTP; }
773 773
 	| STAR	{ $$=0; }
774 774
 	;
775
+eqproto:
776
+	UDP	{ $$=PROTO_UDP; }
777
+	| TCP	{ $$=PROTO_TCP; }
778
+	| TLS	{ $$=PROTO_TLS; }
779
+	| SCTP	{ $$=PROTO_SCTP; }
780
+	| WS	{ $$=PROTO_WS; }
781
+	| WSS	{ $$=PROTO_WSS; }
782
+	| STAR	{ $$=0; }
783
+	;
775 784
 port:
776 785
 	NUMBER	{ $$=$1; }
777 786
 	| STAR	{ $$=0; }
... ...
@@ -2202,22 +2212,18 @@ exp_elem:
2202 2202
 	| eint_op cmpop error   { $$=0; yyerror("number expected"); }
2203 2203
 	| eint_op equalop error { $$=0; yyerror("number expected"); }
2204 2204
 	| eint_op error { $$=0; yyerror("==, !=, <,>, >= or <=  expected"); }
2205
-	| PROTO equalop proto %prec EQUAL_T
2205
+	| PROTO equalop eqproto %prec EQUAL_T
2206 2206
 		{ $$=mk_elem($2, PROTO_O, 0, NUMBER_ST, (void*)$3 ); }
2207
-	| PROTO equalop WS %prec EQUAL_T
2208
-		{ $$=mk_elem($2, PROTO_O, 0, WEBSOCKET_ST, (void *)PROTO_WS ); }
2209 2207
 	| PROTO equalop rval_expr %prec EQUAL_T
2210 2208
 		{ $$=mk_elem($2, PROTO_O, 0, RVE_ST, $3 ); }
2211 2209
 	| PROTO equalop error
2212
-		{ $$=0; yyerror("protocol expected (udp, tcp, tls, sctp, or ws)"); }
2213
-	| SNDPROTO equalop proto %prec EQUAL_T
2210
+		{ $$=0; yyerror("protocol expected (udp, tcp, tls, sctp, ws, or wss)"); }
2211
+	| SNDPROTO equalop eqproto %prec EQUAL_T
2214 2212
 		{ $$=mk_elem($2, SNDPROTO_O, 0, NUMBER_ST, (void*)$3 ); }
2215
-	| SNDPROTO equalop WS %prec EQUAL_T
2216
-		{ $$=mk_elem($2, SNDPROTO_O, 0, WEBSOCKET_ST, (void *)PROTO_WS ); }
2217 2213
 	| SNDPROTO equalop rval_expr %prec EQUAL_T
2218 2214
 		{ $$=mk_elem($2, SNDPROTO_O, 0, RVE_ST, $3 ); }
2219 2215
 	| SNDPROTO equalop error
2220
-		{ $$=0; yyerror("protocol expected (udp, tcp, tls, sctp, ws)"); }
2216
+		{ $$=0; yyerror("protocol expected (udp, tcp, tls, sctp, ws, or wss)"); }
2221 2217
 	| eip_op strop ipnet %prec EQUAL_T { $$=mk_elem($2, $1, 0, NET_ST, $3); }
2222 2218
 	| eip_op strop rval_expr %prec EQUAL_T {
2223 2219
 			s_tmp.s=0;
... ...
@@ -319,6 +319,7 @@ not_forced:
319 319
 	 * eg: ipv4 -> ipv6 or ipv6 -> ipv4) */
320 320
 	switch(proto){
321 321
 #ifdef USE_TCP
322
+		case PROTO_WS:
322 323
 		case PROTO_TCP:
323 324
 		/* on tcp just use the "main address", we don't really now the
324 325
 		 * sending address (we can find it out, but we'll need also to see
... ...
@@ -140,11 +140,11 @@ static inline int msg_send(struct dest_info* dst, char* buf, int len)
140 140
 	sr_event_exec(SREV_NET_DATA_OUT, (void*)&outb);
141 141
 
142 142
 #ifdef USE_TCP
143
-	if (dst->proto == PROTO_TCP
143
+	if (unlikely((dst->proto == PROTO_WS
144 144
 #ifdef USE_TLS
145
-		|| dst->proto == PROTO_TLS
145
+		|| dst->proto == PROTO_WSS
146 146
 #endif
147
-	) {
147
+	) && sr_event_enabled(SREV_TCP_WS_FRAME_OUT))) {
148 148
 		if (unlikely(dst->send_flags.f & SND_F_FORCE_SOCKET
149 149
 				&& dst->send_sock)) {
150 150
 			local_addr = dst->send_sock->su;
... ...
@@ -152,29 +152,24 @@ static inline int msg_send(struct dest_info* dst, char* buf, int len)
152 152
 			from = &local_addr;
153 153
 		}
154 154
 
155
-		if (unlikely(sr_event_enabled(SREV_TCP_WS_FRAME_OUT))) {
156
-			port = su_getport(&dst->to);
157
-			if (likely(port)) {
158
-				su2ip_addr(&ip, &dst->to);
159
-				con = tcpconn_get(dst->id, &ip, port, from, 0);
160
-			}
161
-			else if (likely(dst->id))
162
-				con = tcpconn_get(dst->id, 0, 0, 0, 0);
163
-			else {
164
-				LM_CRIT("BUG: msg_send called with null_id & to\n");
165
-				return -1;
166
-			}
167
-
168
-			if (con && con->flags & F_CONN_WS)
169
-			{
170
-				memset(&wsev, 0, sizeof(ws_event_info_t));
171
-				wsev.type = SREV_TCP_WS_FRAME_OUT;
172
-				wsev.buf = outb.s;
173
-				wsev.len = outb.len;
174
-				wsev.id = con->id;
175
-				return sr_event_exec(SREV_TCP_WS_FRAME_OUT, (void *) &wsev);
176
-			}
155
+		port = su_getport(&dst->to);
156
+		if (likely(port)) {
157
+			su2ip_addr(&ip, &dst->to);
158
+			con = tcpconn_get(dst->id, &ip, port, from, 0);
177 159
 		}
160
+		else if (likely(dst->id))
161
+			con = tcpconn_get(dst->id, 0, 0, 0, 0);
162
+		else {
163
+			LM_CRIT("BUG: msg_send called with null_id & to\n");
164
+			return -1;
165
+		}
166
+
167
+		memset(&wsev, 0, sizeof(ws_event_info_t));
168
+		wsev.type = SREV_TCP_WS_FRAME_OUT;
169
+		wsev.buf = outb.s;
170
+		wsev.len = outb.len;
171
+		wsev.id = con->id;
172
+		return sr_event_exec(SREV_TCP_WS_FRAME_OUT, (void *) &wsev);
178 173
 	}
179 174
 #endif
180 175
 
... ...
@@ -203,6 +198,12 @@ static inline int msg_send(struct dest_info* dst, char* buf, int len)
203 203
 					" support is disabled\n");
204 204
 			goto error;
205 205
 		}else{
206
+			if (unlikely((dst->send_flags.f & SND_F_FORCE_SOCKET) &&
207
+						dst->send_sock)) {
208
+				local_addr=dst->send_sock->su;
209
+				su_setport(&local_addr, 0); /* any local port will do */
210
+				from=&local_addr;
211
+			}
206 212
 			if (unlikely(tcp_send(dst, from, outb.s, outb.len)<0)){
207 213
 				STATS_TX_DROPS;
208 214
 				LOG(L_ERR, "msg_send: ERROR: tcp_send failed\n");
... ...
@@ -218,6 +219,12 @@ static inline int msg_send(struct dest_info* dst, char* buf, int len)
218 218
 					" support is disabled\n");
219 219
 			goto error;
220 220
 		}else{
221
+			if (unlikely((dst->send_flags.f & SND_F_FORCE_SOCKET) &&
222
+						dst->send_sock)) {
223
+				local_addr=dst->send_sock->su;
224
+				su_setport(&local_addr, 0); /* any local port will do */
225
+				from=&local_addr;
226
+			}
221 227
 			if (unlikely(tcp_send(dst, from, outb.s, outb.len)<0)){
222 228
 				STATS_TX_DROPS;
223 229
 				LOG(L_ERR, "msg_send: ERROR: tcp_send failed\n");
... ...
@@ -52,7 +52,7 @@
52 52
 
53 53
 #include "dprint.h"
54 54
 
55
-enum sip_protos { PROTO_NONE, PROTO_UDP, PROTO_TCP, PROTO_TLS, PROTO_SCTP, PROTO_OTHER, PROTO_WS /* Deliberately after PROTO_(OTHER|LAST) */ };
55
+enum sip_protos { PROTO_NONE, PROTO_UDP, PROTO_TCP, PROTO_TLS, PROTO_SCTP, PROTO_WS, PROTO_WSS, PROTO_OTHER };
56 56
 #define PROTO_LAST PROTO_OTHER
57 57
 
58 58
 #ifdef USE_COMP
... ...
@@ -2394,6 +2394,8 @@ char* via_builder( unsigned int *len,
2394 2394
 		memcpy(line_buf+MY_VIA_LEN-4, "TLS ", 4);
2395 2395
 	}else if (send_info->proto==PROTO_SCTP){
2396 2396
 		memcpy(line_buf+MY_VIA_LEN-4, "SCTP ", 5);
2397
+	}else if (send_info->proto==PROTO_WS){
2398
+		memcpy(line_buf+MY_VIA_LEN-4, "WS ", 2);
2397 2399
 	}else{
2398 2400
 		LOG(L_CRIT, "BUG: via_builder: unknown proto %d\n", send_info->proto);
2399 2401
 		return 0;
... ...
@@ -106,7 +106,9 @@ int parse_uri(char* buf, int len, struct sip_uri* uri)
106 106
 					/* tls */
107 107
 					      VTLS_L, VTLS_S_FIN,
108 108
 					/* sctp */
109
-					VS_S, VS_C, VS_T, VS_P_FIN
109
+					VS_S, VS_C, VS_T, VS_P_FIN,
110
+					/* ws */
111
+					VW_W, VW_S_FIN
110 112
 	};
111 113
 	register enum states state;
112 114
 	char* s;
... ...
@@ -701,6 +703,11 @@ int parse_uri(char* buf, int len, struct sip_uri* uri)
701 701
 						v=p;
702 702
 						state=VS_S;
703 703
 						break;
704
+					case 'w':
705
+					case 'W':
706
+						v=p;
707
+						state=VW_W;
708
+						break;
704 709
 					default:
705 710
 						v=p;
706 711
 						state=URI_VAL_P;
... ...
@@ -728,6 +735,9 @@ int parse_uri(char* buf, int len, struct sip_uri* uri)
728 728
 			value_switch(VS_C, 't', 'T', VS_T);
729 729
 			value_switch(VS_T, 'p', 'P', VS_P_FIN);
730 730
 			transport_fin(VS_P_FIN, PROTO_SCTP);
731
+			/* ws */
732
+			value_switch(VW_W, 's', 'S', VW_S_FIN);
733
+			transport_fin(VW_S_FIN, PROTO_WS);
731 734
 			
732 735
 			/* ttl */
733 736
 			param_switch(PTTL_T2,  'l', 'L', PTTL_L);
... ...
@@ -1094,6 +1104,7 @@ int parse_uri(char* buf, int len, struct sip_uri* uri)
1094 1094
 		case VS_S:
1095 1095
 		case VS_C:
1096 1096
 		case VS_T:
1097
+		case VW_W:
1097 1098
 			uri->params.s=s;
1098 1099
 			uri->params.len=p-s;
1099 1100
 			param_set(b, v);
... ...
@@ -1139,6 +1150,12 @@ int parse_uri(char* buf, int len, struct sip_uri* uri)
1139 1139
 			param_set(b, v);
1140 1140
 			uri->proto=PROTO_SCTP;
1141 1141
 			break;
1142
+		case VW_S_FIN:
1143
+			uri->params.s=s;
1144
+			uri->params.len=p-s;
1145
+			param_set(b, v);
1146
+			uri->proto=PROTO_WS;
1147
+			break;
1142 1148
 #ifdef USE_COMP
1143 1149
 		case VCOMP_SIGC_P_FIN:
1144 1150
 			uri->params.s=s;
... ...
@@ -1393,6 +1410,7 @@ static str	s_udp  = STR_STATIC_INIT("udp");
1393 1393
 static str	s_tcp  = STR_STATIC_INIT("tcp");
1394 1394
 static str	s_tls  = STR_STATIC_INIT("tls");
1395 1395
 static str	s_sctp = STR_STATIC_INIT("sctp");
1396
+static str	s_ws   = STR_STATIC_INIT("ws");
1396 1397
 
1397 1398
 inline void proto_type_to_str(unsigned short type, str *s) {
1398 1399
 	switch (type) {
... ...
@@ -1408,6 +1426,9 @@ inline void proto_type_to_str(unsigned short type, str *s) {
1408 1408
 	case PROTO_SCTP:
1409 1409
 		*s = s_sctp;
1410 1410
 		break;
1411
+	case PROTO_WS:
1412
+		*s = s_ws;
1413
+		break;
1411 1414
 	default:
1412 1415
 		*s = s_null;
1413 1416
 	}
... ...
@@ -1374,13 +1374,13 @@ parse_again:
1374 1374
 					case WS_WSS2:
1375 1375
 						/* finished proto parsing */
1376 1376
 						vb->transport.len=tmp-vb->transport.s;
1377
-						vb->proto=PROTO_TCP;
1377
+						vb->proto=PROTO_WS;
1378 1378
 						state=F_HOST; /* start looking for host*/
1379 1379
 						goto main_via;
1380 1380
 					case FIN_WSS:
1381 1381
 						/* finished proto parsing */
1382 1382
 						vb->transport.len=tmp-vb->transport.s;
1383
-						vb->proto=PROTO_TLS;
1383
+						vb->proto=PROTO_WSS;
1384 1384
 						state=F_HOST; /* start looking for host*/
1385 1385
 						goto main_via;
1386 1386
 					case OTHER_PROTO:
... ...
@@ -1460,14 +1460,14 @@ parse_again:
1460 1460
 					case WS_WSS2:
1461 1461
 						/* finished proto parsing */
1462 1462
 						vb->transport.len=tmp-vb->transport.s;
1463
-						vb->proto=PROTO_TCP;
1463
+						vb->proto=PROTO_WS;
1464 1464
 						state=F_LF;
1465 1465
 						saved_state=F_HOST; /* start looking for host*/
1466 1466
 						goto main_via;
1467 1467
 					case FIN_WSS:
1468 1468
 						/* finished proto parsing */
1469 1469
 						vb->transport.len=tmp-vb->transport.s;
1470
-						vb->proto=PROTO_TLS;
1470
+						vb->proto=PROTO_WSS;
1471 1471
 						state=F_LF;
1472 1472
 						saved_state=F_HOST; /* start looking for host*/
1473 1473
 						goto main_via;
... ...
@@ -1552,13 +1552,13 @@ parse_again:
1552 1552
 						goto main_via;
1553 1553
 					case WS_WSS2:
1554 1554
 						vb->transport.len=tmp-vb->transport.s;
1555
-						vb->proto=PROTO_TCP;
1555
+						vb->proto=PROTO_WS;
1556 1556
 						state=F_CR;
1557 1557
 						saved_state=F_HOST;
1558 1558
 						goto main_via;
1559 1559
 					case FIN_WSS:
1560 1560
 						vb->transport.len=tmp-vb->transport.s;
1561
-						vb->proto=PROTO_TLS;
1561
+						vb->proto=PROTO_WSS;
1562 1562
 						state=F_CR;
1563 1563
 						saved_state=F_HOST;
1564 1564
 						goto main_via;
... ...
@@ -1231,7 +1231,6 @@ inline static int comp_num(int op, long left, int rtype, union exp_op* r,
1231 1231
 	pv_value_t pval;
1232 1232
 	avp_t* avp;
1233 1233
 	int right;
1234
-	struct tcp_connection *con;
1235 1234
 
1236 1235
 	if (unlikely(op==NO_OP)) return !(!left);
1237 1236
 	switch(rtype){
... ...
@@ -1261,14 +1260,6 @@ inline static int comp_num(int op, long left, int rtype, union exp_op* r,
1261 1261
 				return (op == DIFF_OP); /* not found or invalid type */
1262 1262
 			}
1263 1263
 			break;
1264
-		case WEBSOCKET_ST:
1265
-			if ((con = tcpconn_get(msg->rcv.proto_reserved1, 0, 0, 0, 0)) != NULL) {
1266
-				if (con->flags & F_CONN_WS)
1267
-					left = PROTO_WS;
1268
-			}
1269
-			right = r->numval;
1270
-			break;
1271
-
1272 1264
 		default:
1273 1265
 			LOG(L_CRIT, "BUG: comp_num: Invalid right operand (%d)\n", rtype);
1274 1266
 			return E_BUG;
... ...
@@ -476,6 +476,7 @@ struct socket_info** get_sock_info_list(unsigned short proto)
476 476
 			return &udp_listen;
477 477
 			break;
478 478
 		case PROTO_TCP:
479
+		case PROTO_WS:
479 480
 #ifdef USE_TCP
480 481
 			return &tcp_listen;
481 482
 #endif
... ...
@@ -75,7 +75,6 @@
75 75
 #define F_CONN_WANTS_RD  4096  /* conn. should be watched for READ */
76 76
 #define F_CONN_WANTS_WR  8192  /* conn. should be watched for WRITE */
77 77
 #define F_CONN_PASSIVE  16384 /* conn. created via accept() and not connect()*/
78
-#define F_CONN_WS	32768 /* conn. is a websocket */
79 78
 
80 79
 #ifndef NO_READ_HTTP11
81 80
 #define READ_HTTP11
... ...
@@ -1025,7 +1025,7 @@ static int tcp_read_ws(struct tcp_connection *c, int* read_flags)
1025 1025
 
1026 1026
 	r=&c->req;
1027 1027
 #ifdef USE_TLS
1028
-	if (unlikely(c->type == PROTO_TLS))
1028
+	if (unlikely(c->type == PROTO_WSS))
1029 1029
 		bytes = tls_read(c, read_flags);
1030 1030
 	else
1031 1031
 #endif
... ...
@@ -1168,7 +1168,7 @@ int receive_tcp_msg(char* tcpbuf, unsigned int len,
1168 1168
 			return msrp_process_msg(tcpbuf, len, rcv_info, con);
1169 1169
 #endif
1170 1170
 #ifdef READ_WS
1171
-		if(unlikely(con->flags & F_CONN_WS))
1171
+		if(unlikely(con->type == PROTO_WS || con->type == PROTO_WSS))
1172 1172
 			return ws_process_msg(tcpbuf, len, rcv_info, con);
1173 1173
 #endif
1174 1174
 
... ...
@@ -1216,7 +1216,7 @@ int receive_tcp_msg(char* tcpbuf, unsigned int len,
1216 1216
 		return msrp_process_msg(buf, len, rcv_info, con);
1217 1217
 #endif
1218 1218
 #ifdef READ_WS
1219
-	if(unlikely(con->flags & F_CONN_WS))
1219
+	if(unlikely(con->type == PROTO_WS || con->type == PROTO_WSS))
1220 1220
 		return ws_process_msg(buf, len, rcv_info, con);
1221 1221
 #endif
1222 1222
 	return receive_msg(buf, len, rcv_info);
... ...
@@ -1226,7 +1226,7 @@ int receive_tcp_msg(char* tcpbuf, unsigned int len,
1226 1226
 		return msrp_process_msg(tcpbuf, len, rcv_info, con);
1227 1227
 #endif
1228 1228
 #ifdef READ_WS
1229
-	if(unlikely(con->flags & F_CONN_WS))
1229
+	if(unlikely(con->type == PROTO_WS || con->type == PROTO_WSS))
1230 1230
 		return ws_process_msg(tcpbuf, len, rcv_info, con);
1231 1231
 #endif
1232 1232
 	return receive_msg(tcpbuf, len, rcv_info);
... ...
@@ -1252,7 +1252,7 @@ int tcp_read_req(struct tcp_connection* con, int* bytes_read, int* read_flags)
1252 1252
 again:
1253 1253
 		if (likely(req->error==TCP_REQ_OK)){
1254 1254
 #ifdef READ_WS
1255
-			if (unlikely(con->flags&F_CONN_WS))
1255
+			if (unlikely(con->type == PROTO_WS || con->type == PROTO_WSS))
1256 1256
 				bytes=tcp_read_ws(con, read_flags);
1257 1257
 			else
1258 1258
 #endif
... ...
@@ -1372,7 +1372,7 @@ again:
1372 1372
 			}else
1373 1373
 #endif
1374 1374
 #ifdef READ_WS
1375
-			if (unlikely(con->flags&F_CONN_WS)){
1375
+			if (unlikely(con->type == PROTO_WS || con->type == PROTO_WSS)){
1376 1376
 				ret = receive_tcp_msg(req->start, req->parsed-req->start,
1377 1377
 									&con->rcv, con);
1378 1378
 			}else