Browse code

- tcp: support for pending connects: add a connection immediately to the connection hash (before even attempting the connect sys call) and just queue possible writes. When the connection completes update the connection info & aliases and send the queued data. This avoids parallel connects when the intial connect takes too long (highly experimental, on by default)

Andrei Pelinescu-Onciul authored on 21/12/2007 17:58:07
Showing 6 changed files
... ...
@@ -78,7 +78,7 @@ MAIN_NAME=ser
78 78
 VERSION = 2
79 79
 PATCHLEVEL = 1
80 80
 SUBLEVEL =  0
81
-EXTRAVERSION = -dev15
81
+EXTRAVERSION = -dev16-tcp
82 82
 
83 83
 SER_VER = $(shell expr $(VERSION) \* 1000000 + $(PATCHLEVEL) \* 1000 + \
84 84
 			$(SUBLEVEL) )
... ...
@@ -562,9 +562,10 @@ static void core_tcp_options(rpc_t* rpc, void* c)
562 562
 	if (!tcp_disable){
563 563
 		tcp_options_get(&t);
564 564
 		rpc->add(c, "{", &handle);
565
-		rpc->struct_add(handle, "ddddddddddddd",
565
+		rpc->struct_add(handle, "dddddddddddddd",
566 566
 			"fd_cache",		t.fd_cache,
567 567
 			"tcp_buf_write",	t.tcp_buf_write,
568
+			"tcp_connect_wait",	t.tcp_connect_wait,
568 569
 			"tcpconn_wq_max",	t.tcpconn_wq_max,
569 570
 			"tcp_wq_max",	t.tcp_wq_max,
570 571
 			"tcp_wq_timeout",	TICKS_TO_S(t.tcp_wq_timeout),
... ...
@@ -72,7 +72,9 @@
72 72
 #define F_CONN_READER       4 /* handled by a tcp reader */
73 73
 #define F_CONN_WRITE_W      8 /* watched for write (main) */
74 74
 #define F_CONN_HASHED      16 /* in tcp_main hash */
75
-#define F_CONN_FD_CLOSED   32 /* in tcp_main hash */
75
+#define F_CONN_FD_CLOSED   32 /* fd was already closed */
76
+#define F_CONN_PENDING     64 /* pending connect  (fd not known yet in main) */
77
+#define F_CONN_MAIN_TIMER 128 /* timer active in the tcp_main process */
76 78
 
77 79
 
78 80
 enum tcp_req_errors {	TCP_REQ_INIT, TCP_REQ_OK, TCP_READ_ERROR,
... ...
@@ -87,12 +89,13 @@ enum tcp_req_states {	H_SKIP_EMPTY, H_SKIP, H_LF, H_LFCR,  H_BODY, H_STARTWS,
87 87
 
88 88
 enum tcp_conn_states { S_CONN_ERROR=-2, S_CONN_BAD=-1, S_CONN_OK=0, 
89 89
 						S_CONN_INIT, S_CONN_EOF, 
90
-						S_CONN_ACCEPT, S_CONN_CONNECT };
90
+						S_CONN_ACCEPT, S_CONN_CONNECT, S_CONN_PENDING };
91 91
 
92 92
 
93 93
 /* fd communication commands */
94 94
 enum conn_cmds { CONN_DESTROY=-3, CONN_ERROR=-2, CONN_EOF=-1, CONN_RELEASE, 
95
-					CONN_GET_FD, CONN_NEW, CONN_QUEUED_WRITE };
95
+					CONN_GET_FD, CONN_NEW, CONN_QUEUED_WRITE,
96
+					CONN_NEW_PENDING_WRITE, CONN_NEW_COMPLETE };
96 97
 /* CONN_RELEASE, EOF, ERROR, DESTROY can be used by "reader" processes
97 98
  * CONN_GET_FD, NEW, ERROR only by writers */
98 99
 
... ...
@@ -91,6 +91,8 @@
91 91
  *  2007-12-12  destroy connection asap on wbuf. timeout (andrei)
92 92
  *  2007-12-13  changed the refcnt and destroy scheme, now refcnt is 1 if
93 93
  *                linked into the hash tables (was 0) (andrei)
94
+ *  2007-12-21  support for pending connects (connections are added to the
95
+ *               hash immediately and writes on them are buffered) (andrei)
94 96
  */
95 97
 
96 98
 
... ...
@@ -864,61 +866,60 @@ error:
864 864
 
865 865
 
866 866
 
867
-struct tcp_connection* tcpconn_connect( union sockaddr_union* server, 
868
-										union sockaddr_union* from,
869
-										int type)
867
+/* do the actual connect, set sock. options a.s.o
868
+ * returns socket on success, -1 on error
869
+ * sets also *res_local_addr, res_si and state (S_CONN_CONNECT for an
870
+ * unfinished connect and S_CONN_OK for a finished one)*/
871
+inline static int tcp_do_connect(	union sockaddr_union* server,
872
+									union sockaddr_union* from,
873
+									int type,
874
+									union sockaddr_union* res_local_addr,
875
+									struct socket_info** res_si,
876
+									enum tcp_conn_states *state
877
+									)
870 878
 {
871 879
 	int s;
872
-	struct socket_info* si;
873 880
 	union sockaddr_union my_name;
874 881
 	socklen_t my_name_len;
875
-	struct tcp_connection* con;
876 882
 	struct ip_addr ip;
877
-	enum tcp_conn_states state;
878 883
 #ifdef TCP_BUF_WRITE
879 884
 	int n;
880 885
 #endif /* TCP_BUF_WRITE */
881 886
 
882
-	s=-1;
883
-	
884
-	if (*tcp_connections_no >= tcp_max_connections){
885
-		LOG(L_ERR, "ERROR: tcpconn_connect: maximum number of connections"
886
-					" exceeded (%d/%d)\n",
887
-					*tcp_connections_no, tcp_max_connections);
888
-		goto error;
889
-	}
890 887
 	s=socket(AF2PF(server->s.sa_family), SOCK_STREAM, 0);
891
-	if (s==-1){
892
-		LOG(L_ERR, "ERROR: tcpconn_connect: socket: (%d) %s\n",
888
+	if (unlikely(s==-1)){
889
+		LOG(L_ERR, "ERROR: tcp_do_connect: socket: (%d) %s\n",
893 890
 				errno, strerror(errno));
894 891
 		goto error;
895 892
 	}
896 893
 	if (init_sock_opt(s)<0){
897
-		LOG(L_ERR, "ERROR: tcpconn_connect: init_sock_opt failed\n");
894
+		LOG(L_ERR, "ERROR: tcp_do_connect: init_sock_opt failed\n");
898 895
 		goto error;
899 896
 	}
900 897
 	
901
-	if (from && bind(s, &from->s, sockaddru_len(*from)) != 0)
902
-		LOG(L_WARN, "WARNING: tcpconn_connect: binding to source address"
898
+	if (unlikely(from && bind(s, &from->s, sockaddru_len(*from)) != 0)){
899
+		LOG(L_WARN, "WARNING: tcp_do_connect: binding to source address"
903 900
 					" failed: %s [%d]\n", strerror(errno), errno);
904
-	state=S_CONN_OK;
901
+	}
902
+	*state=S_CONN_OK;
905 903
 #ifdef TCP_BUF_WRITE
906 904
 	if (likely(tcp_options.tcp_buf_write)){
907 905
 again:
908 906
 		n=connect(s, &server->s, sockaddru_len(*server));
909 907
 		if (unlikely(n==-1)){
910 908
 			if (errno==EINTR) goto again;
911
-			if (errno!=EINPROGRESS && errno!=EALREADY){
912
-				LOG(L_ERR, "ERROR: tcpconn_connect: connect: (%d) %s\n",
909
+			if (likely(errno==EINPROGRESS))
910
+				*state=S_CONN_CONNECT;
911
+			else if (errno!=EALREADY){
912
+				LOG(L_ERR, "ERROR: tcp_do_connect: connect: (%d) %s\n",
913 913
 						errno, strerror(errno));
914 914
 				goto error;
915 915
 			}
916
-			state=S_CONN_CONNECT;
917 916
 		}
918 917
 	}else{
919 918
 #endif /* TCP_BUF_WRITE */
920 919
 		if (tcp_blocking_connect(s, &server->s, sockaddru_len(*server))<0){
921
-			LOG(L_ERR, "ERROR: tcpconn_connect: tcp_blocking_connect"
920
+			LOG(L_ERR, "ERROR: tcp_do_connect: tcp_blocking_connect"
922 921
 						" failed\n");
923 922
 			goto error;
924 923
 		}
... ...
@@ -932,31 +933,64 @@ again:
932 932
 			goto find_socket;
933 933
 	}
934 934
 	my_name_len=sizeof(my_name);
935
-	if (getsockname(s, &my_name.s, &my_name_len)!=0){
936
-		LOG(L_ERR, "ERROR: tcp_connect: getsockname failed: %s(%d)\n",
935
+	if (unlikely(getsockname(s, &my_name.s, &my_name_len)!=0)){
936
+		LOG(L_ERR, "ERROR: tcp_do_connect: getsockname failed: %s(%d)\n",
937 937
 				strerror(errno), errno);
938
-		si=0; /* try to go on */
939
-		goto skip;
938
+		*res_si=0;
939
+		goto error;
940 940
 	}
941 941
 	from=&my_name; /* update from with the real "from" address */
942 942
 	su2ip_addr(&ip, &my_name);
943 943
 find_socket:
944 944
 #ifdef USE_TLS
945
-	if (type==PROTO_TLS)
946
-		si=find_si(&ip, 0, PROTO_TLS);
945
+	if (unlikely(type==PROTO_TLS))
946
+		*res_si=find_si(&ip, 0, PROTO_TLS);
947 947
 	else
948 948
 #endif
949
-		si=find_si(&ip, 0, PROTO_TCP);
950
-skip:
951
-	if (si==0){
952
-		LOG(L_WARN, "WARNING: tcp_connect: could not find corresponding"
949
+		*res_si=find_si(&ip, 0, PROTO_TCP);
950
+	
951
+	if (unlikely(*res_si==0)){
952
+		LOG(L_WARN, "WARNING: tcp_do_connect: could not find corresponding"
953 953
 				" listening socket, using default...\n");
954
-		if (server->s.sa_family==AF_INET) si=sendipv4_tcp;
954
+		if (server->s.sa_family==AF_INET) *res_si=sendipv4_tcp;
955 955
 #ifdef USE_IPV6
956
-		else si=sendipv6_tcp;
956
+		else *res_si=sendipv6_tcp;
957 957
 #endif
958 958
 	}
959
-	con=tcpconn_new(s, server, from, si,  type, state);
959
+	*res_local_addr=*from;
960
+	return s;
961
+error:
962
+	if (s!=-1) close(s);
963
+	return -1;
964
+}
965
+
966
+
967
+
968
+struct tcp_connection* tcpconn_connect( union sockaddr_union* server, 
969
+										union sockaddr_union* from,
970
+										int type)
971
+{
972
+	int s;
973
+	struct socket_info* si;
974
+	union sockaddr_union my_name;
975
+	struct tcp_connection* con;
976
+	enum tcp_conn_states state;
977
+
978
+	s=-1;
979
+	
980
+	if (*tcp_connections_no >= tcp_max_connections){
981
+		LOG(L_ERR, "ERROR: tcpconn_connect: maximum number of connections"
982
+					" exceeded (%d/%d)\n",
983
+					*tcp_connections_no, tcp_max_connections);
984
+		goto error;
985
+	}
986
+	s=tcp_do_connect(server, from, type, &my_name, &si, &state);
987
+	if (s==-1){
988
+		LOG(L_ERR, "ERROR: tcp_do_connect: failed (%d) %s\n",
989
+				errno, strerror(errno));
990
+		goto error;
991
+	}
992
+	con=tcpconn_new(s, server, &my_name, si, type, state);
960 993
 	if (con==0){
961 994
 		LOG(L_ERR, "ERROR: tcp_connect: tcpconn_new failed, closing the "
962 995
 				 " socket\n");
... ...
@@ -971,6 +1005,59 @@ error:
971 971
 
972 972
 
973 973
 
974
+#ifdef TCP_CONNECT_WAIT
975
+int tcpconn_finish_connect( struct tcp_connection* c,
976
+												union sockaddr_union* from)
977
+{
978
+	int s;
979
+	int r;
980
+	union sockaddr_union local_addr;
981
+	struct socket_info* si;
982
+	enum tcp_conn_states state;
983
+	struct tcp_conn_alias* a;
984
+	
985
+	s=tcp_do_connect(&c->rcv.src_su, from, c->type, &local_addr, &si, &state);
986
+	if (unlikely(s==-1)){
987
+		LOG(L_ERR, "ERROR: tcpconn_finish_connect: tcp_do_connect for %p"
988
+						" failed\n", c);
989
+		return -1;
990
+	}
991
+	c->rcv.bind_address=si;
992
+	su2ip_addr(&c->rcv.dst_ip, &local_addr);
993
+	c->rcv.dst_port=su_getport(&local_addr);
994
+	/* update aliases if needed */
995
+	if (likely(from==0)){
996
+		/* add aliases */
997
+		TCPCONN_LOCK;
998
+		_tcpconn_add_alias_unsafe(c, c->rcv.src_port, &c->rcv.dst_ip, 0,
999
+													tcp_new_conn_alias_flags);
1000
+		_tcpconn_add_alias_unsafe(c, c->rcv.src_port, &c->rcv.dst_ip,
1001
+									c->rcv.dst_port, tcp_new_conn_alias_flags);
1002
+		TCPCONN_UNLOCK;
1003
+	}else if (su_cmp(from, &local_addr)!=1){
1004
+		TCPCONN_LOCK;
1005
+			/* remove all the aliases except the first one and re-add them
1006
+			 * (there shouldn't be more then the 3 default aliases at this 
1007
+			 * stage) */
1008
+			for (r=1; r<c->aliases; r++){
1009
+				a=&c->con_aliases[r];
1010
+				tcpconn_listrm(tcpconn_aliases_hash[a->hash], a, next, prev);
1011
+			}
1012
+			c->aliases=1;
1013
+			/* add the local_ip:0 and local_ip:local_port aliases */
1014
+			_tcpconn_add_alias_unsafe(c, c->rcv.src_port, &c->rcv.dst_ip,
1015
+												0, tcp_new_conn_alias_flags);
1016
+			_tcpconn_add_alias_unsafe(c, c->rcv.src_port, &c->rcv.dst_ip,
1017
+									c->rcv.dst_port, tcp_new_conn_alias_flags);
1018
+		TCPCONN_UNLOCK;
1019
+	}
1020
+	
1021
+	return s;
1022
+}
1023
+#endif /* TCP_CONNECT_WAIT */
1024
+
1025
+
1026
+
974 1027
 /* adds a tcp connection to the tcpconn hashes
975 1028
  * Note: it's called _only_ from the tcp_main process */
976 1029
 inline static struct tcp_connection*  tcpconn_add(struct tcp_connection *c)
... ...
@@ -994,10 +1081,12 @@ inline static struct tcp_connection*  tcpconn_add(struct tcp_connection *c)
994 994
 		 *   -- for finding if a fully specified connection exists */
995 995
 		_tcpconn_add_alias_unsafe(c, c->rcv.src_port, &zero_ip, 0,
996 996
 													tcp_new_conn_alias_flags);
997
-		_tcpconn_add_alias_unsafe(c, c->rcv.src_port, &c->rcv.dst_ip, 0,
997
+		if (likely(c->rcv.dst_ip.af && ! ip_addr_any(&c->rcv.dst_ip))){
998
+			_tcpconn_add_alias_unsafe(c, c->rcv.src_port, &c->rcv.dst_ip, 0,
998 999
 													tcp_new_conn_alias_flags);
999
-		_tcpconn_add_alias_unsafe(c, c->rcv.src_port, &c->rcv.dst_ip,
1000
+			_tcpconn_add_alias_unsafe(c, c->rcv.src_port, &c->rcv.dst_ip,
1000 1001
 									c->rcv.dst_port, tcp_new_conn_alias_flags);
1002
+		}
1001 1003
 		/* ignore add_alias errors, there are some valid cases when one
1002 1004
 		 *  of the add_alias would fail (e.g. first add_alias for 2 connections
1003 1005
 		 *   with the same destination but different src. ip*/
... ...
@@ -1407,6 +1496,98 @@ no_id:
1407 1407
 						break;
1408 1408
 				}
1409 1409
 			}
1410
+#if defined(TCP_CONNECT_WAIT) && defined(TCP_BUF_WRITE)
1411
+			if (likely(tcp_options.tcp_connect_wait && 
1412
+						tcp_options.tcp_buf_write )){
1413
+				/* FIXME: flag for timer? + check again */
1414
+				if (unlikely(*tcp_connections_no >= tcp_max_connections)){
1415
+					LOG(L_ERR, "ERROR: tcp_send: maximum number of connections"
1416
+								" exceeded (%d/%d)\n",
1417
+								*tcp_connections_no, tcp_max_connections);
1418
+					return -1;
1419
+				}
1420
+				c=tcpconn_new(-1, &dst->to, from, 0, dst->proto,
1421
+								S_CONN_PENDING);
1422
+				if (unlikely(c==0)){
1423
+					LOG(L_ERR, "ERROR: tcp_send: could not create new"
1424
+							" connection\n");
1425
+					return -1;
1426
+				}
1427
+				c->flags|=F_CONN_PENDING|F_CONN_FD_CLOSED;
1428
+				atomic_set(&c->refcnt, 2); /* ref from here and from main hash
1429
+											 table */
1430
+				/* add it to id hash and aliases */
1431
+				if (unlikely(tcpconn_add(c)==0)){
1432
+					LOG(L_ERR, "ERROR: tcp_send: could not add "
1433
+									"connection %p\n", c);
1434
+					_tcpconn_free(c);
1435
+					n=-1;
1436
+					goto end_no_conn;
1437
+				}
1438
+				/* do connect and if src ip or port changed, update the 
1439
+				 * aliases */
1440
+				if (unlikely((fd=tcpconn_finish_connect(c, from))<0)){
1441
+					LOG(L_ERR, "ERROR: tcp_send: tcpconn_finsish_connect(%p)"
1442
+							" failed\n", c);
1443
+					goto conn_wait_error;
1444
+				}
1445
+				/* ? TODO: it might be faster just to queue the write directly
1446
+				 *  and send to main CONN_NEW_PENDING_WRITE */
1447
+				/* delay sending the fd to main after the send */
1448
+				
1449
+				/* NOTE: no lock here, because the connection is marked as
1450
+				 * pending and nobody else will try to write on it. However
1451
+				 * this might produce out-of-order writes. If this is not
1452
+				 * desired either lock before the write or use 
1453
+				 * _wbufq_insert(...) */
1454
+				n=_tcpconn_write_nb(fd, c, buf, len);
1455
+				if (unlikely(n<0)){
1456
+					if (errno==EAGAIN|| errno==EWOULDBLOCK){
1457
+						DBG("tcp_send: pending write on new connection (%p)\n",
1458
+								c);
1459
+						/* add to the write queue */
1460
+						lock_get(&c->write_lock);
1461
+							if (unlikely(_wbufq_add(c, buf, len)<0)){
1462
+								lock_release(&c->write_lock);
1463
+								n=-1;
1464
+								LOG(L_ERR, "ERROR: tcp_send: EAGAIN and"
1465
+										" write queue full or failed for %p\n",
1466
+										c);
1467
+								goto conn_wait_error;
1468
+							}
1469
+						lock_release(&c->write_lock);
1470
+						/* send to tcp_main */
1471
+						response[0]=(long)c;
1472
+						response[1]=CONN_NEW_PENDING_WRITE;
1473
+						if (unlikely(send_fd(unix_tcp_sock, response, 
1474
+												sizeof(response), fd) <= 0)){
1475
+							LOG(L_ERR, "BUG: tcp_send: CONN_NEW_PENDING_WRITE"
1476
+										" for %p failed:" " %s (%d)\n",
1477
+										c, strerror(errno), errno);
1478
+							goto conn_wait_error;
1479
+						}
1480
+						goto end;
1481
+					}
1482
+					/* error: destroy it directly */
1483
+					LOG(L_ERR, "ERROR: tcp_send: connect & send "
1484
+										" for %p failed:" " %s (%d)\n",
1485
+										c, strerror(errno), errno);
1486
+					goto conn_wait_error;
1487
+				}
1488
+				LOG(L_INFO, "tcp_send: quick connect for %p\n", c);
1489
+				/* send to tcp_main */
1490
+				response[0]=(long)c;
1491
+				response[1]=CONN_NEW_COMPLETE;
1492
+				if (unlikely(send_fd(unix_tcp_sock, response, 
1493
+										sizeof(response), fd) <= 0)){
1494
+					LOG(L_ERR, "BUG: tcp_send: CONN_NEW_COMPLETE  for %p"
1495
+								" failed:" " %s (%d)\n",
1496
+								c, strerror(errno), errno);
1497
+					goto conn_wait_error;
1498
+				}
1499
+				goto end;
1500
+			}
1501
+#endif /* TCP_CONNECT_WAIT  && TCP_BUF_WRITE */
1410 1502
 			if (unlikely((c=tcpconn_connect(&dst->to, from, dst->proto))==0)){
1411 1503
 				LOG(L_ERR, "ERROR: tcp_send: connect failed\n");
1412 1504
 				return -1;
... ...
@@ -1414,6 +1595,9 @@ no_id:
1414 1414
 			atomic_set(&c->refcnt, 2); /* ref. from here and it will also
1415 1415
 			                              be added in the tcp_main hash */
1416 1416
 			fd=c->s;
1417
+			c->flags|=F_CONN_FD_CLOSED; /* not yet opened in main */
1418
+			/* ? TODO: it might be faster just to queue the write and
1419
+			 * send to main a CONN_NEW_PENDING_WRITE */
1417 1420
 			
1418 1421
 			/* send the new tcpconn to "tcp main" */
1419 1422
 			response[0]=(long)c;
... ...
@@ -1432,9 +1616,18 @@ no_id:
1432 1432
 get_fd:
1433 1433
 #ifdef TCP_BUF_WRITE
1434 1434
 		/* if data is already queued, we don't need the fd any more */
1435
-		if (unlikely(tcp_options.tcp_buf_write && _wbufq_non_empty(c))){
1435
+		if (unlikely(tcp_options.tcp_buf_write && (_wbufq_non_empty(c)
1436
+#ifdef TCP_CONNECT_WAIT
1437
+												|| (c->state==S_CONN_PENDING)
1438
+#endif /* TCP_CONNECT_WAIT */
1439
+						) )){
1436 1440
 			lock_get(&c->write_lock);
1437
-				if (likely(_wbufq_non_empty(c))){
1441
+				if (likely(_wbufq_non_empty(c)
1442
+#ifdef TCP_CONNECT_WAIT
1443
+							|| (c->state==S_CONN_PENDING)
1444
+#endif /* TCP_CONNECT_WAIT */
1445
+
1446
+							)){
1438 1447
 					do_close_fd=0;
1439 1448
 					if (unlikely(_wbufq_add(c, buf, len)<0)){
1440 1449
 						lock_release(&c->write_lock);
... ...
@@ -1503,7 +1696,11 @@ send_it:
1503 1503
 	lock_get(&c->write_lock);
1504 1504
 #ifdef TCP_BUF_WRITE
1505 1505
 	if (likely(tcp_options.tcp_buf_write)){
1506
-		if (_wbufq_non_empty(c)){
1506
+		if (_wbufq_non_empty(c)
1507
+#ifdef TCP_CONNECT_WAIT
1508
+			|| (c->state==S_CONN_PENDING) 
1509
+#endif /* TCP_CONNECT_WAIT */
1510
+			){
1507 1511
 			if (unlikely(_wbufq_add(c, buf, len)<0)){
1508 1512
 				lock_release(&c->write_lock);
1509 1513
 				n=-1;
... ...
@@ -1528,7 +1725,8 @@ send_it:
1528 1528
 #else /* ! TCP_BUF_WRITE */
1529 1529
 	lock_release(&c->write_lock);
1530 1530
 #endif /* TCP_BUF_WRITE */
1531
-	DBG("tcp_send: after write: c= %p n=%d fd=%d\n",c, n, fd);
1531
+	
1532
+	DBG("tcp_send: after real write: c= %p n=%d fd=%d\n",c, n, fd);
1532 1533
 	DBG("tcp_send: buf=\n%.*s\n", (int)len, buf);
1533 1534
 	if (unlikely(n<0)){
1534 1535
 #ifdef TCP_BUF_WRITE
... ...
@@ -1542,12 +1740,12 @@ send_it:
1542 1542
 			}
1543 1543
 			lock_release(&c->write_lock);
1544 1544
 			n=len;
1545
-			if (enable_write_watch){
1545
+			if (likely(enable_write_watch)){
1546 1546
 				response[0]=(long)c;
1547 1547
 				response[1]=CONN_QUEUED_WRITE;
1548
-				if (send_all(unix_tcp_sock, response, sizeof(response))<=0){
1548
+				if (send_all(unix_tcp_sock, response, sizeof(response)) <= 0){
1549 1549
 					LOG(L_ERR, "BUG: tcp_send: error return failed "
1550
-							"(write):%s (%d)\n", strerror(errno), errno);
1550
+								"(write):%s (%d)\n", strerror(errno), errno);
1551 1551
 					n=-1;
1552 1552
 					goto error;
1553 1553
 				}
... ...
@@ -1556,9 +1754,12 @@ send_it:
1556 1556
 		}else{
1557 1557
 			lock_release(&c->write_lock);
1558 1558
 		}
1559
+#endif /* TCP_BUF_WRITE */
1560
+		LOG(L_ERR, "ERROR: tcp_send: failed to send on %p: %s (%d)\n",
1561
+					c, strerror(errno), errno);
1562
+#ifdef TCP_BUF_WRITE
1559 1563
 error:
1560 1564
 #endif /* TCP_BUF_WRITE */
1561
-		LOG(L_ERR, "ERROR: tcp_send: failed to send\n");
1562 1565
 		/* error on the connection , mark it as bad and set 0 timeout */
1563 1566
 		c->state=S_CONN_BAD;
1564 1567
 		c->timeout=get_ticks_raw();
... ...
@@ -1566,9 +1767,9 @@ error:
1566 1566
 		response[0]=(long)c;
1567 1567
 		response[1]=CONN_ERROR;
1568 1568
 		if (send_all(unix_tcp_sock, response, sizeof(response))<=0){
1569
-			LOG(L_ERR, "BUG: tcp_send: error return failed (write):%s (%d)\n",
1569
+			LOG(L_CRIT, "BUG: tcp_send: error return failed (write):%s (%d)\n",
1570 1570
 					strerror(errno), errno);
1571
-			tcpconn_chld_put(c); /* deref. it manually & free on 0 */
1571
+			tcpconn_chld_put(c); /* deref. it manually */
1572 1572
 			n=-1;
1573 1573
 		}
1574 1574
 		/* CONN_ERROR will auto-dec refcnt => we must not call tcpconn_put 
... ...
@@ -1604,6 +1805,30 @@ release_c:
1604 1604
 	tcpconn_chld_put(c); /* release c (dec refcnt & free on 0) */
1605 1605
 end_no_conn:
1606 1606
 	return n;
1607
+#ifdef TCP_CONNECT_WAIT
1608
+conn_wait_error:
1609
+	/* connect or send failed on newly created connection which was not
1610
+	 * yet sent to tcp_main (but was already hashed) => don't send to main,
1611
+	 * unhash and destroy directly (if refcnt>2 it will be destroyed when the 
1612
+	 * last sender releases the connection (tcpconn_chld_put(c))) or when
1613
+	 * tcp_main receives a CONN_ERROR it*/
1614
+	c->state=S_CONN_BAD;
1615
+	TCPCONN_LOCK;
1616
+		/* FIXME: race: what if CONN_ERROR is sent by another tcp_send() to
1617
+		 * tcp_main ? */
1618
+		if (c->flags & F_CONN_HASHED){
1619
+			/* if some other parallel tcp_send did send CONN_ERROR to
1620
+			 * tcp_main, the connection might be already detached */
1621
+			_tcpconn_detach(c);
1622
+			c->flags&=~F_CONN_HASHED;
1623
+			TCPCONN_UNLOCK;
1624
+			tcpconn_put(c);
1625
+		}else
1626
+			TCPCONN_UNLOCK;
1627
+	/* dec refcnt -> mark it for destruction */
1628
+	tcpconn_chld_put(c);
1629
+	return -1;
1630
+#endif /* TCP_CONNET_WAIT */
1607 1631
 }
1608 1632
 
1609 1633
 
... ...
@@ -1752,77 +1977,6 @@ error:
1752 1752
 
1753 1753
 
1754 1754
 
1755
-#if 0
1756
-/* used internally by tcp_main_loop()
1757
- * tries to destroy a tcp connection (if it cannot it will force a timeout)
1758
- * Note: it's called _only_ from the tcp_main process */
1759
-static void tcpconn_destroy(struct tcp_connection* tcpconn)
1760
-{
1761
-	int fd;
1762
-	ticks_t t;
1763
-
1764
-	/* always try to remove the timer to protect against tcpconn_destroy
1765
-	 *  being called several times for the same connection 
1766
-	 *  (if the timer is already removed, nothing happens) */
1767
-	if (likely(!(tcpconn->flags & F_CONN_READER)))
1768
-		local_timer_del(&tcp_main_ltimer, &tcpconn->timer);
1769
-#ifdef TCP_BUF_WRITE
1770
-	if (unlikely((tcpconn->flags & F_CONN_WRITE_W) ||
1771
-				!(tcpconn->flags & F_CONN_REMOVED))){
1772
-		LOG(L_CRIT, "tcpconn_destroy: possible BUG: flags = %0x\n",
1773
-					tcpconn->flags);
1774
-	}
1775
-	if (unlikely(_wbufq_non_empty(tcpconn))){
1776
-		lock_get(&tcpconn->write_lock);
1777
-			/* check again, while holding the lock */
1778
-			if (likely(_wbufq_non_empty(tcpconn)))
1779
-				_wbufq_destroy(&tcpconn->wbuf_q);
1780
-		lock_release(&tcpconn->write_lock);
1781
-	}
1782
-#endif /* TCP_BUF_WRITE */
1783
-	TCPCONN_LOCK; /*avoid races w/ tcp_send*/
1784
-	if (likely(atomic_dec_and_test(&tcpconn->refcnt))){ 
1785
-		_tcpconn_detach(tcpconn);
1786
-		TCPCONN_UNLOCK;
1787
-		DBG("tcpconn_destroy: destroying connection %p (%d, %d) flags %04x\n",
1788
-				tcpconn, tcpconn->id, tcpconn->s, tcpconn->flags);
1789
-		fd=tcpconn->s;
1790
-#ifdef USE_TLS
1791
-		/*FIXME: lock ->writelock ? */
1792
-		if (tcpconn->type==PROTO_TLS)
1793
-			tls_close(tcpconn, fd);
1794
-#endif
1795
-		_tcpconn_free(tcpconn); /* destroys also the wbuf_q if still present*/
1796
-#ifdef TCP_FD_CACHE
1797
-		if (likely(tcp_options.fd_cache)) shutdown(fd, SHUT_RDWR);
1798
-#endif /* TCP_FD_CACHE */
1799
-		if (unlikely(close(fd)<0)){
1800
-			LOG(L_ERR, "ERROR: tcpconn_destroy; close() failed: %s (%d)\n",
1801
-					strerror(errno), errno);
1802
-		}
1803
-		(*tcp_connections_no)--;
1804
-	}else{
1805
-		TCPCONN_UNLOCK;
1806
-		/* force timeout */
1807
-		t=get_ticks_raw();
1808
-		tcpconn->timeout=t+TCPCONN_WAIT_TIMEOUT;
1809
-		tcpconn->state=S_CONN_BAD;
1810
-		if (!(tcpconn->flags & F_CONN_READER)){
1811
-			/* re-activate the timer only if the connection is handled
1812
-			 * by tcp_main (and not by a tcp reader)*/
1813
-			tcpconn->timer.f=tcpconn_main_timeout;
1814
-			local_timer_reinit(&tcpconn->timer);
1815
-			local_timer_add(&tcp_main_ltimer, &tcpconn->timer, 
1816
-									TCPCONN_WAIT_TIMEOUT, t);
1817
-		}
1818
-		DBG("tcpconn_destroy: delaying (%p, flags %04x) ...\n",
1819
-				tcpconn, tcpconn->flags);
1820
-	}
1821
-}
1822
-#endif
1823
-
1824
-
1825
-
1826 1755
 /* close tcp_main's fd from a tcpconn
1827 1756
  * WARNING: call only in tcp_main context */
1828 1757
 inline static void tcpconn_close_main_fd(struct tcp_connection* tcpconn)
... ...
@@ -1857,7 +2011,7 @@ close_again:
1857 1857
 inline static int tcpconn_chld_put(struct tcp_connection* tcpconn)
1858 1858
 {
1859 1859
 	if (unlikely(atomic_dec_and_test(&tcpconn->refcnt))){
1860
-		DBG("tcpconn_put_chld: destroying connection %p (%d, %d) "
1860
+		DBG("tcpconn_chld_put: destroying connection %p (%d, %d) "
1861 1861
 				"flags %04x\n", tcpconn, tcpconn->id,
1862 1862
 				tcpconn->s, tcpconn->flags);
1863 1863
 		/* sanity checks */
... ...
@@ -1865,7 +2019,7 @@ inline static int tcpconn_chld_put(struct tcp_connection* tcpconn)
1865 1865
 					 !(tcpconn->flags & F_CONN_REMOVED) || 
1866 1866
 					(tcpconn->flags & 
1867 1867
 					 		(F_CONN_HASHED| F_CONN_WRITE_W)) )){
1868
-			LOG(L_CRIT, "BUG: tcpconn_put_chld: %p bad flags = %0x\n",
1868
+			LOG(L_CRIT, "BUG: tcpconn_chld_put: %p bad flags = %0x\n",
1869 1869
 					tcpconn, tcpconn->flags);
1870 1870
 			abort();
1871 1871
 		}
... ...
@@ -1889,7 +2043,8 @@ inline static void tcpconn_destroy(struct tcp_connection* tcpconn)
1889 1889
 			LOG(L_CRIT, "BUG: tcpconn_destroy: called with hashed"
1890 1890
 						" connection (%p)\n", tcpconn);
1891 1891
 			/* try to continue */
1892
-			local_timer_del(&tcp_main_ltimer, &tcpconn->timer);
1892
+			if (likely(tcpconn->flags & F_CONN_MAIN_TIMER))
1893
+				local_timer_del(&tcp_main_ltimer, &tcpconn->timer);
1893 1894
 			TCPCONN_LOCK;
1894 1895
 				_tcpconn_detach(tcpconn);
1895 1896
 			TCPCONN_UNLOCK;
... ...
@@ -1949,23 +2104,24 @@ inline static int tcpconn_put_destroy(struct tcp_connection* tcpconn)
1949 1949
  */
1950 1950
 inline static int tcpconn_try_unhash(struct tcp_connection* tcpconn)
1951 1951
 {
1952
-	if (unlikely((tcpconn->flags & F_CONN_WRITE_W) ||
1953
-				!(tcpconn->flags & F_CONN_REMOVED))){
1954
-		/* sanity check */
1955
-		LOG(L_CRIT, "BUG: tcpconn_put_destroy: %p flags = %0x\n",
1956
-					tcpconn, tcpconn->flags);
1957
-	}
1958 1952
 	if (likely(tcpconn->flags & F_CONN_HASHED)){
1959
-		tcpconn->flags&=~F_CONN_HASHED;
1960 1953
 		tcpconn->state=S_CONN_BAD;
1961
-		if (likely(!(tcpconn->flags & F_CONN_READER)))
1954
+		if (likely(tcpconn->flags & F_CONN_MAIN_TIMER)){
1962 1955
 			local_timer_del(&tcp_main_ltimer, &tcpconn->timer);
1963
-		else
1956
+			tcpconn->flags&=~F_CONN_MAIN_TIMER;
1957
+		}else
1964 1958
 			/* in case it's still in a reader timer */
1965 1959
 			tcpconn->timeout=get_ticks_raw();
1966 1960
 		TCPCONN_LOCK;
1967
-			_tcpconn_detach(tcpconn);
1968
-		TCPCONN_UNLOCK;
1961
+			if (tcpconn->flags & F_CONN_HASHED){
1962
+				tcpconn->flags&=~F_CONN_HASHED;
1963
+				_tcpconn_detach(tcpconn);
1964
+				TCPCONN_UNLOCK;
1965
+			}else{
1966
+				/* tcp_send was faster and did unhash it itself */
1967
+				TCPCONN_UNLOCK;
1968
+				return 0;
1969
+			}
1969 1970
 #ifdef TCP_BUF_WRITE
1970 1971
 		/* empty possible write buffers (optional) */
1971 1972
 		if (unlikely(_wbufq_non_empty(tcpconn))){
... ...
@@ -2279,6 +2435,7 @@ inline static int handle_tcp_child(struct tcp_child* tcp_c, int fd_i)
2279 2279
 			local_timer_reinit(&tcpconn->timer);
2280 2280
 			local_timer_add(&tcp_main_ltimer, &tcpconn->timer, crt_timeout, t);
2281 2281
 			/* must be after the de-ref*/
2282
+			tcpconn->flags|=F_CONN_MAIN_TIMER;
2282 2283
 			tcpconn->flags&=~(F_CONN_REMOVED|F_CONN_READER);
2283 2284
 #ifdef TCP_BUF_WRITE
2284 2285
 			if (unlikely(tcpconn->flags & F_CONN_WRITE_W))
... ...
@@ -2416,17 +2573,26 @@ inline static int handle_ser_child(struct process_table* p, int fd_i)
2416 2416
 	}
2417 2417
 	switch(cmd){
2418 2418
 		case CONN_ERROR:
2419
+			LOG(L_ERR, "handle_ser_child: ERROR: received CON_ERROR for %p"
2420
+					" (id %d), refcnt %d\n", 
2421
+					tcpconn, tcpconn->id, atomic_get(&tcpconn->refcnt));
2422
+#ifdef TCP_CONNECT_WAIT
2423
+			/* if the connection is pending => it might be on the way of
2424
+			 * reaching tcp_main (e.g. CONN_NEW_COMPLETE or 
2425
+			 *  CONN_NEW_PENDING_WRITE) =>  it cannot be destroyed here */
2426
+			if ( !(tcpconn->flags & F_CONN_PENDING) && 
2427
+					tcpconn_try_unhash(tcpconn) )
2428
+				tcpconn_put(tcpconn);
2429
+#else /* ! TCP_CONNECT_WAIT */
2430
+			if ( tcpconn_try_unhash(tcpconn) )
2431
+				tcpconn_put(tcpconn);
2432
+#endif /* TCP_CONNECT_WAIT */
2419 2433
 			if ( (!(tcpconn->flags & F_CONN_REMOVED) ||
2420 2434
 					(tcpconn->flags & F_CONN_WRITE_W) ) && (tcpconn->s!=-1)){
2421 2435
 				io_watch_del(&io_h, tcpconn->s, -1, IO_FD_CLOSING);
2422 2436
 				tcpconn->flags|=F_CONN_REMOVED;
2423 2437
 				tcpconn->flags&=~F_CONN_WRITE_W;
2424 2438
 			}
2425
-			LOG(L_ERR, "handle_ser_child: ERROR: received CON_ERROR for %p"
2426
-					" (id %d), refcnt %d\n", 
2427
-					tcpconn, tcpconn->id, atomic_get(&tcpconn->refcnt));
2428
-			if (tcpconn_try_unhash(tcpconn))
2429
-				tcpconn_put(tcpconn);
2430 2439
 			tcpconn_put_destroy(tcpconn); /* dec refcnt & destroy on 0 */
2431 2440
 			break;
2432 2441
 		case CONN_GET_FD:
... ...
@@ -2460,7 +2626,8 @@ inline static int handle_ser_child(struct process_table* p, int fd_i)
2460 2460
 			 * no need for reinit */
2461 2461
 			local_timer_add(&tcp_main_ltimer, &tcpconn->timer, 
2462 2462
 								tcp_con_lifetime, t);
2463
-			tcpconn->flags&=~F_CONN_REMOVED;
2463
+			tcpconn->flags|=F_CONN_MAIN_TIMER;
2464
+			tcpconn->flags&=~(F_CONN_REMOVED|F_CONN_FD_CLOSED);
2464 2465
 			flags=POLLIN 
2465 2466
 #ifdef TCP_BUF_WRITE
2466 2467
 					/* not used for now, the connection is sent to tcp_main
... ...
@@ -2482,6 +2649,11 @@ inline static int handle_ser_child(struct process_table* p, int fd_i)
2482 2482
 			break;
2483 2483
 #ifdef TCP_BUF_WRITE
2484 2484
 		case CONN_QUEUED_WRITE:
2485
+			/* received only if the wr. queue is empty and a write finishes
2486
+			 * with EAGAIN (common after connect())
2487
+			 * it should only enable write watching on the fd. The connection
2488
+			 * should be  already in the hash. The refcnt is not changed.
2489
+			 */
2485 2490
 			if (unlikely((tcpconn->state==S_CONN_BAD) || 
2486 2491
 							!(tcpconn->flags & F_CONN_HASHED) ))
2487 2492
 				break;
... ...
@@ -2509,7 +2681,7 @@ inline static int handle_ser_child(struct process_table* p, int fd_i)
2509 2509
 				}
2510 2510
 				tcpconn->flags|=F_CONN_WRITE_W;
2511 2511
 				t=get_ticks_raw();
2512
-				if (likely(!(tcpconn->flags & F_CONN_READER) && 
2512
+				if (likely((tcpconn->flags & F_CONN_MAIN_TIMER) && 
2513 2513
 					(TICKS_LT(tcpconn->wbuf_q.wr_timeout, tcpconn->timeout)) &&
2514 2514
 						TICKS_LT(t, tcpconn->wbuf_q.wr_timeout) )){
2515 2515
 					/* _wbufq_nonempty() is guaranteed here */
... ...
@@ -2527,6 +2699,65 @@ inline static int handle_ser_child(struct process_table* p, int fd_i)
2527 2527
 							" already watched for write\n", tcpconn);
2528 2528
 			}
2529 2529
 			break;
2530
+#ifdef TCP_CONNECT_WAIT
2531
+		case CONN_NEW_COMPLETE:
2532
+		case CONN_NEW_PENDING_WRITE:
2533
+				/* received when a pending connect completes in the same
2534
+				 * tcp_send() that initiated it
2535
+				 * the connection is already in the hash with S_CONN_PENDING
2536
+				 * state (added by tcp_send()) and refcnt at least 1 (for the
2537
+				 *  hash)*/
2538
+			tcpconn->flags&=~(F_CONN_PENDING|F_CONN_FD_CLOSED|F_CONN_REMOVED);
2539
+			if (unlikely((tcpconn->state==S_CONN_BAD) || (fd==-1))){
2540
+				if (unlikely(fd==-1))
2541
+					LOG(L_CRIT, "BUG: handle_ser_child: CONN_NEW_COMPLETE:"
2542
+								" no fd received\n");
2543
+				else
2544
+					LOG(L_WARN, "WARNING: handle_ser_child: CONN_NEW_COMPLETE:"
2545
+							" received connection with error\n");
2546
+				tcpconn->flags|=F_CONN_FD_CLOSED;
2547
+				tcpconn->state=S_CONN_BAD;
2548
+				tcpconn_try_unhash(tcpconn);
2549
+				tcpconn_put_destroy(tcpconn);
2550
+				break;
2551
+			}
2552
+			tcpconn->state=S_CONN_OK;
2553
+			(*tcp_connections_no)++;
2554
+			tcpconn->s=fd;
2555
+			/* update the timeout*/
2556
+			t=get_ticks_raw();
2557
+			tcpconn->timeout=t+tcp_con_lifetime;
2558
+			/* activate the timer (already properly init. in tcpconn_new())
2559
+			 * no need for reinit */
2560
+			local_timer_add(&tcp_main_ltimer, &tcpconn->timer, 
2561
+								tcp_con_lifetime, t);
2562
+			tcpconn->flags|=F_CONN_MAIN_TIMER;
2563
+			if (unlikely(cmd==CONN_NEW_COMPLETE)){
2564
+				/* check if needs to be watched for write */
2565
+				lock_get(&tcpconn->write_lock);
2566
+					/* if queue non empty watch it for write */
2567
+					flags=(_wbufq_empty(tcpconn)-1)&POLLOUT;
2568
+				lock_release(&tcpconn->write_lock);
2569
+				tcpconn->flags|=(!(flags&POLLOUT)-1)&F_CONN_WRITE_W;
2570
+			}else{
2571
+				/* CONN_NEW_PENDING_WRITE */
2572
+				/* no need to check, we have something queued for write */
2573
+				flags=POLLOUT;
2574
+				tcpconn->flags|=F_CONN_WRITE_W;
2575
+			}
2576
+			flags|=POLLIN;
2577
+			if (unlikely(
2578
+					io_watch_add(&io_h, tcpconn->s, flags,
2579
+												F_TCPCONN, tcpconn)<0)){
2580
+				LOG(L_CRIT, "ERROR: tcp_main: handle_ser_child: failed to add"
2581
+						" new socket to the fd list\n");
2582
+				tcpconn->flags|=F_CONN_REMOVED;
2583
+				tcpconn->flags&=~F_CONN_WRITE_W;
2584
+				tcpconn_try_unhash(tcpconn); /*  unhash & dec refcnt */
2585
+				tcpconn_put_destroy(tcpconn);
2586
+			}
2587
+			break;
2588
+#endif /* TCP_CONNECT_WAIT */
2530 2589
 #endif /* TCP_BUF_WRITE */
2531 2590
 		default:
2532 2591
 			LOG(L_CRIT, "BUG: handle_ser_child: unknown cmd %d\n", cmd);
... ...
@@ -2679,6 +2910,7 @@ static inline int handle_new_connect(struct socket_info* si)
2679 2679
 		/* activate the timer */
2680 2680
 		local_timer_add(&tcp_main_ltimer, &tcpconn->timer, 
2681 2681
 								tcp_con_lifetime, get_ticks_raw());
2682
+		tcpconn->flags|=F_CONN_MAIN_TIMER;
2682 2683
 		tcpconn->flags&=~F_CONN_REMOVED;
2683 2684
 		if (unlikely(io_watch_add(&io_h, tcpconn->s, POLLIN, 
2684 2685
 													F_TCPCONN, tcpconn)<0)){
... ...
@@ -2794,6 +3026,7 @@ inline static int handle_tcpconn_ev(struct tcp_connection* tcpconn, short ev,
2794 2794
 				goto error;
2795 2795
 		tcpconn->flags|=F_CONN_REMOVED|F_CONN_READER;
2796 2796
 		local_timer_del(&tcp_main_ltimer, &tcpconn->timer);
2797
+		tcpconn->flags&=~F_CONN_MAIN_TIMER;
2797 2798
 		tcpconn_ref(tcpconn); /* refcnt ++ */
2798 2799
 		if (unlikely(send2child(tcpconn)<0)){
2799 2800
 			LOG(L_ERR,"ERROR: handle_tcpconn_ev: no children available\n");
... ...
@@ -2962,9 +3195,10 @@ static inline void tcpconn_destroy_all()
2962 2962
 				if (is_tcp_main){
2963 2963
 					/* we cannot close or remove the fd if we are not in the
2964 2964
 					 * tcp main proc.*/
2965
-					if (!(c->flags & F_CONN_READER))
2965
+					if ((c->flags & F_CONN_MAIN_TIMER)){
2966 2966
 						local_timer_del(&tcp_main_ltimer, &c->timer);
2967
-					/* else still in some reader */
2967
+						c->flags&=~F_CONN_MAIN_TIMER;
2968
+					} /* else still in some reader */
2968 2969
 					fd=c->s;
2969 2970
 					if (fd>0 && (!(c->flags & F_CONN_REMOVED)
2970 2971
 #ifdef TCP_BUF_WRITE
... ...
@@ -40,7 +40,10 @@ void init_tcp_options()
40 40
 	tcp_options.tcpconn_wq_max=32*1024; /* 32 k */
41 41
 	tcp_options.tcp_wq_max=10*1024*1024; /* 10 MB */
42 42
 	tcp_options.tcp_wq_timeout=S_TO_TICKS(tcp_send_timeout);
43
-#endif
43
+#ifdef TCP_CONNECT_WAIT
44
+	tcp_options.tcp_connect_wait=1;
45
+#endif /* TCP_CONNECT_WAIT */
46
+#endif /* TCP_BUF_WRITE */
44 47
 #ifdef TCP_FD_CACHE
45 48
 	tcp_options.fd_cache=1;
46 49
 #endif
... ...
@@ -89,7 +92,16 @@ void tcp_options_check()
89 89
 	W_OPT_NC(tcp_wq_max);
90 90
 	W_OPT_NC(tcp_wq_timeout);
91 91
 #endif /* TCP_BUF_WRITE */
92
-
92
+#ifndef TCP_CONNECT_WAIT
93
+	W_OPT_NC(tcp_connect_wait);
94
+#endif /* TCP_CONNECT_WAIT */
95
+	
96
+	if (tcp_options.tcp_connect_wait && !tcp_options.tcp_buf_write){
97
+		WARN("tcp_options: tcp_connect_wait depends on tcp_buf_write, "
98
+				" disabling...\n");
99
+		tcp_options.tcp_connect_wait=0;
100
+	}
101
+	
93 102
 #if ! defined HAVE_TCP_DEFER_ACCEPT && ! defined HAVE_TCP_ACCEPT_FILTER
94 103
 	W_OPT_NS(defer_accept);
95 104
 #endif
... ...
@@ -31,6 +31,16 @@
31 31
 #define TCP_BUF_WRITE /* enabled buffered writing */
32 32
 #endif 
33 33
 
34
+#if !defined(NO_TCP_CONNECT_WAIT) && defined(TCP_BUF_WRITE)
35
+#define TCP_CONNECT_WAIT /* enable pending connects support */
36
+#endif
37
+
38
+#if defined(TCP_CONNECT_WAIT) && !defined(TCP_BUF_WRITE)
39
+/* check for impossible configuration: TCP_CONNECT_WAIT w/o TCP_BUF_WRITE */
40
+#warning "disabling TCP_CONNECT_WAIT because TCP_BUF_WRITE is not defined"
41
+#undef TCP_CONNECT_WAIT
42
+#endif
43
+
34 44
 #ifndef NO_TCP_FD_CACHE
35 45
 #define TCP_FD_CACHE /* enable fd caching */
36 46
 #endif
... ...
@@ -102,6 +112,7 @@ struct tcp_cfg_options{
102 102
 	int fd_cache; /* on /off */
103 103
 	/* tcp buf. write options */
104 104
 	int tcp_buf_write; /* on / off */
105
+	int tcp_connect_wait; /* on / off, depends on tcp_buf_write */
105 106
 	unsigned int tcpconn_wq_max; /* maximum queue len per connection */
106 107
 	unsigned int tcp_wq_max; /* maximum overall queued bytes */
107 108
 	unsigned int tcp_wq_timeout;      /* timeout for queue writes */