Browse code

- merge from testing-0.8.12-r0: - tcp updates (lots) - makefile mips support - tm timer workarround (present also in stable), t_relay_tls changed to t_relay_to_tls - udp_flood sleep & throttle support

Andrei Pelinescu-Onciul authored on 11/11/2003 15:32:36
Showing 12 changed files
... ...
@@ -29,6 +29,7 @@
29 29
 #  2003-09-25  added -pthread into LIBS when compiling on FreeBSD/alpha
30 30
 #              and other FreeBSD arches for which no fast locking assembly
31 31
 #              code exists (sobomax)
32
+#  2003-11-08  mips1 support introduced (andrei)
32 33
 
33 34
 
34 35
 # check if already included/exported
... ...
@@ -43,7 +44,7 @@ export makefile_defs
43 43
 VERSION = 0
44 44
 PATCHLEVEL = 8
45 45
 SUBLEVEL =   12
46
-EXTRAVERSION = dev-22-tcp_aliases
46
+EXTRAVERSION = -dev-23-merged
47 47
 
48 48
 RELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
49 49
 OS = $(shell uname -s | sed -e s/SunOS/solaris/ | tr "[A-Z]" "[a-z]")
... ...
@@ -51,7 +52,7 @@ ARCH = $(shell uname -m |sed -e s/i.86/i386/ -e s/sun4u/sparc64/  \
51 51
 			-e s/armv4l/arm/)
52 52
 
53 53
 # TLS support
54
-TLS ?=
54
+TLS ?= 
55 55
 ifneq ($(TLS),)
56 56
 	RELEASE:=$(RELEASE)-tls
57 57
 endif
... ...
@@ -240,16 +241,16 @@ endif
240 240
 # -DUSE_POSIX_SEM
241 241
 #		uses posix semaphores for locking (faster than sys v)
242 242
 # -DBUSY_WAIT
243
-#		uses busy waiting on the lock
243
+#		uses busy waiting on the lock (FAST_LOCK)
244 244
 # -DADAPTIVE_WAIT
245 245
 #		try busy waiting for a while and if the lock is still held go to
246
-#		force reschedule
246
+#		force reschedule (FAST_LOCK)
247 247
 # -DADAPTIVE_WAIT_LOOPS=number
248 248
 #		number of loops we busy wait, after "number" loops have elapsed we 
249
-#		force a reschedule
249
+#		force a reschedule (FAST_LOCK)
250 250
 # -DNOSMP
251 251
 #		don't use smp compliant locking (faster but won't work on SMP machines)
252
-#		(not yet enabled)
252
+#		(not yet enabled) (FAST_LOCK)
253 253
 # -DNO_PINGTEL_TAG_HACK
254 254
 #		if enabled, To-header-field will be less liberal and will not accept
255 255
 #		'tag=' (tag parameter with equal sign and without value); it is called
... ...
@@ -273,12 +274,11 @@ DEFS+= $(extra_defs) \
273 273
 	 -DCFG_DIR='"$(cfg-target)"'\
274 274
 	 -DPKG_MALLOC \
275 275
 	 -DSHM_MEM  -DSHM_MMAP \
276
-	 -DADAPTIVE_WAIT -DADAPTIVE_WAIT_LOOPS=1024 \
277 276
 	 -DDNS_IP_HACK \
278 277
 	 -DUSE_IPV6 \
279 278
 	 -DUSE_TCP \
280 279
 	 -DDISABLE_NAGLE \
281
-	 -DDBG_QM_MALLOC \
280
+	# -DDBG_QM_MALLOC \
282 281
 	# -DF_MALLOC \
283 282
 	# -DDBG_F_MALLOC \
284 283
 	# -DDBG_QM_MALLOC \
... ...
@@ -386,8 +386,13 @@ ifeq ($(ARCH), ppc)
386 386
 	use_fast_lock=yes
387 387
 endif
388 388
 
389
+ifeq ($(ARCH), mips)
390
+# mips1 arch. (e.g. R3000) - no hardware locking support
391
+	use_fast_lock=no
392
+endif
393
+
389 394
 ifeq ($(use_fast_lock), yes)
390
-	DEFS+= -DFAST_LOCK
395
+	DEFS+= -DFAST_LOCK -DADAPTIVE_WAIT -DADAPTIVE_WAIT_LOOPS=1024 
391 396
 	found_lock_method=yes
392 397
 endif
393 398
 
... ...
@@ -519,15 +524,46 @@ else
519 519
 				#really old version
520 520
 $(warning			You are using an old and unsupported gcc \
521 521
 					 version ($(CC_SHORTVER)), compile at your own risk!)
522
-
522
+	
523 523
 endif			# CC_SHORTVER, 2.9x
524 524
 endif			# CC_SHORTVER, 3.0
525
+	
526
+else		# CC_NAME, gcc
527
+				#other compilers
528
+$(error 			Unsupported compiler ($(CC):$(CC_NAME)), try gcc)
529
+endif		#CC_NAME, gcc
530
+endif	#ARCH, arm 
525 531
 
532
+	#if  mips (R3000)
533
+ifeq	($(ARCH), mips)
534
+		# if gcc 
535
+ifeq		($(CC_NAME), gcc)
536
+				#common stuff
537
+				CFLAGS=-O9 -funroll-loops  -Wcast-align $(PROFILE) \
538
+					-Wall   \
539
+			#if gcc 3.0
540
+ifeq			($(CC_SHORTVER), 3.0)
541
+					CFLAGS+= -mcpu=r3000
542
+							#-mcpu=athlon
543
+else
544
+ifeq			($(CC_SHORTVER), 2.9x) #older gcc version (2.9[1-5])
545
+$(warning 			Old gcc detected ($(CC_SHORTVER)), use  gcc 3.0.x \
546
+					for better results)
547
+					
548
+					CFLAGS+=-mcpu=r3000
549
+else
550
+				#really old version
551
+$(warning			You are using an old and unsupported gcc \
552
+					 version ($(CC_SHORTVER)), compile at your own risk!)
553
+	
554
+endif			# CC_SHORTVER, 2.9x
555
+endif			# CC_SHORTVER, 3.0
556
+	
526 557
 else		# CC_NAME, gcc
527 558
 				#other compilers
528 559
 $(error 			Unsupported compiler ($(CC):$(CC_NAME)), try gcc)
529 560
 endif		#CC_NAME, gcc
530
-endif	#ARCH, i386
561
+endif	#ARCH, mips
531 562
 
532 563
 
533 564
 CFLAGS+= $(CC_EXTRA_OPTS)
... ...
@@ -6,9 +6,9 @@
6 6
 
7 7
 # ----------- global configuration parameters ------------------------
8 8
 
9
-debug=3         # debug level (cmd line: -dddddddddd)
10
-fork=yes
11
-log_stderror=no	# (cmd line: -E)
9
+#debug=3         # debug level (cmd line: -dddddddddd)
10
+#fork=yes
11
+#log_stderror=no	# (cmd line: -E)
12 12
 
13 13
 /* Uncomment these lines to enter debugging mode 
14 14
 fork=no
... ...
@@ -18,8 +18,8 @@ log_stderror=yes
18 18
 check_via=no	# (cmd. line: -v)
19 19
 dns=no           # (cmd. line: -r)
20 20
 rev_dns=no      # (cmd. line: -R)
21
-port=5060
22
-children=4
21
+#port=5060
22
+#children=4
23 23
 fifo="/tmp/ser_fifo"
24 24
 
25 25
 # ------------------ module loading ----------------------------------
... ...
@@ -349,8 +349,8 @@ static int fifo_check(int fd, char* fname)
349 349
 	 */
350 350
 	if ((lst.st_dev!=fst.st_dev)||(lst.st_ino!=fst.st_ino)){
351 351
 		LOG(L_ERR, "ERROR: security: fifo_check: inode/dev number differ"
352
-				": %ld %ld (%s)\n",
353
-				 fst.st_ino, lst.st_ino, fname);
352
+				": %d %d (%s)\n",
353
+				 (int)fst.st_ino, (int)lst.st_ino, fname);
354 354
 		return -1;
355 355
 	}
356 356
 	/* success */
... ...
@@ -326,6 +326,11 @@ inline static void final_response_handler( void *attr)
326 326
 	struct cell *t;
327 327
 
328 328
 	r_buf = (struct retr_buf*)attr;
329
+	if (r_buf==0){
330
+		/* or BUG?, ignoring it for now */
331
+		LOG(L_CRIT, "ERROR: final_response_handler(0) called\n");
332
+		return;
333
+	}
329 334
 	t=r_buf->my_T;
330 335
 
331 336
 #	ifdef EXTRA_DEBUG
... ...
@@ -52,7 +52,7 @@
52 52
 #define T_RELAY_TO           "t_relay_to"
53 53
 #define T_RELAY_TO_UDP       "t_relay_to_udp"
54 54
 #define T_RELAY_TO_TCP       "t_relay_to_tcp"
55
-#define T_RELAY_TO_TLS       "t_relay_tls"
55
+#define T_RELAY_TO_TLS       "t_relay_to_tls"
56 56
 #define T_RELAY              "t_relay"
57 57
 #define T_REPLY              "t_reply"
58 58
 #define T_REPLY_WB           "t_reply_with_body"
... ...
@@ -29,6 +29,8 @@
29 29
   * --------
30 30
   *  2002-11-29  created by andrei
31 31
   *  2003-02-20  added solaris support (! HAVE_MSGHDR_MSG_CONTROL) (andrei)
32
+  *  2003-11-03  added send_all, recv_all  and updated send/get_fd
33
+  *               to handle signals  (andrei)
32 34
   */
33 35
 
34 36
 #ifdef USE_TCP
... ...
@@ -37,10 +39,55 @@
37 37
 #include <sys/socket.h>
38 38
 #include <sys/uio.h>
39 39
 #include <stdlib.h> /* for NULL definition on openbsd */
40
+#include <errno.h>
41
+#include <string.h>
40 42
 
41 43
 #include "dprint.h"
42 44
 
43 45
 
46
+
47
+/* receive all the data or returns error (handles EINTR etc.)
48
+ * returns: bytes read or error (<0)
49
+ * can return < data_len if EOF */
50
+int recv_all(int socket, void* data, int data_len)
51
+{
52
+	int b_read;
53
+	int n;
54
+	
55
+	b_read=0;
56
+	do{
57
+		n=recv(socket, data+b_read, data_len-b_read, MSG_WAITALL);
58
+		if (n<0){
59
+			/* error */
60
+			if (errno==EINTR) continue; /* signal, try again */
61
+			LOG(L_CRIT, "ERROR: recv_all: recv on %d failed: %s\n",
62
+					socket, strerror(errno));
63
+			return n;
64
+		}
65
+		b_read+=n;
66
+	}while( (b_read!=data_len) && (n));
67
+	return b_read;
68
+}
69
+
70
+
71
+/* sends all data (takes care of signals) (assumes blocking fd)
72
+ * returns number of bytes sent or < 0 for an error */
73
+int send_all(int socket, void* data, int data_len)
74
+{
75
+	int n;
76
+	
77
+again:
78
+	n=send(socket, data, data_len, 0);
79
+	if (n<0){
80
+			/* error */
81
+		if (errno==EINTR) goto again; /* signal, try again */
82
+		LOG(L_CRIT, "ERROR: send_all: send on %d failed: %s\n",
83
+					socket, strerror(errno));
84
+	}
85
+	return n;
86
+}
87
+
88
+
44 89
 /* at least 1 byte must be sent! */
45 90
 int send_fd(int unix_socket, void* data, int data_len, int fd)
46 91
 {
... ...
@@ -76,8 +123,13 @@ int send_fd(int unix_socket, void* data, int data_len, int fd)
76 76
 	msg.msg_iov=iov;
77 77
 	msg.msg_iovlen=1;
78 78
 	
79
-	
79
+again:
80 80
 	ret=sendmsg(unix_socket, &msg, 0);
81
+	if (ret<0){
82
+		if (errno==EINTR) goto again;
83
+		LOG(L_CRIT, "ERROR: send_fd: sendmsg failed on %d: %s\n",
84
+				unix_socket, strerror(errno));
85
+	}
81 86
 	
82 87
 	return ret;
83 88
 }
... ...
@@ -90,6 +142,7 @@ int receive_fd(int unix_socket, void* data, int data_len, int* fd)
90 90
 	struct iovec iov[1];
91 91
 	int new_fd;
92 92
 	int ret;
93
+	int n;
93 94
 #ifdef HAVE_MSGHDR_MSG_CONTROL
94 95
 	struct cmsghdr* cmsg;
95 96
 	union{
... ...
@@ -112,26 +165,47 @@ int receive_fd(int unix_socket, void* data, int data_len, int* fd)
112 112
 	msg.msg_iov=iov;
113 113
 	msg.msg_iovlen=1;
114 114
 	
115
-	ret=recvmsg(unix_socket, &msg, 0);
116
-	if (ret<=0) goto error;
115
+again:
116
+	ret=recvmsg(unix_socket, &msg, MSG_WAITALL);
117
+	if (ret<0){
118
+		if (errno==EINTR) goto again;
119
+		LOG(L_CRIT, "ERROR: receive_fd: recvmsg on %d failed: %s\n",
120
+				unix_socket, strerror(errno));
121
+		goto error;
122
+	}
123
+	if (ret==0){
124
+		/* EOF */
125
+		LOG(L_CRIT, "ERROR: receive_fd: EOF on %d\n", unix_socket);
126
+		goto error;
127
+	}
128
+	if (ret<data_len){
129
+		LOG(L_WARN, "WARNING: receive_fd: too few bytes read (%d from %d)"
130
+				    "trying to fix...\n", ret, data_len);
131
+		n=recv_all(unix_socket, (char*)data+ret, data_len-ret);
132
+		if (n>=0) ret+=n;
133
+		else{
134
+			ret=n;
135
+			goto error;
136
+		}
137
+	}
117 138
 	
118 139
 #ifdef HAVE_MSGHDR_MSG_CONTROL
119 140
 	cmsg=CMSG_FIRSTHDR(&msg);
120 141
 	if ((cmsg!=0) && (cmsg->cmsg_len==CMSG_LEN(sizeof(new_fd)))){
121 142
 		if (cmsg->cmsg_type!= SCM_RIGHTS){
122
-			LOG(L_ERR, "receive_fd: msg control type != SCM_RIGHTS\n");
143
+			LOG(L_ERR, "ERROR: receive_fd: msg control type != SCM_RIGHTS\n");
123 144
 			ret=-1;
124 145
 			goto error;
125 146
 		}
126 147
 		if (cmsg->cmsg_level!= SOL_SOCKET){
127
-			LOG(L_ERR, "receive_fd: msg level != SOL_SOCKET\n");
148
+			LOG(L_ERR, "ERROR: receive_fd: msg level != SOL_SOCKET\n");
128 149
 			ret=-1;
129 150
 			goto error;
130 151
 		}
131 152
 		*fd=*((int*) CMSG_DATA(cmsg));
132 153
 	}else{
133
-		LOG(L_ERR, "receive_fd: no descriptor passed, cmsg=%p, len=%d\n",
134
-				cmsg, cmsg->cmsg_len);
154
+		LOG(L_ERR, "ERROR: receive_fd: no descriptor passed, cmsg=%p,"
155
+				"len=%d\n", cmsg, cmsg->cmsg_len);
135 156
 		*fd=-1;
136 157
 		/* it's not really an error */
137 158
 	}
... ...
@@ -139,8 +213,8 @@ int receive_fd(int unix_socket, void* data, int data_len, int* fd)
139 139
 	if (msg.msg_accrightslen==sizeof(int)){
140 140
 		*fd=new_fd;
141 141
 	}else{
142
-		LOG(L_ERR, "receive_fd: no descriptor passed, accrightslen=%d\n",
143
-				msg.msg_accrightslen);
142
+		LOG(L_ERR, "ERROR: receive_fd: no descriptor passed,"
143
+				" accrightslen=%d\n", msg.msg_accrightslen);
144 144
 		*fd=-1;
145 145
 	}
146 146
 #endif
... ...
@@ -148,5 +222,4 @@ int receive_fd(int unix_socket, void* data, int data_len, int* fd)
148 148
 error:
149 149
 	return ret;
150 150
 }
151
-
152 151
 #endif
... ...
@@ -32,6 +32,8 @@
32 32
 int send_fd(int unix_socket, void* data, int data_len, int fd);
33 33
 int receive_fd(int unix_socket, void* data, int data_len, int* fd);
34 34
 
35
+int recv_all(int socket, void* data, int data_len);
36
+int send_all(int socket, void* data, int data_len);
35 37
 
36 38
 
37 39
 #endif
... ...
@@ -44,8 +44,8 @@
44 44
 #define TCP_CON_MAX_ALIASES 4 /* maximum number of port aliases */
45 45
 
46 46
 #define TCP_BUF_SIZE 65535
47
-#define TCP_CON_TIMEOUT 60 /* in  seconds */
48
-#define TCP_CON_SEND_TIMEOUT 30 /* timeout after a send */
47
+#define TCP_CON_TIMEOUT 120 /* in  seconds */
48
+#define TCP_CON_SEND_TIMEOUT 120 /* timeout after a send */
49 49
 #define TCP_CHILD_TIMEOUT 5 /* after 5 seconds, the child "returns" 
50 50
 							 the connection to the tcp master process */
51 51
 #define TCP_MAIN_SELECT_TIMEOUT 5 /* how often "tcp main" checks for timeout*/
... ...
@@ -73,6 +73,8 @@ enum tcp_conn_states { S_CONN_ERROR=-2, S_CONN_BAD=-1, S_CONN_OK=0,
73 73
 /* fd communication commands */
74 74
 enum conn_cmds { CONN_DESTROY=-3, CONN_ERROR=-2, CONN_EOF=-1, CONN_RELEASE, 
75 75
 					CONN_GET_FD, CONN_NEW };
76
+/* CONN_RELEASE, EOF, ERROR, DESTROY can be used by "reader" processes
77
+ * CONN_GET_FD, NEW, ERROR only by writers */
76 78
 
77 79
 struct tcp_req{
78 80
 	struct tcp_req* next;
... ...
@@ -44,6 +44,10 @@
44 44
  *  2003-07-09  tls_close called before closing the tcp connection (andrei)
45 45
  *  2003-10-24  converted to the new socket_info lists (andrei)
46 46
  *  2003-10-27  tcp port aliases support added (andrei)
47
+ *  2003-11-04  always lock before manipulating refcnt; sendchild
48
+ *              does not inc refcnt by itself anymore (andrei)
49
+ *  2003-11-07  different unix sockets are used for fd passing
50
+ *              to/from readers/writers (andrei)
47 51
  */
48 52
 
49 53
 
... ...
@@ -100,7 +104,7 @@
100 100
 struct tcp_child{
101 101
 	pid_t pid;
102 102
 	int proc_no; /* ser proc_no, for debugging */
103
-	int unix_sock; /* unix sock fd, copied from pt*/
103
+	int unix_sock; /* unix "read child" sock fd */
104 104
 	int busy;
105 105
 	int n_reqs; /* number of requests serviced so far */
106 106
 };
... ...
@@ -242,7 +246,13 @@ struct tcp_connection* tcpconn_connect(union sockaddr_union* server, int type)
242 242
 				strerror(errno), errno);
243 243
 		si=0; /* try to go on */
244 244
 	}
245
-	si=find_tcp_si(&my_name);
245
+#ifdef USE_TLS
246
+	if (type==PROTO_TLS)
247
+		si=find_tls_si(&my_name);
248
+	else
249
+#endif
250
+		si=find_tcp_si(&my_name);
251
+
246 252
 	if (si==0){
247 253
 		LOG(L_ERR, "ERROR: tcp_connect: could not find coresponding"
248 254
 				" listening socket, using default...\n");
... ...
@@ -443,9 +453,20 @@ error_sec:
443 443
 
444 444
 
445 445
 
446
+void tcpconn_ref(struct tcp_connection* c)
447
+{
448
+	TCPCONN_LOCK;
449
+	c->refcnt++; /* FIXME: atomic_dec */
450
+	TCPCONN_UNLOCK;
451
+}
452
+
453
+
454
+
446 455
 void tcpconn_put(struct tcp_connection* c)
447 456
 {
457
+	TCPCONN_LOCK;
448 458
 	c->refcnt--; /* FIXME: atomic_dec */
459
+	TCPCONN_UNLOCK;
449 460
 }
450 461
 
451 462
 
... ...
@@ -455,6 +476,7 @@ int tcp_send(int type, char* buf, unsigned len, union sockaddr_union* to,
455 455
 				int id)
456 456
 {
457 457
 	struct tcp_connection *c;
458
+	struct tcp_connection *tmp;
458 459
 	struct ip_addr ip;
459 460
 	int port;
460 461
 	int fd;
... ...
@@ -494,22 +516,25 @@ no_id:
494 494
 				LOG(L_ERR, "ERROR: tcp_send: connect failed\n");
495 495
 				return -1;
496 496
 			}
497
-			c->refcnt++;
497
+			c->refcnt++; /* safe to do it w/o locking, it's not yet
498
+							available to the rest of the world */
498 499
 			fd=c->s;
499 500
 			
500 501
 			/* send the new tcpconn to "tcp main" */
501 502
 			response[0]=(long)c;
502 503
 			response[1]=CONN_NEW;
503
-			n=write(unix_tcp_sock, response, sizeof(response));
504
-			if (n<0){
504
+			n=send_all(unix_tcp_sock, response, sizeof(response));
505
+			if (n<=0){
505 506
 				LOG(L_ERR, "BUG: tcp_send: failed write: %s (%d)\n",
506 507
 						strerror(errno), errno);
508
+				n=-1;
507 509
 				goto end;
508 510
 			}	
509 511
 			n=send_fd(unix_tcp_sock, &c, sizeof(c), c->s);
510
-			if (n<0){
512
+			if (n<=0){
511 513
 				LOG(L_ERR, "BUG: tcp_send: failed send_fd: %s (%d)\n",
512 514
 						strerror(errno), errno);
515
+				n=-1;
513 516
 				goto end;
514 517
 			}
515 518
 			goto send_it;
... ...
@@ -517,21 +542,34 @@ no_id:
517 517
 get_fd:
518 518
 			/* todo: see if this is not the same process holding
519 519
 			 *  c  and if so send directly on c->fd */
520
-			DBG("tcp_send: tcp connection found, acquiring fd\n");
520
+			DBG("tcp_send: tcp connection found (%p), acquiring fd\n", c);
521 521
 			/* get the fd */
522 522
 			response[0]=(long)c;
523 523
 			response[1]=CONN_GET_FD;
524
-			n=write(unix_tcp_sock, response, sizeof(response));
525
-			if (n<0){
524
+			n=send_all(unix_tcp_sock, response, sizeof(response));
525
+			if (n<=0){
526 526
 				LOG(L_ERR, "BUG: tcp_send: failed to get fd(write):%s (%d)\n",
527 527
 						strerror(errno), errno);
528
+				n=-1;
528 529
 				goto release_c;
529 530
 			}
530 531
 			DBG("tcp_send, c= %p, n=%d\n", c, n);
532
+			tmp=c;
531 533
 			n=receive_fd(unix_tcp_sock, &c, sizeof(c), &fd);
532
-			if (n<0){
534
+			if (n<=0){
533 535
 				LOG(L_ERR, "BUG: tcp_send: failed to get fd(receive_fd):"
534 536
 							" %s (%d)\n", strerror(errno), errno);
537
+				n=-1;
538
+				goto release_c;
539
+			}
540
+			if (c!=tmp){
541
+				LOG(L_CRIT, "BUG: tcp_send: get_fd: got different connection:"
542
+						"  %p (id= %d, refcnt=%d state=%d != "
543
+						"  %p (id= %d, refcnt=%d state=%d (n=%d)\n",
544
+						  c,   c->id,   c->refcnt,   c->state,
545
+						  tmp, tmp->id, tmp->refcnt, tmp->state, n
546
+				   );
547
+				n=-1; /* fail */
535 548
 				goto release_c;
536 549
 			}
537 550
 			DBG("tcp_send: after receive_fd: c= %p n=%d fd=%d\n",c, n, fd);
... ...
@@ -567,11 +605,12 @@ send_it:
567 567
 		/* tell "main" it should drop this (optional it will t/o anyway?)*/
568 568
 		response[0]=(long)c;
569 569
 		response[1]=CONN_ERROR;
570
-		n=write(unix_tcp_sock, response, sizeof(response));
571
-		/* CONN_ERROR wil auto-dec refcnt => we must not call tcpconn_put !!*/
572
-		if (n<0){
570
+		n=send_all(unix_tcp_sock, response, sizeof(response));
571
+		/* CONN_ERROR will auto-dec refcnt => we must not call tcpconn_put !!*/
572
+		if (n<=0){
573 573
 			LOG(L_ERR, "BUG: tcp_send: error return failed (write):%s (%d)\n",
574 574
 					strerror(errno), errno);
575
+			n=-1;
575 576
 		}
576 577
 		close(fd);
577 578
 		return n; /* error return, no tcpconn_put */
... ...
@@ -737,19 +776,21 @@ static int send2child(struct tcp_connection* tcpconn)
737 737
 	
738 738
 	tcp_children[idx].busy++;
739 739
 	tcp_children[idx].n_reqs++;
740
-	tcpconn->refcnt++;
741 740
 	if (min_busy){
742
-		LOG(L_WARN, "WARNING: send2child:no free tcp receiver, "
741
+		LOG(L_WARN, "WARNING: send2child: no free tcp receiver, "
743 742
 				" connection passed to the least busy one (%d)\n",
744 743
 				min_busy);
745 744
 	}
746 745
 	DBG("send2child: to tcp child %d %d(%d), %p\n", idx, 
747 746
 					tcp_children[idx].proc_no,
748 747
 					tcp_children[idx].pid, tcpconn);
749
-	send_fd(tcp_children[idx].unix_sock, &tcpconn, sizeof(tcpconn),
750
-			tcpconn->s);
748
+	if (send_fd(tcp_children[idx].unix_sock, &tcpconn, sizeof(tcpconn),
749
+			tcpconn->s)<=0){
750
+		LOG(L_ERR, "ERROR: send2child: send_fd failed\n");
751
+		return -1;
752
+	}
751 753
 	
752
-	return 0; /* just to fix a warning*/
754
+	return 0;
753 755
 }
754 756
 
755 757
 
... ...
@@ -776,6 +817,8 @@ static inline void handle_new_connect(struct socket_info* si,
776 776
 		/* add socket to list */
777 777
 		tcpconn=tcpconn_new(new_sock, &su, si, si->proto, S_CONN_ACCEPT);
778 778
 		if (tcpconn){
779
+			tcpconn->refcnt++; /* safe, not yet available to the
780
+								  outside world */
779 781
 			tcpconn_add(tcpconn);
780 782
 			DBG("tcp_main_loop: new connection: %p %d\n",
781 783
 				tcpconn, tcpconn->s);
... ...
@@ -784,6 +827,7 @@ static inline void handle_new_connect(struct socket_info* si,
784 784
 				LOG(L_ERR,"ERROR: tcp_main_loop: no children "
785 785
 						"available\n");
786 786
 				TCPCONN_LOCK;
787
+				tcpconn->refcnt--;
787 788
 				if (tcpconn->refcnt==0){
788 789
 					close(tcpconn->s);
789 790
 					_tcpconn_rm(tcpconn);
... ...
@@ -795,6 +839,34 @@ static inline void handle_new_connect(struct socket_info* si,
795 795
 }
796 796
 
797 797
 
798
+/* used internally by tcp_main_loop() */
799
+static void tcpconn_destroy(struct tcp_connection* tcpconn)
800
+{
801
+	int fd;
802
+
803
+	TCPCONN_LOCK; /*avoid races w/ tcp_send*/
804
+	tcpconn->refcnt--;
805
+	if (tcpconn->refcnt==0){ 
806
+		DBG("tcp_main_loop: destroying connection\n");
807
+		fd=tcpconn->s;
808
+#ifdef USE_TLS
809
+		/*FIXME: lock ->writelock ? */
810
+		if (tcpconn->type==PROTO_TLS)
811
+			tls_close(tcpconn, fd);
812
+#endif
813
+		_tcpconn_rm(tcpconn);
814
+		close(fd);
815
+	}else{
816
+		/* force timeout */
817
+		tcpconn->timeout=0;
818
+		tcpconn->state=S_CONN_BAD;
819
+		DBG("tcp_main_loop: delaying ...\n");
820
+		
821
+	}
822
+	TCPCONN_UNLOCK;
823
+}
824
+
825
+
798 826
 void tcp_main_loop()
799 827
 {
800 828
 	int r;
... ...
@@ -843,6 +915,14 @@ void tcp_main_loop()
843 843
 			if (pt[r].unix_sock>maxfd) maxfd=pt[r].unix_sock;
844 844
 		}
845 845
 	}
846
+	for (r=0; r<tcp_children_no; r++){
847
+		if (tcp_children[r].unix_sock>0){ /* we can't have 0, 
848
+											 we never close it!*/
849
+			FD_SET(tcp_children[r].unix_sock, &master_set);
850
+			if (tcp_children[r].unix_sock>maxfd)
851
+				maxfd=tcp_children[r].unix_sock;
852
+		}
853
+	}
846 854
 	
847 855
 	
848 856
 	/* main loop*/
... ...
@@ -872,6 +952,7 @@ void tcp_main_loop()
872 872
 		for (h=0; h<TCP_ID_HASH_SIZE; h++){
873 873
 			for(tcpconn=tcpconn_id_hash[h]; tcpconn && n; 
874 874
 					tcpconn=tcpconn->id_next){
875
+				/* FIXME: is refcnt==0 really necessary? */
875 876
 				if ((tcpconn->refcnt==0)&&(FD_ISSET(tcpconn->s, &sel_set))){
876 877
 					/* new data available */
877 878
 					n--;
... ...
@@ -879,10 +960,12 @@ void tcp_main_loop()
879 879
 					DBG("tcp_main_loop: data available on %p [h:%d] %d\n",
880 880
 							tcpconn, h, tcpconn->s);
881 881
 					FD_CLR(tcpconn->s, &master_set);
882
+					tcpconn_ref(tcpconn); /* refcnt ++ */
882 883
 					if (send2child(tcpconn)<0){
883 884
 						LOG(L_ERR,"ERROR: tcp_main_loop: no "
884 885
 									"children available\n");
885 886
 						TCPCONN_LOCK;
887
+						tcpconn->refcnt--;
886 888
 						if (tcpconn->refcnt==0){
887 889
 							fd=tcpconn->s;
888 890
 							_tcpconn_rm(tcpconn);
... ...
@@ -894,109 +977,138 @@ void tcp_main_loop()
894 894
 			}
895 895
 		}
896 896
 		/* check unix sockets & listen | destroy connections */
897
-		/* start from 1, the "main" process does not transmit anything*/
898
-		for (r=1; r<process_no && n; r++){
899
-			if ( (pt[r].unix_sock>0) && FD_ISSET(pt[r].unix_sock, &sel_set)){
897
+		/* tcp_children readers first */
898
+		for (r=0; r<tcp_children_no && n; r++){
899
+			if ( (tcp_children[r].unix_sock>0) && 
900
+					FD_ISSET(tcp_children[r].unix_sock, &sel_set)){
900 901
 				/* (we can't have a fd==0, 0 is never closed )*/
901 902
 				n--;
902
-				/* errno==EINTR !!! TODO*/
903
-read_again:
904
-				bytes=read(pt[r].unix_sock, response, sizeof(response));
903
+				/* read until sizeof(response)
904
+				 * (this is a SOCK_STREAM so read is not atomic */
905
+				bytes=recv_all(tcp_children[r].unix_sock, response,
906
+								sizeof(response));
905 907
 				if (bytes==0){
906 908
 					/* EOF -> bad, child has died */
907
-					LOG(L_CRIT, "BUG: tcp_main_loop: dead child %d\n", r);
909
+					LOG(L_CRIT, "BUG: tcp_main_loop: dead tcp child %d\n", r);
908 910
 					/* don't listen on it any more */
909
-					FD_CLR(pt[r].unix_sock, &master_set);
911
+					FD_CLR(tcp_children[r].unix_sock, &master_set);
910 912
 					/*exit(-1);*/
911
-					continue;
913
+					continue; /* skip this and try the next one */
912 914
 				}else if (bytes<0){
913
-					if (errno==EINTR) goto read_again;
914
-					else{
915
-						LOG(L_CRIT, "ERROR: tcp_main_loop: read from child: "
916
-								" %s\n", strerror(errno));
917
-						/* try to continue ? */
918
-						continue;
919
-					}
915
+					LOG(L_CRIT, "ERROR: tcp_main_loop: read from tcp child %d "
916
+							"%s\n", r, strerror(errno));
917
+					/* try to ignore ? */
918
+					continue; /* skip this and try the next one */
920 919
 				}
921 920
 					
922
-				DBG("tcp_main_loop: read response= %lx, %ld from %d (%d)\n",
923
-						response[0], response[1], r, pt[r].pid);
921
+				DBG("tcp_main_loop: reader response= %lx, %ld from %d \n",
922
+						response[0], response[1], r);
924 923
 				cmd=response[1];
924
+				tcpconn=(struct tcp_connection*)response[0];
925 925
 				switch(cmd){
926 926
 					case CONN_RELEASE:
927
-						if (pt[r].idx>=0){
928
-							tcp_children[pt[r].idx].busy--;
929
-						}else{
930
-							LOG(L_CRIT, "BUG: tcp_main_loop: CONN_RELEASE\n");
931
-						}
932
-						tcpconn=(struct tcp_connection*)response[0];
927
+						tcp_children[r].busy--;
933 928
 						if (tcpconn){
934
-								if (tcpconn->state==S_CONN_BAD) 
935
-									goto tcpconn_destroy;
929
+								if (tcpconn->state==S_CONN_BAD){ 
930
+									tcpconn_destroy(tcpconn);
931
+									break;
932
+								}
936 933
 								FD_SET(tcpconn->s, &master_set);
937 934
 								if (maxfd<tcpconn->s) maxfd=tcpconn->s;
938 935
 								/* update the timeout*/
939 936
 								tcpconn->timeout=get_ticks()+TCP_CON_TIMEOUT;
940 937
 								tcpconn_put(tcpconn);
941
-								DBG("tcp_main_loop: %p refcnt= %d\n", 
942
-									tcpconn, tcpconn->refcnt);
938
+								DBG("tcp_main_loop: CONN_RELEASE  %p"
939
+										" refcnt= %d\n", 
940
+										tcpconn, tcpconn->refcnt);
943 941
 						}
944 942
 						break;
945 943
 					case CONN_ERROR:
946 944
 					case CONN_DESTROY:
947 945
 					case CONN_EOF:
948 946
 						/* WARNING: this will auto-dec. refcnt! */
949
-						if (pt[r].idx>=0){
950
-							tcp_children[pt[r].idx].busy--;
951
-						}else{
952
-							LOG(L_CRIT, "BUG: tcp_main_loop: CONN_RELEASE\n");
947
+						tcp_children[pt[r].idx].busy--;
948
+						if (tcpconn){
949
+							if (tcpconn->s!=-1)
950
+								FD_CLR(tcpconn->s, &master_set);
951
+							tcpconn_destroy(tcpconn);
953 952
 						}
954
-						tcpconn=(struct tcp_connection*)response[0];
953
+						break;
954
+					default:
955
+							LOG(L_CRIT, "BUG: tcp_main_loop:  unknown cmd %d"
956
+										" from tcp reader %d\n",
957
+									cmd, r);
958
+				}
959
+			}
960
+		}
961
+		/* check "send" unix sockets & listen | destroy connections */
962
+		/* start from 1, the "main" process does not transmit anything*/
963
+		for (r=1; r<process_no && n; r++){
964
+			if ( (pt[r].unix_sock>0) && FD_ISSET(pt[r].unix_sock, &sel_set)){
965
+				/* (we can't have a fd==0, 0 is never closed )*/
966
+				n--;
967
+				/* read until sizeof(response)
968
+				 * (this is a SOCK_STREAM so read is not atomic */
969
+				bytes=recv_all(pt[r].unix_sock, response, sizeof(response));
970
+				if (bytes==0){
971
+					/* EOF -> bad, child has died */
972
+					LOG(L_CRIT, "BUG: tcp_main_loop: dead child %d\n", r);
973
+					/* don't listen on it any more */
974
+					FD_CLR(pt[r].unix_sock, &master_set);
975
+					/*exit(-1);*/
976
+					continue; /* skip this and try the next one */
977
+				}else if (bytes<0){
978
+					LOG(L_CRIT, "ERROR: tcp_main_loop: read from child:  %s\n",
979
+							strerror(errno));
980
+					/* try to ignore ? */
981
+					continue; /* skip this and try the next one */
982
+				}
983
+					
984
+				DBG("tcp_main_loop: read response= %lx, %ld from %d (%d)\n",
985
+						response[0], response[1], r, pt[r].pid);
986
+				cmd=response[1];
987
+				tcpconn=(struct tcp_connection*)response[0];
988
+				switch(cmd){
989
+					case CONN_ERROR:
955 990
 						if (tcpconn){
956 991
 							if (tcpconn->s!=-1)
957 992
 								FD_CLR(tcpconn->s, &master_set);
958
-		tcpconn_destroy:
959
-							TCPCONN_LOCK; /*avoid races w/ tcp_send*/
960
-							tcpconn->refcnt--;
961
-							if (tcpconn->refcnt==0){ 
962
-								DBG("tcp_main_loop: destroying connection\n");
963
-								fd=tcpconn->s;
964
-#ifdef USE_TLS
965
-								if (tcpconn->type==PROTO_TLS)
966
-									tls_close(tcpconn, fd);
967
-#endif
968
-								_tcpconn_rm(tcpconn);
969
-								close(fd);
970
-							}else{
971
-								/* force timeout */
972
-								tcpconn->timeout=0;
973
-								tcpconn->state=S_CONN_BAD;
974
-								DBG("tcp_main_loop: delaying ...\n");
975
-								
976
-							}
977
-							TCPCONN_UNLOCK;
993
+							tcpconn_destroy(tcpconn);
978 994
 						}
979 995
 						break;
980 996
 					case CONN_GET_FD:
981 997
 						/* send the requested FD  */
982
-						tcpconn=(struct tcp_connection*)response[0];
983 998
 						/* WARNING: take care of setting refcnt properly to
984 999
 						 * avoid race condition */
985 1000
 						if (tcpconn){
986
-							send_fd(pt[r].unix_sock, &tcpconn,
987
-									sizeof(tcpconn), tcpconn->s);
1001
+							if (send_fd(pt[r].unix_sock, &tcpconn,
1002
+										sizeof(tcpconn), tcpconn->s)<=0){
1003
+								LOG(L_ERR, "ERROR: tcp_main_loop:"
1004
+										"send_fd failed\n");
1005
+							}
988 1006
 						}else{
989 1007
 							LOG(L_CRIT, "BUG: tcp_main_loop: null pointer\n");
990 1008
 						}
991 1009
 						break;
992 1010
 					case CONN_NEW:
993 1011
 						/* update the fd in the requested tcpconn*/
994
-						tcpconn=(struct tcp_connection*)response[0];
995 1012
 						/* WARNING: take care of setting refcnt properly to
996 1013
 						 * avoid race condition */
997 1014
 						if (tcpconn){
998
-							receive_fd(pt[r].unix_sock, &tcpconn,
999
-										sizeof(tcpconn), &tcpconn->s);
1015
+							bytes=receive_fd(pt[r].unix_sock, &tcpconn,
1016
+									sizeof(tcpconn), &tcpconn->s);
1017
+								if (bytes<sizeof(tcpconn)){
1018
+									if (bytes<0){
1019
+										LOG(L_CRIT, "BUG: tcp_main_loop:"
1020
+												" CONN_NEW: receive_fd "
1021
+												"failed\n");
1022
+									}else{
1023
+										LOG(L_CRIT, "BUG: tcp_main_loop:"
1024
+												" CONN_NEW: to few bytes "
1025
+												"received (%d)\n", bytes );
1026
+									}
1027
+									break; /* try to ignore */
1028
+								}
1000 1029
 							/* add tcpconn to the list*/
1001 1030
 							tcpconn_add(tcpconn);
1002 1031
 							FD_SET(tcpconn->s, &master_set);
... ...
@@ -1012,7 +1124,7 @@ read_again:
1012 1012
 									cmd);
1013 1013
 				}
1014 1014
 			}
1015
-		}
1015
+		} /* for */
1016 1016
 		
1017 1017
 		/* remove old connections */
1018 1018
 		tcpconn_timeout(&master_set);
... ...
@@ -1114,6 +1226,7 @@ int tcp_init_children()
1114 1114
 {
1115 1115
 	int r;
1116 1116
 	int sockfd[2];
1117
+	int reader_fd[2]; /* for comm. with the tcp children read  */
1117 1118
 	pid_t pid;
1118 1119
 	
1119 1120
 	
... ...
@@ -1127,6 +1240,11 @@ int tcp_init_children()
1127 1127
 					strerror(errno));
1128 1128
 			goto error;
1129 1129
 		}
1130
+		if (socketpair(AF_UNIX, SOCK_STREAM, 0, reader_fd)<0){
1131
+			LOG(L_ERR, "ERROR: tcp_main: socketpair failed: %s\n",
1132
+					strerror(errno));
1133
+			goto error;
1134
+		}
1130 1135
 		
1131 1136
 		process_no++;
1132 1137
 		pid=fork();
... ...
@@ -1137,11 +1255,12 @@ int tcp_init_children()
1137 1137
 		}else if (pid>0){
1138 1138
 			/* parent */
1139 1139
 			close(sockfd[1]);
1140
+			close(reader_fd[1]);
1140 1141
 			tcp_children[r].pid=pid;
1141 1142
 			tcp_children[r].proc_no=process_no;
1142 1143
 			tcp_children[r].busy=0;
1143 1144
 			tcp_children[r].n_reqs=0;
1144
-			tcp_children[r].unix_sock=sockfd[0];
1145
+			tcp_children[r].unix_sock=reader_fd[0];
1145 1146
 			pt[process_no].pid=pid;
1146 1147
 			pt[process_no].unix_sock=sockfd[0];
1147 1148
 			pt[process_no].idx=r;
... ...
@@ -1156,7 +1275,7 @@ int tcp_init_children()
1156 1156
 				LOG(L_ERR, "init_children failed\n");
1157 1157
 				goto error;
1158 1158
 			}
1159
-			tcp_receive_loop(sockfd[1]);
1159
+			tcp_receive_loop(reader_fd[1]);
1160 1160
 		}
1161 1161
 	}
1162 1162
 	return 0;
... ...
@@ -399,20 +399,11 @@ int tcp_read_req(struct tcp_connection* con)
399 399
 		req=&con->req;
400 400
 #ifdef USE_TLS
401 401
 		if (con->type==PROTO_TLS){
402
-			if (con->state==S_CONN_ACCEPT){
403
-				if (tls_accept(con, 0)!=0){
404
-					resp=CONN_ERROR;
405
-					goto end_req;
406
-				}
407
-				if(con->state!=S_CONN_OK) goto end_req; /* not enough data */
408
-			}
409
-			if(con->state==S_CONN_CONNECT){
410
-				if (tls_connect(con, 0)!=0){
411
-					resp=CONN_ERROR;
412
-					goto end_req;
413
-				}
414
-				if(con->state!=S_CONN_OK) goto end_req; /* not enough data */
402
+			if (tls_fix_read_conn(con)!=0){
403
+				resp=CONN_ERROR;
404
+				goto end_req;
415 405
 			}
406
+			if(con->state!=S_CONN_OK) goto end_req; /* not enough data */
416 407
 		}
417 408
 #endif
418 409
 
... ...
@@ -547,7 +538,8 @@ void release_tcpconn(struct tcp_connection* c, long state, int unix_sock)
547 547
 		/* errno==EINTR, EWOULDBLOCK a.s.o todo */
548 548
 		response[0]=(long)c;
549 549
 		response[1]=state;
550
-		write(unix_sock, response, sizeof(response));
550
+		if (send_all(unix_sock, response, sizeof(response))<=0)
551
+			LOG(L_ERR, "ERROR: release_tcpconn: send_all failed\n");
551 552
 }
552 553
 
553 554
 
... ...
@@ -625,12 +617,18 @@ void tcp_receive_loop(int unix_sock)
625 625
 					release_tcpconn(con, resp, unix_sock);
626 626
 					goto skip;
627 627
 				}
628
-#ifdef USE_TLS
629
-				if (con->type==PROTO_TLS) tls_tcpconn_update_fd(con, s);
630
-#endif
631 628
 				con->timeout=get_ticks()+TCP_CHILD_TIMEOUT;
632 629
 				FD_SET(s, &master_set);
633 630
 				if (maxfd<s) maxfd=s;
631
+				if (con==list){
632
+					LOG(L_CRIT, "BUG: tcp_receive_loop: duplicate"
633
+							" connection recevied: %p, id %d, fd %d, refcnt %d"
634
+							" state %d (n=%d)\n", con, con->id, con->fd,
635
+							con->refcnt, con->state, n);
636
+					resp=CONN_ERROR;
637
+					release_tcpconn(con, resp, unix_sock);
638
+					goto skip; /* try to recover */
639
+				}
634 640
 				tcpconn_listadd(list, con, c_next, c_prev);
635 641
 			}
636 642
 skip:
... ...
@@ -641,12 +639,22 @@ skip:
641 641
 				DBG("tcp receive: list fd=%d, id=%d, timeout=%d, refcnt=%d\n",
642 642
 						con->fd, con->id, con->timeout, con->refcnt);
643 643
 #endif
644
+				if (con->state<0){
645
+					/* S_CONN_BAD or S_CONN_ERROR, remove it */
646
+					resp=CONN_ERROR;
647
+					FD_CLR(con->fd, &master_set);
648
+					tcpconn_listrm(list, con, c_next, c_prev);
649
+					con->state=S_CONN_BAD;
650
+					release_tcpconn(con, resp, unix_sock);
651
+					continue;
652
+				}
644 653
 				if (nfds && FD_ISSET(con->fd, &sel_set)){
645 654
 #ifdef EXTRA_DEBUG
646 655
 					DBG("tcp receive: match, fd:isset\n");
647 656
 #endif
648 657
 					nfds--;
649 658
 					resp=tcp_read_req(con);
659
+					
650 660
 					if (resp<0){
651 661
 						FD_CLR(con->fd, &master_set);
652 662
 						tcpconn_listrm(list, con, c_next, c_prev);
... ...
@@ -26,7 +26,7 @@ rev_dns=off      # (cmd. line: -R)
26 26
 alias=iptel.org
27 27
 alias="foo.bar"
28 28
 fifo="/tmp/ser_fifo"
29
-listen= tcp:10.0.0.179:5065
29
+#listen= tcp:10.0.0.179:5065
30 30
 alias=  tcp:all:5065
31 31
 tcp_accept_aliases=yes
32 32
 
... ...
@@ -50,6 +50,8 @@ Options:\n\
50 50
     -d address    destination address\n\
51 51
     -p port       destination port\n\
52 52
     -c count      number of packets to be sent\n\
53
+    -s usec       microseconds to sleep before sending \"throttle\" packets\n\
54
+    -t throttle   number of packets to send before sleeping\n\
53 55
     -v            increase verbosity level\n\
54 56
     -V            version number\n\
55 57
     -h            this help message\n\
... ...
@@ -74,6 +76,9 @@ int main (int argc, char** argv)
74 74
 	char *fname;
75 75
 	char *dst;
76 76
 	int port;
77
+	long usec;
78
+	int throttle;
79
+	int t;
77 80
 	
78 81
 	/* init */
79 82
 	count=0;
... ...
@@ -81,9 +86,11 @@ int main (int argc, char** argv)
81 81
 	fname=0;
82 82
 	dst=0;
83 83
 	port=0;
84
+	usec=0;
85
+	throttle=0;
84 86
 
85 87
 	opterr=0;
86
-	while ((c=getopt(argc,argv, "f:c:d:p:vhV"))!=-1){
88
+	while ((c=getopt(argc,argv, "f:c:d:p:s:t:vhV"))!=-1){
87 89
 		switch(c){
88 90
 			case 'f':
89 91
 				fname=optarg;
... ...
@@ -108,6 +115,20 @@ int main (int argc, char** argv)
108 108
 					goto error;
109 109
 				}
110 110
 				break;
111
+			case 's':
112
+				usec=strtol(optarg, &tmp, 10);
113
+				if ((tmp==0)||(*tmp)){
114
+					fprintf(stderr, "bad count: -c %s\n", optarg);
115
+					goto error;
116
+				}
117
+				break;
118
+			case 't':
119
+				throttle=strtol(optarg, &tmp, 10);
120
+				if ((tmp==0)||(*tmp)){
121
+					fprintf(stderr, "bad count: -c %s\n", optarg);
122
+					goto error;
123
+				}
124
+				break;
111 125
 			case 'V':
112 126
 				printf("version: %s\n", version);
113 127
 				printf("%s\n",id);
... ...
@@ -197,12 +218,20 @@ int main (int argc, char** argv)
197 197
 
198 198
 
199 199
 	/* flood loop */
200
+	t=throttle;
200 201
 	for (r=0; r<count; r++){
201 202
 		if ((verbose>1)&&(r%1000))  putchar('.');
202 203
 		if (send(sock, buf, n, 0)==-1) {
203 204
 			fprintf(stderr, "Error: send: %s\n",  strerror(errno));
204 205
 			exit(1);
205 206
 		}
207
+		if (usec){
208
+			t--;
209
+			if (t==0){
210
+				usleep(usec);
211
+				t=throttle;
212
+			}
213
+		}
206 214
 	}
207 215
 	printf("\n%d packets sent, %d bytes each => total %d bytes\n",
208 216
 			count, n, n*count);