Browse code

core: tcp - added core parameter tcp_wait_data

- specify how long to wait (in milliseconds) to wait for data on tcp
connections in certain cases
- default is 5000ms (5secs)
- now applies when reading on tcp connection for haproxy protocol

Daniel-Constantin Mierla authored on 13/12/2021 13:42:50
Showing 5 changed files
... ...
@@ -422,6 +422,7 @@ TCP_OPT_ACCEPT_HEP3	"tcp_accept_hep3"
422 422
 TCP_OPT_ACCEPT_HAPROXY	"tcp_accept_haproxy"
423 423
 TCP_CLONE_RCVBUF	"tcp_clone_rcvbuf"
424 424
 TCP_REUSE_PORT		"tcp_reuse_port"
425
+TCP_WAIT_DATA	"tcp_wait_data"
425 426
 DISABLE_TLS		"disable_tls"|"tls_disable"
426 427
 ENABLE_TLS		"enable_tls"|"tls_enable"
427 428
 TLSLOG			"tlslog"|"tls_log"
... ...
@@ -916,6 +917,8 @@ IMPORTFILE      "import_file"
916 917
 <INITIAL>{TCP_CLONE_RCVBUF}		{ count(); yylval.strval=yytext;
917 918
 									return TCP_CLONE_RCVBUF; }
918 919
 <INITIAL>{TCP_REUSE_PORT}	{ count(); yylval.strval=yytext; return TCP_REUSE_PORT; }
920
+<INITIAL>{TCP_WAIT_DATA}	{ count(); yylval.strval=yytext;
921
+									return TCP_WAIT_DATA; }
919 922
 <INITIAL>{DISABLE_TLS}	{ count(); yylval.strval=yytext; return DISABLE_TLS; }
920 923
 <INITIAL>{ENABLE_TLS}	{ count(); yylval.strval=yytext; return ENABLE_TLS; }
921 924
 <INITIAL>{TLSLOG}		{ count(); yylval.strval=yytext; return TLS_PORT_NO; }
... ...
@@ -451,6 +451,7 @@ extern char *default_routename;
451 451
 %token TCP_OPT_ACCEPT_HAPROXY
452 452
 %token TCP_CLONE_RCVBUF
453 453
 %token TCP_REUSE_PORT
454
+%token TCP_WAIT_DATA
454 455
 %token DISABLE_TLS
455 456
 %token ENABLE_TLS
456 457
 %token TLSLOG
... ...
@@ -1319,6 +1320,14 @@ assign_stm:
1319 1320
 		#endif
1320 1321
 	}
1321 1322
 	| TCP_REUSE_PORT EQUAL error { yyerror("boolean value expected"); }
1323
+	| TCP_WAIT_DATA EQUAL intno {
1324
+		#ifdef USE_TCP
1325
+			tcp_default_cfg.wait_data_ms=$3;
1326
+		#else
1327
+			warn("tcp support not compiled in");
1328
+		#endif
1329
+	}
1330
+	| TCP_WAIT_DATA EQUAL error { yyerror("number expected"); }
1322 1331
 	| DISABLE_TLS EQUAL NUMBER {
1323 1332
 		#ifdef USE_TLS
1324 1333
 			tls_disable=$3;
... ...
@@ -908,6 +908,8 @@ int tcpconn_read_haproxy(struct tcp_connection *c) {
908 908
 	uint32_t size, port;
909 909
 	char *p, *end;
910 910
 	struct ip_addr *src_ip, *dst_ip;
911
+	int twaitms = 0;
912
+	int tsleepus = 0;
911 913
 
912 914
 	const char v2sig[12] = "\x0D\x0A\x0D\x0A\x00\x0D\x0A\x51\x55\x49\x54\x0A";
913 915
 
... ...
@@ -949,10 +951,35 @@ int tcpconn_read_haproxy(struct tcp_connection *c) {
949 951
 
950 952
 	} hdr;
951 953
 
954
+	if(cfg_get(tcp, tcp_cfg, wait_data_ms) > 10000) {
955
+		tsleepus = 100000;
956
+	} else if (cfg_get(tcp, tcp_cfg, wait_data_ms) < 1000) {
957
+		tsleepus = 50000;
958
+	} else {
959
+		tsleepus = 10 * cfg_get(tcp, tcp_cfg, wait_data_ms);
960
+	}
961
+
962
+	twaitms = 0;
952 963
 	do {
953 964
 		bytes = recv(c->s, &hdr, sizeof(hdr), MSG_PEEK);
954
-	} while (bytes == -1 && (errno == EINTR || errno == EAGAIN));
965
+		if(bytes==-1 && (errno == EINTR || errno == EAGAIN)) {
966
+			if(twaitms <= cfg_get(tcp, tcp_cfg, wait_data_ms)) {
967
+				/* LM_DBG("bytes: %d - errno: %d (%d/%d) - twait: %dms\n", bytes,
968
+						errno, EINTR, EAGAIN, twaitms); */
969
+				sleep_us(tsleepus);
970
+				twaitms += tsleepus/1000;
971
+			} else {
972
+				break;
973
+			}
974
+		} else {
975
+			break;
976
+		}
977
+	} while (1);
955 978
 
979
+	if(bytes == -1) {
980
+		/* no data received during tcp_wait_data */
981
+		return -1;
982
+	}
956 983
 	/* copy original tunnel address details */
957 984
 	memcpy(&c->cinfo.src_ip, &c->rcv.src_ip, sizeof(ip_addr_t));
958 985
 	memcpy(&c->cinfo.dst_ip, &c->rcv.dst_ip, sizeof(ip_addr_t));
... ...
@@ -1115,8 +1142,21 @@ int tcpconn_read_haproxy(struct tcp_connection *c) {
1115 1142
 
1116 1143
 done:
1117 1144
 	/* we need to consume the appropriate amount of data from the socket */
1145
+	twaitms = 0;
1118 1146
 	do {
1119 1147
 		bytes = recv(c->s, &hdr, size, 0);
1148
+		if(bytes==-1 && errno == EINTR)) {
1149
+			if(twaitms <= cfg_get(tcp, tcp_cfg, wait_data_ms)) {
1150
+				/* LM_DBG("bytes: %d - errno: %d (%d/%d) - twait: %dms\n", bytes,
1151
+						errno, EINTR, EAGAIN, twaitms); */
1152
+				sleep_us(tsleepus);
1153
+				twaitms += tsleepus/1000;
1154
+			} else {
1155
+				break;
1156
+			}
1157
+		} else {
1158
+			break;
1159
+		}
1120 1160
 	} while (bytes == -1 && errno == EINTR);
1121 1161
 
1122 1162
 	return (bytes >= 0) ? retval : -1;
... ...
@@ -108,6 +108,8 @@ static cfg_def_t tcp_cfg_def[] = {
108 108
 		"accept TCP messages without Content-Length "},
109 109
 	{ "reuse_port",   CFG_VAR_INT | CFG_ATOMIC,   0,        1,  0,         0,
110 110
 		"reuse TCP ports "},
111
+	{ "wait_data_ms",  CFG_VAR_INT | CFG_ATOMIC,      0, 7200000, 0,        0,
112
+		"wait for data on new tcp connetions (milliseconds)"},
111 113
 	/* internal and/or "fixed" versions of some vars
112 114
 	   (not supposed to be writeable, read will provide only debugging value*/
113 115
 	{ "rd_buf_size", CFG_VAR_INT | CFG_ATOMIC,    512,    16777216,  0,         0,
... ...
@@ -164,6 +166,7 @@ void init_tcp_options()
164 166
 	tcp_default_cfg.rd_buf_size=DEFAULT_TCP_BUF_SIZE;
165 167
 	tcp_default_cfg.wq_blk_size=DEFAULT_TCP_WBUF_SIZE;
166 168
 	tcp_default_cfg.reuse_port=0;
169
+	tcp_default_cfg.wait_data_ms=5000;
167 170
 }
168 171
 
169 172
 
... ...
@@ -138,6 +138,7 @@ struct cfg_group_tcp{
138 138
 	int new_conn_alias_flags;
139 139
 	int accept_no_cl;  /* on/off - accept messages without content-length */
140 140
 	int reuse_port;  /* enable SO_REUSEPORT */
141
+	int wait_data_ms;  /* wait for data in milliseconds */
141 142
 
142 143
 	/* internal, "fixed" vars */
143 144
 	unsigned int rd_buf_size; /* read buffer size (should be > max. datagram)*/