Browse code

Merge commit 'origin/ser_core_cvs'

* commit 'origin/ser_core_cvs':
make: use C_INCLUDES for includes
tcp: stun fixes
tcp: tcp_blocking_connect timeout fix
tcp: stats: added init & destroy macros
tcp: minor stats fixes
tcp: internal macro-hooks for stats & events
tcp: helper internal macros
Do not try to backlist and do not try DNS failover for blind UACs as
Safety check added to verify whether the static buffers have

Andrei Pelinescu-Onciul authored on 16/04/2009 11:31:43
Showing 8 changed files
... ...
@@ -1653,7 +1653,7 @@ endif
1653 1653
 
1654 1654
 #add libssl if needed
1655 1655
 ifeq ($(CORE_TLS), 1)
1656
-C_DEFS+= -I$(LOCALBASE)/ssl/include
1656
+C_INCLUDES+= -I$(LOCALBASE)/ssl/include
1657 1657
 LIBS+= -L$(LOCALBASE)/lib -L$(LOCALBASE)/ssl/lib -lssl -lcrypto \
1658 1658
 		$(TLS_EXTRA_LIBS)
1659 1659
 # NOTE: depending on the way in which libssl was compiled you might
... ...
@@ -1662,7 +1662,7 @@ LIBS+= -L$(LOCALBASE)/lib -L$(LOCALBASE)/ssl/lib -lssl -lcrypto \
1662 1662
 endif
1663 1663
 
1664 1664
 ifneq ($(STUN),)
1665
-C_DEFS+= -I$(LOCALBASE)/ssl/include
1665
+C_INCLUDES+= -I$(LOCALBASE)/ssl/include
1666 1666
 LIBS+= -L$(LOCALBASE)/lib -L$(LOCALBASE)/ssl/lib -lcrypto
1667 1667
 endif
1668 1668
 
... ...
@@ -449,7 +449,9 @@ inline static void final_response_handler(	struct retr_buf* r_buf,
449 449
 	DBG("DEBUG: final_response_handler:stop retr. and send CANCEL (%p)\n", t);
450 450
 #endif
451 451
 	if ((r_buf->branch < MAX_BRANCHES) && /* r_buf->branch is always >=0 */
452
-			(t->uac[r_buf->branch].last_received==0)){
452
+			(t->uac[r_buf->branch].last_received==0) &&
453
+			(t->uac[r_buf->branch].request.buffer!=NULL) /* not a blind UAC */
454
+	){
453 455
 		/* no reply received */
454 456
 #ifdef USE_DST_BLACKLIST
455 457
 		if (cfg_get(core, core_cfg, use_dst_blacklist)
... ...
@@ -105,6 +105,15 @@ static int allocate_buffer(int req_size) {
105 105
 
106 106
 char* get_static_buffer(int req_size) {
107 107
 	char *p = NULL;
108
+
109
+#ifdef EXTRA_DEBUG
110
+	if ((active_buffer < 0) || (active_buffer > MAX_BUFFERS-1)) {
111
+		LOG(L_CRIT, "BUG: buffers have not been initialized yet. "
112
+			"Call reset_static_buffer() before executing "
113
+			"a route block.\n");
114
+		abort();
115
+	}
116
+#endif
108 117
 	if ((buffer[active_buffer].size >= buffer[active_buffer].offset + req_size)
109 118
 			|| (allocate_buffer(req_size))) {
110 119
 		/* enough space in current buffer or allocation successful */
... ...
@@ -188,6 +188,31 @@ struct tcp_connection{
188 188
 };
189 189
 
190 190
 
191
+/* helper macros */
192
+
193
+#define TCP_RCV_INFO(c) (&(c)->rcv)
194
+
195
+#define TCP_RCV_LADDR(r) (&((r).dst_ip))
196
+#define TCP_RCV_LPORT(r) ((r).dst_port)
197
+#define TCP_RCV_PADDR(r)  (&((r).src_ip))
198
+#define TCP_RCV_PPORT(r)  ((r).src_port)
199
+#define TCP_RCV_PSU(r)   (&(r).src_su)
200
+#define TCP_RCV_SOCK_INFO(r)  ((r).bind_address)
201
+#define TCP_RCV_PROTO(r)      ((r).proto)
202
+#ifdef USE_COMP
203
+#define TCP_RCV_COMP(r)       ((r).comp)
204
+#else
205
+#define TCP_RCV_COMP(r)  0
206
+#endif /* USE_COMP */
207
+
208
+#define TCP_LADDR(c) TCP_RCV_LADDR(c->rcv)
209
+#define TCP_LPORT(c) TCP_RCV_LPORT(c->rcv)
210
+#define TCP_PADDR(c) TCP_RCV_PADDR(c->rcv)
211
+#define TCP_PPORT(c) TCP_RCV_PPORT(c->rcv)
212
+#define TCP_PSU(c)   TCP_RCV_PSU(c->rcv)
213
+#define TCP_SOCK_INFO(c) TCP_RCV_SOCK_INFO(c->rcv)
214
+#define TCP_PROTO(c) TCP_RCV_PROTO(c->rcv)
215
+#define TCP_COMP(c) TCP_RCV_COMP(c->rcv)
191 216
 
192 217
 
193 218
 
194 219
new file mode 100644
... ...
@@ -0,0 +1,97 @@
1
+/* 
2
+ * $Id$
3
+ * 
4
+ * Copyright (C) 2009 iptelorg GmbH
5
+ *
6
+ * Permission to use, copy, modify, and distribute this software for any
7
+ * purpose with or without fee is hereby granted, provided that the above
8
+ * copyright notice and this permission notice appear in all copies.
9
+ *
10
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
+ */
18
+/*
19
+ * tcp_ev.h - tcp events
20
+ */
21
+/*
22
+ * History:
23
+ * --------
24
+ *  2009-04-09  initial version (andrei)
25
+*/
26
+
27
+#ifndef __tcp_ev_h
28
+#define __tcp_ev_h
29
+
30
+#include <errno.h>
31
+#include <string.h>
32
+
33
+#include "ip_addr.h"
34
+
35
+
36
+/** a connect attempt got a RST from the peer
37
+ * Note: the RST might be for the connect() itself (SYN), for the first
38
+ *  send() attempt on the connection (unlikely) or received immediately after
39
+ * the connect() succeeded (unlikely, the remote host would have a very small
40
+ *  window after accepting a connection to send a RST before it receives
41
+ * any data).
42
+ *
43
+ * @param err - if 0 it should be ignored (no corresp. libc error), if non-0
44
+ *                it will contain the errno.
45
+ * @param lip   - pointer to an ip_addr containing the local ip
46
+ *                   or 0 if dynamic (WARNING can be 0).
47
+ * @param lport - pointer to an ip_addr containing the local port or 0
48
+ *                   if unknown/dynamic.
49
+ * @param dst   - pointer to a sockaddr_union containing the destination.
50
+ * @param proto - protocol used
51
+ */
52
+#define TCP_EV_CONNECT_RST(err, lip, lport, dst, proto) \
53
+	LOG(L_ERR, "connect %s failed (RST) %s\n", \
54
+			su2a(dst, sizeof(*(dst))), (err)?strerror(err):"")
55
+
56
+/** a connect failed because the remote host/network is unreachable. */
57
+#define TCP_EV_CONNECT_UNREACHABLE(err, lip, lport, dst, proto) \
58
+	LOG(L_ERR, "connect %s failed (unreachable) %s\n", \
59
+			su2a(dst, sizeof(*(dst))), (err)?strerror(err):"")
60
+
61
+/** a connect attempt did timeout. */
62
+#define TCP_EV_CONNECT_TIMEOUT(err, lip, lport, dst, proto) \
63
+	LOG(L_ERR, "connect %s failed (timeout) %s\n", \
64
+			su2a(dst, sizeof(*(dst))), (err)?strerror(err):"")
65
+
66
+/** a connect attempt failed because the local ports are exhausted. */
67
+#define TCP_EV_CONNECT_NO_MORE_PORTS(err, lip, lport, dst, proto) \
68
+	LOG(L_ERR, "connect %s failed (no more ports) %s\n", \
69
+			su2a(dst, sizeof(*(dst))), (err)?strerror(err):"")
70
+
71
+/** a connect attempt failed for some unknown reason.  */
72
+#define TCP_EV_CONNECT_ERR(err, lip, lport, dst, proto) \
73
+	LOG(L_ERR, "connect %s failed %s\n", \
74
+			su2a(dst, sizeof(*(dst))), (err)?strerror(err):"")
75
+
76
+
77
+/** send failed due to timeout.
78
+ * @param err   - if 0 it should be ignored (no corresp. libc error), if non-0
79
+ *                it will contain the errno.
80
+ * @param rcv   - pointer to rcv_info structure
81
+ * 
82
+ */
83
+#define TCP_EV_SEND_TIMEOUT(err, rcv)
84
+
85
+/** send failed due to buffering capacity being exceeded.
86
+  * (only in async mode) */
87
+#define TCP_EV_SENDQ_FULL(err, rcv)
88
+
89
+/** established connection closed for being idle too long. */
90
+#define TCP_EV_IDLE_CONN_CLOSED(err, rcv)
91
+
92
+
93
+
94
+
95
+#endif /*__tcp_ev_h*/
96
+
97
+/* vi: set ts=4 sw=4 tw=79:ai:cindent: */
... ...
@@ -100,6 +100,7 @@
100 100
  *  2009-02-26  direct blacklist support (andrei)
101 101
  *  2009-03-20  s/wq_timeout/send_timeout ; send_timeout is now in ticks
102 102
  *              (andrei)
103
+ * 2009-04-09  tcp ev and tcp stats macros added (andrei)
103 104
  */
104 105
 
105 106
 
... ...
@@ -155,6 +156,8 @@
155 156
 #include "sr_module.h"
156 157
 #include "tcp_server.h"
157 158
 #include "tcp_init.h"
159
+#include "tcp_stats.h"
160
+#include "tcp_ev.h"
158 161
 #include "tsend.h"
159 162
 #include "timer_ticks.h"
160 163
 #include "local_timer.h"
... ...
@@ -503,23 +506,7 @@ again:
503 506
 			else goto error_timeout;
504 507
 		}
505 508
 		if (errno!=EINPROGRESS && errno!=EALREADY){
506
-#ifdef USE_DST_BLACKLIST
507
-			if (cfg_get(core, core_cfg, use_dst_blacklist))
508
-				switch(errno){
509
-					case ECONNREFUSED:
510
-					case ENETUNREACH:
511
-					case ETIMEDOUT:
512
-					case ECONNRESET:
513
-					case EHOSTUNREACH:
514
-						dst_blacklist_su(BLST_ERR_CONNECT, type,
515
-										 (union sockaddr_union*)servaddr, 0);
516
-						break;
517
-				}
518
-#endif /* USE_DST_BLACKLIST */
519
-			LOG(L_ERR, "ERROR: tcp_blocking_connect %s: (%d) %s\n",
520
-					su2a((union sockaddr_union*)servaddr, addrlen),
521
-					errno, strerror(errno));
522
-			goto error;
509
+			goto error_errno;
523 510
 		}
524 511
 	}else goto end;
525 512
 	
... ...
@@ -533,17 +520,15 @@ again:
533 520
 #endif
534 521
 	while(1){
535 522
 		elapsed=(get_ticks()-ticks)*TIMER_TICK;
536
-		if (elapsed<to)
537
-			to-=elapsed;
538
-		else 
523
+		if (elapsed>=to)
539 524
 			goto error_timeout;
540 525
 #if defined(HAVE_SELECT) && defined(BLOCKING_USE_SELECT)
541 526
 		sel_set=orig_set;
542
-		timeout.tv_sec=to;
527
+		timeout.tv_sec=to-elapsed;
543 528
 		timeout.tv_usec=0;
544 529
 		n=select(fd+1, 0, &sel_set, 0, &timeout);
545 530
 #else
546
-		n=poll(&pf, 1, to*1000);
531
+		n=poll(&pf, 1, (to-elapsed)*1000);
547 532
 #endif
548 533
 		if (n<0){
549 534
 			if (errno==EINTR) continue;
... ...
@@ -573,10 +558,54 @@ again:
573 558
 						"%s\n",
574 559
 						su2a((union sockaddr_union*)servaddr, addrlen),
575 560
 						err, strerror(err));
576
-				goto error;
561
+				errno=err;
562
+				goto error_errno;
577 563
 			}
578 564
 		}
579 565
 	}
566
+error_errno:
567
+	switch(errno){
568
+		case ENETUNREACH:
569
+		case EHOSTUNREACH:
570
+#ifdef USE_DST_BLACKLIST
571
+			if (cfg_get(core, core_cfg, use_dst_blacklist))
572
+				dst_blacklist_su(BLST_ERR_CONNECT, type,
573
+							 (union sockaddr_union*)servaddr, 0);
574
+#endif /* USE_DST_BLACKLIST */
575
+			TCP_EV_CONNECT_UNREACHABLE(errno, 0, 0,
576
+							(union sockaddr_union*)servaddr, type);
577
+			break;
578
+		case ETIMEDOUT:
579
+#ifdef USE_DST_BLACKLIST
580
+			if (cfg_get(core, core_cfg, use_dst_blacklist))
581
+				dst_blacklist_su(BLST_ERR_CONNECT, type,
582
+								 (union sockaddr_union*)servaddr, 0);
583
+#endif /* USE_DST_BLACKLIST */
584
+			TCP_EV_CONNECT_TIMEOUT(errno, 0, 0,
585
+							(union sockaddr_union*)servaddr, type);
586
+			break;
587
+		case ECONNREFUSED:
588
+		case ECONNRESET:
589
+#ifdef USE_DST_BLACKLIST
590
+			if (cfg_get(core, core_cfg, use_dst_blacklist))
591
+				dst_blacklist_su(BLST_ERR_CONNECT, type,
592
+								 (union sockaddr_union*)servaddr, 0);
593
+#endif /* USE_DST_BLACKLIST */
594
+			TCP_EV_CONNECT_RST(errno, 0, 0,
595
+							(union sockaddr_union*)servaddr, type);
596
+			break;
597
+		case EAGAIN: /* not posix, but supported on linux and bsd */
598
+			TCP_EV_CONNECT_NO_MORE_PORTS(errno, 0, 0,
599
+							(union sockaddr_union*)servaddr, type);
600
+			break;
601
+		default:
602
+			TCP_EV_CONNECT_ERR(errno, 0, 0,
603
+								(union sockaddr_union*)servaddr, type);
604
+	}
605
+	LOG(L_ERR, "ERROR: tcp_blocking_connect %s: (%d) %s\n",
606
+			su2a((union sockaddr_union*)servaddr, addrlen),
607
+			errno, strerror(errno));
608
+	goto error;
580 609
 error_timeout:
581 610
 	/* timeout */
582 611
 #ifdef USE_DST_BLACKLIST
... ...
@@ -584,10 +613,12 @@ error_timeout:
584 613
 		dst_blacklist_su(BLST_ERR_CONNECT, type,
585 614
 							(union sockaddr_union*)servaddr, 0);
586 615
 #endif /* USE_DST_BLACKLIST */
616
+	TCP_EV_CONNECT_TIMEOUT(0, 0, 0, (union sockaddr_union*)servaddr, type);
587 617
 	LOG(L_ERR, "ERROR: tcp_blocking_connect %s: timeout %d s elapsed "
588 618
 				"from %d s\n", su2a((union sockaddr_union*)servaddr, addrlen),
589 619
 				elapsed, cfg_get(tcp, tcp_cfg, connect_timeout_s));
590 620
 error:
621
+	TCP_STATS_CONNECT_FAILED();
591 622
 	return -1;
592 623
 end:
593 624
 	return 0;
... ...
@@ -630,15 +661,34 @@ inline static int _wbufq_add(struct  tcp_connection* c, char* data,
630 661
 					size, q->queued, *tcp_total_wq,
631 662
 					TICKS_TO_S(t-q->wr_timeout-
632 663
 						cfg_get(tcp, tcp_cfg, send_timeout)));
664
+		if (q->first && TICKS_LT(q->wr_timeout, t)){
665
+			if (unlikely(c->state==S_CONN_CONNECT)){
633 666
 #ifdef USE_DST_BLACKLIST
634
-		if (q->first && TICKS_LT(q->wr_timeout, t) &&
635
-				cfg_get(core, core_cfg, use_dst_blacklist)){
636
-			ERR("blacklisting, state=%d\n", c->state);
637
-			dst_blacklist_su((c->state==S_CONN_CONNECT)?  BLST_ERR_CONNECT:
638
-									BLST_ERR_SEND,
639
-								c->rcv.proto, &c->rcv.src_su, 0);
640
-		}
667
+				if (likely(cfg_get(core, core_cfg, use_dst_blacklist))){
668
+					DBG("blacklisting, state=%d\n", c->state);
669
+					dst_blacklist_su( BLST_ERR_CONNECT, c->rcv.proto,
670
+										&c->rcv.src_su, 0);
671
+				}
672
+#endif /* USE_DST_BLACKLIST */
673
+				TCP_EV_CONNECT_TIMEOUT(0, TCP_LADDR(c), TCP_LPORT(c),
674
+											TCP_PSU(c), TCP_PROTO(c));
675
+				TCP_STATS_CONNECT_FAILED();
676
+			}else{
677
+#ifdef USE_DST_BLACKLIST
678
+				if (likely(cfg_get(core, core_cfg, use_dst_blacklist))){
679
+					DBG("blacklisting, state=%d\n", c->state);
680
+					dst_blacklist_su( BLST_ERR_SEND, c->rcv.proto,
681
+										&c->rcv.src_su, 0);
682
+				}
641 683
 #endif /* USE_DST_BLACKLIST */
684
+				TCP_EV_SEND_TIMEOUT(0, &c->rcv);
685
+				TCP_STATS_SEND_TIMEOUT();
686
+			}
687
+		}else{
688
+			/* if it's not a timeout => queue full */
689
+			TCP_EV_SENDQ_FULL(0, &c->rcv);
690
+			TCP_STATS_SENDQ_FULL();
691
+		}
642 692
 		goto error;
643 693
 	}
644 694
 	
... ...
@@ -808,20 +858,55 @@ inline static int wbufq_run(int fd, struct tcp_connection* c, int* empty)
808 858
 			if (n<0){
809 859
 				/* EINTR is handled inside _tcpconn_write_nb */
810 860
 				if (!(errno==EAGAIN || errno==EWOULDBLOCK)){
811
-#ifdef USE_DST_BLACKLIST
812
-					if (cfg_get(core, core_cfg, use_dst_blacklist))
861
+					if (unlikely(c->state==S_CONN_CONNECT)){
813 862
 						switch(errno){
814 863
 							case ENETUNREACH:
864
+							case EHOSTUNREACH: /* not posix for send() */
865
+#ifdef USE_DST_BLACKLIST
866
+								if (cfg_get(core, core_cfg, use_dst_blacklist))
867
+									dst_blacklist_su(BLST_ERR_CONNECT,
868
+															c->rcv.proto,
869
+															&c->rcv.src_su, 0);
870
+#endif /* USE_DST_BLACKLIST */
871
+								TCP_EV_CONNECT_UNREACHABLE(errno, TCP_LADDR(c),
872
+													TCP_LPORT(c), TCP_PSU(c),
873
+													TCP_PROTO(c));
874
+								break;
875
+							case ECONNREFUSED:
876
+							case ECONNRESET:
877
+#ifdef USE_DST_BLACKLIST
878
+								if (cfg_get(core, core_cfg, use_dst_blacklist))
879
+									dst_blacklist_su(BLST_ERR_CONNECT,
880
+															c->rcv.proto,
881
+															&c->rcv.src_su, 0);
882
+#endif /* USE_DST_BLACKLIST */
883
+								TCP_EV_CONNECT_RST(0, TCP_LADDR(c),
884
+													TCP_LPORT(c), TCP_PSU(c),
885
+													TCP_PROTO(c));
886
+								break;
887
+							default:
888
+								TCP_EV_CONNECT_ERR(errno, TCP_LADDR(c),
889
+													TCP_LPORT(c), TCP_PSU(c),
890
+													TCP_PROTO(c));
891
+						}
892
+						TCP_STATS_CONNECT_FAILED();
893
+					}else{
894
+						switch(errno){
895
+							case ECONNREFUSED:
815 896
 							case ECONNRESET:
816
-							/*case EHOSTUNREACH: -- not posix */
817
-								dst_blacklist_su((c->state==S_CONN_CONNECT)?
818
-														BLST_ERR_CONNECT:
819
-														BLST_ERR_SEND,
897
+								TCP_STATS_CON_RESET();
898
+								/* no break */
899
+							case ENETUNREACH:
900
+							case EHOSTUNREACH: /* not posix for send() */
901
+#ifdef USE_DST_BLACKLIST
902
+								if (cfg_get(core, core_cfg, use_dst_blacklist))
903
+									dst_blacklist_su(BLST_ERR_SEND,
820 904
 														c->rcv.proto,
821 905
 														&c->rcv.src_su, 0);
906
+#endif /* USE_DST_BLACKLIST */
822 907
 								break;
823 908
 						}
824
-#endif /* USE_DST_BLACKLIST */
909
+					}
825 910
 					ret=-1;
826 911
 					LOG(L_ERR, "ERROR: wbuf_runq: %s [%d]\n",
827 912
 						strerror(errno), errno);
... ...
@@ -839,8 +924,10 @@ inline static int wbufq_run(int fd, struct tcp_connection* c, int* empty)
839 924
 	lock_release(&c->write_lock);
840 925
 	if (likely(ret>0)){
841 926
 		q->wr_timeout=get_ticks_raw()+cfg_get(tcp, tcp_cfg, send_timeout);
842
-		if (unlikely(c->state==S_CONN_CONNECT || c->state==S_CONN_ACCEPT))
927
+		if (unlikely(c->state==S_CONN_CONNECT || c->state==S_CONN_ACCEPT)){
928
+			TCP_STATS_ESTABLISHED(c->state);
843 929
 			c->state=S_CONN_OK;
930
+		}
844 931
 	}
845 932
 	return ret;
846 933
 }
... ...
@@ -876,6 +963,8 @@ again:
876 963
 		else if (errno!=EAGAIN && errno!=EWOULDBLOCK){
877 964
 			LOG(L_ERR, "tcp_blocking_write: failed to send: (%d) %s\n",
878 965
 					errno, strerror(errno));
966
+			TCP_EV_SEND_TIMEOUT(errno, &c->rcv);
967
+			TCP_STATS_SEND_TIMEOUT();
879 968
 			goto error;
880 969
 		}
881 970
 	}else if (n<len){
... ...
@@ -1032,19 +1121,37 @@ again:
1032 1121
 				*state=S_CONN_CONNECT;
1033 1122
 			else if (errno==EINTR) goto again;
1034 1123
 			else if (errno!=EALREADY){
1124
+				switch(errno){
1125
+					case ENETUNREACH:
1126
+					case EHOSTUNREACH:
1035 1127
 #ifdef USE_DST_BLACKLIST
1036
-				if (cfg_get(core, core_cfg, use_dst_blacklist))
1037
-					switch(errno){
1038
-						case ECONNREFUSED:
1039
-						case ENETUNREACH:
1040
-						case ETIMEDOUT:
1041
-						case ECONNRESET:
1042
-						case EHOSTUNREACH:
1043
-							dst_blacklist_su(BLST_ERR_CONNECT, type, server,
1044
-												0);
1045
-							break;
1046
-				}
1128
+						if (cfg_get(core, core_cfg, use_dst_blacklist))
1129
+							dst_blacklist_su(BLST_ERR_CONNECT, type, server,0);
1047 1130
 #endif /* USE_DST_BLACKLIST */
1131
+						TCP_EV_CONNECT_UNREACHABLE(errno, 0, 0, server, type);
1132
+						break;
1133
+					case ETIMEDOUT:
1134
+#ifdef USE_DST_BLACKLIST
1135
+						if (cfg_get(core, core_cfg, use_dst_blacklist))
1136
+							dst_blacklist_su(BLST_ERR_CONNECT, type, server,0);
1137
+#endif /* USE_DST_BLACKLIST */
1138
+						TCP_EV_CONNECT_TIMEOUT(errno, 0, 0, server, type);
1139
+						break;
1140
+					case ECONNREFUSED:
1141
+					case ECONNRESET:
1142
+#ifdef USE_DST_BLACKLIST
1143
+						if (cfg_get(core, core_cfg, use_dst_blacklist))
1144
+							dst_blacklist_su(BLST_ERR_CONNECT, type, server,0);
1145
+#endif /* USE_DST_BLACKLIST */
1146
+						TCP_EV_CONNECT_RST(errno, 0, 0, server, type);
1147
+						break;
1148
+					case EAGAIN:/* not posix, but supported on linux and bsd */
1149
+						TCP_EV_CONNECT_NO_MORE_PORTS(errno, 0, 0, server,type);
1150
+						break;
1151
+					default:
1152
+						TCP_EV_CONNECT_ERR(errno, 0, 0, server, type);
1153
+				}
1154
+				TCP_STATS_CONNECT_FAILED();
1048 1155
 				LOG(L_ERR, "ERROR: tcp_do_connect: connect %s: (%d) %s\n",
1049 1156
 							su2a(server, sizeof(*server)),
1050 1157
 							errno, strerror(errno));
... ...
@@ -1744,9 +1851,11 @@ no_id:
1744 1851
 						DBG("tcp_send: pending write on new connection %p "
1745 1852
 								" (%d/%d bytes written)\n", c, n, len);
1746 1853
 						if (n<0) n=0;
1747
-						else 
1854
+						else{
1855
+							TCP_STATS_ESTABLISHED(S_CONN_CONNECT);
1748 1856
 							c->state=S_CONN_OK; /* partial write => connect()
1749 1857
 													ended */
1858
+						}
1750 1859
 						/* add to the write queue */
1751 1860
 						lock_get(&c->write_lock);
1752 1861
 							if (unlikely(_wbufq_insert(c, buf+n, len-n)<0)){
... ...
@@ -1774,19 +1883,33 @@ no_id:
1774 1883
 						n=len;
1775 1884
 						goto end;
1776 1885
 					}
1886
+					/* if first write failed it's most likely a
1887
+					   connect error */
1888
+					switch(errno){
1889
+						case ENETUNREACH:
1890
+						case EHOSTUNREACH:  /* not posix for send() */
1777 1891
 #ifdef USE_DST_BLACKLIST
1778
-					if (cfg_get(core, core_cfg, use_dst_blacklist))
1779
-						switch(errno){
1780
-							case ENETUNREACH:
1781
-							case ECONNRESET:
1782
-							/*case EHOSTUNREACH: -- not posix */
1783
-								/* if first write failed it's most likely a
1784
-								   connect error */
1892
+							if (cfg_get(core, core_cfg, use_dst_blacklist))
1785 1893
 								dst_blacklist_add( BLST_ERR_CONNECT, dst, 0);
1786
-								break;
1787
-						}
1788 1894
 #endif /* USE_DST_BLACKLIST */
1895
+							TCP_EV_CONNECT_UNREACHABLE(errno, TCP_LADDR(c),
1896
+									TCP_LPORT(c), TCP_PSU(c), TCP_PROTO(c));
1897
+							break;
1898
+						case ECONNREFUSED:
1899
+						case ECONNRESET:
1900
+#ifdef USE_DST_BLACKLIST
1901
+							if (cfg_get(core, core_cfg, use_dst_blacklist))
1902
+								dst_blacklist_add( BLST_ERR_CONNECT, dst, 0);
1903
+#endif /* USE_DST_BLACKLIST */
1904
+							TCP_EV_CONNECT_RST(errno, TCP_LADDR(c),
1905
+									TCP_LPORT(c), TCP_PSU(c), TCP_PROTO(c));
1906
+							break;
1907
+						default:
1908
+							TCP_EV_CONNECT_ERR(errno, TCP_LADDR(c),
1909
+									TCP_LPORT(c), TCP_PSU(c), TCP_PROTO(c));
1910
+					}
1789 1911
 					/* error: destroy it directly */
1912
+					TCP_STATS_CONNECT_FAILED();
1790 1913
 					LOG(L_ERR, "ERROR: tcp_send %s: connect & send "
1791 1914
 										" for %p failed:" " %s (%d)\n",
1792 1915
 										su2a(&dst->to, sizeof(dst->to)),
... ...
@@ -1794,6 +1917,7 @@ no_id:
1794 1917
 					goto conn_wait_error;
1795 1918
 				}
1796 1919
 				LOG(L_INFO, "tcp_send: quick connect for %p\n", c);
1920
+				TCP_STATS_ESTABLISHED(S_CONN_CONNECT);
1797 1921
 				c->state=S_CONN_OK;
1798 1922
 				/* send to tcp_main */
1799 1923
 				response[0]=(long)c;
... ...
@@ -1814,6 +1938,8 @@ no_id:
1814 1938
 								su2a(&dst->to, sizeof(dst->to)));
1815 1939
 				return -1;
1816 1940
 			}
1941
+			if (likely(c->state==S_CONN_OK))
1942
+				TCP_STATS_ESTABLISHED(S_CONN_CONNECT);
1817 1943
 			atomic_set(&c->refcnt, 2); /* ref. from here and it will also
1818 1944
 			                              be added in the tcp_main hash */
1819 1945
 			fd=c->s;
... ...
@@ -1965,8 +2091,10 @@ send_it:
1965 2091
 			enable_write_watch=_wbufq_empty(c);
1966 2092
 			if (n<0) n=0;
1967 2093
 			else if (unlikely(c->state==S_CONN_CONNECT ||
1968
-						c->state==S_CONN_ACCEPT))
2094
+						c->state==S_CONN_ACCEPT)){
2095
+				TCP_STATS_ESTABLISHED(c->state);
1969 2096
 				c->state=S_CONN_OK; /* something was written */
2097
+			}
1970 2098
 			if (unlikely(_wbufq_add(c, buf+n, len-n)<0)){
1971 2099
 				lock_release(&c->write_lock);
1972 2100
 				n=-1;
... ...
@@ -1989,20 +2117,49 @@ send_it:
1989 2117
 			lock_release(&c->write_lock);
1990 2118
 		}
1991 2119
 #endif /* TCP_ASYNC */
1992
-#ifdef USE_DST_BLACKLIST
1993
-		if (cfg_get(core, core_cfg, use_dst_blacklist))
2120
+		if (unlikely(c->state==S_CONN_CONNECT)){
1994 2121
 			switch(errno){
1995 2122
 				case ENETUNREACH:
2123
+				case EHOSTUNREACH: /* not posix for send() */
2124
+#ifdef USE_DST_BLACKLIST
2125
+					if (cfg_get(core, core_cfg, use_dst_blacklist))
2126
+						dst_blacklist_su(BLST_ERR_CONNECT, c->rcv.proto,
2127
+											&c->rcv.src_su, 0);
2128
+#endif /* USE_DST_BLACKLIST */
2129
+					TCP_EV_CONNECT_UNREACHABLE(errno, TCP_LADDR(c),
2130
+									TCP_LPORT(c), TCP_PSU(c), TCP_PROTO(c));
2131
+					break;
2132
+				case ECONNREFUSED:
1996 2133
 				case ECONNRESET:
2134
+#ifdef USE_DST_BLACKLIST
2135
+					if (cfg_get(core, core_cfg, use_dst_blacklist))
2136
+						dst_blacklist_su(BLST_ERR_CONNECT, c->rcv.proto,
2137
+											&c->rcv.src_su, 0);
2138
+#endif /* USE_DST_BLACKLIST */
2139
+					TCP_EV_CONNECT_RST(errno, TCP_LADDR(c), TCP_LPORT(c),
2140
+										TCP_PSU(c), TCP_PROTO(c));
2141
+					break;
2142
+				default:
2143
+					TCP_EV_CONNECT_ERR(errno, TCP_LADDR(c), TCP_LPORT(c),
2144
+										TCP_PSU(c), TCP_PROTO(c));
2145
+				}
2146
+			TCP_STATS_CONNECT_FAILED();
2147
+		}else{
2148
+			switch(errno){
2149
+				case ECONNREFUSED:
2150
+				case ECONNRESET:
2151
+					TCP_STATS_CON_RESET();
2152
+					/* no break */
2153
+				case ENETUNREACH:
1997 2154
 				/*case EHOSTUNREACH: -- not posix */
1998
-					dst_blacklist_su((c->state==S_CONN_CONNECT)?
1999
-											BLST_ERR_CONNECT:
2000
-											BLST_ERR_SEND,
2001
-										c->rcv.proto,
2002
-										&c->rcv.src_su, 0);
2155
+#ifdef USE_DST_BLACKLIST
2156
+					if (cfg_get(core, core_cfg, use_dst_blacklist))
2157
+						dst_blacklist_su(BLST_ERR_SEND, c->rcv.proto,
2158
+												&c->rcv.src_su, 0);
2159
+#endif /* USE_DST_BLACKLIST */
2003 2160
 					break;
2004 2161
 			}
2005
-#endif /* USE_DST_BLACKLIST */
2162
+		}
2006 2163
 		LOG(L_ERR, "ERROR: tcp_send: failed to send on %p (%s:%d->%s): %s (%d)"
2007 2164
 					"\n", c, ip_addr2a(&c->rcv.dst_ip), c->rcv.dst_port,
2008 2165
 					su2a(&c->rcv.src_su, sizeof(c->rcv.src_su)),
... ...
@@ -2042,8 +2199,10 @@ error:
2042 2199
 	lock_release(&c->write_lock);
2043 2200
 #endif /* TCP_ASYNC */
2044 2201
 	/* in non-async mode here we're either in S_CONN_OK or S_CONN_ACCEPT*/
2045
-	if (unlikely(c->state==S_CONN_CONNECT || c->state==S_CONN_ACCEPT))
2202
+	if (unlikely(c->state==S_CONN_CONNECT || c->state==S_CONN_ACCEPT)){
2203
+			TCP_STATS_ESTABLISHED(c->state);
2046 2204
 			c->state=S_CONN_OK;
2205
+	}
2047 2206
 end:
2048 2207
 #ifdef TCP_FD_CACHE
2049 2208
 	if (unlikely((fd_cache_e==0) && use_fd_cache)){
... ...
@@ -2682,14 +2841,27 @@ inline static int handle_tcp_child(struct tcp_child* tcp_c, int fd_i)
2682 2841
 							"refcnt= %d\n", tcpconn,
2683 2842
 							atomic_get(&tcpconn->refcnt));
2684 2843
 					/* timeout */
2844
+					if (unlikely(tcpconn->state==S_CONN_CONNECT)){
2685 2845
 #ifdef USE_DST_BLACKLIST
2686
-					if (cfg_get(core, core_cfg, use_dst_blacklist))
2687
-						dst_blacklist_su((tcpconn->state==S_CONN_CONNECT)?
2688
-													BLST_ERR_CONNECT:
2689
-													BLST_ERR_SEND,
2846
+						if (cfg_get(core, core_cfg, use_dst_blacklist))
2847
+							dst_blacklist_su( BLST_ERR_CONNECT,
2848
+													tcpconn->rcv.proto,
2849
+													&tcpconn->rcv.src_su, 0);
2850
+#endif /* USE_DST_BLACKLIST */
2851
+						TCP_EV_CONNECT_TIMEOUT(0, TCP_LADDR(tcpconn),
2852
+										TCP_LPORT(tcpconn), TCP_PSU(tcpconn),
2853
+										TCP_PROTO(tcpconn));
2854
+						TCP_STATS_CONNECT_FAILED();
2855
+					}else{
2856
+#ifdef USE_DST_BLACKLIST
2857
+						if (cfg_get(core, core_cfg, use_dst_blacklist))
2858
+							dst_blacklist_su( BLST_ERR_SEND,
2690 2859
 													tcpconn->rcv.proto,
2691 2860
 													&tcpconn->rcv.src_su, 0);
2692 2861
 #endif /* USE_DST_BLACKLIST */
2862
+						TCP_EV_SEND_TIMEOUT(0, &tcpconn->rcv);
2863
+						TCP_STATS_SEND_TIMEOUT();
2864
+					}
2693 2865
 					if (unlikely(tcpconn->flags & F_CONN_WRITE_W)){
2694 2866
 						io_watch_del(&io_h, tcpconn->s, -1, IO_FD_CLOSING);
2695 2867
 						tcpconn->flags&=~F_CONN_WRITE_W;
... ...
@@ -3182,6 +3354,7 @@ static inline int handle_new_connect(struct socket_info* si)
3182 3354
 					*tcp_connections_no,
3183 3355
 					cfg_get(tcp, tcp_cfg, max_connections));
3184 3356
 		close(new_sock);
3357
+		TCP_STATS_LOCAL_REJECT();
3185 3358
 		return 1; /* success, because the accept was succesfull */
3186 3359
 	}
3187 3360
 	if (unlikely(init_sock_opt_accept(new_sock)<0)){
... ...
@@ -3190,6 +3363,7 @@ static inline int handle_new_connect(struct socket_info* si)
3190 3363
 		return 1; /* success, because the accept was succesfull */
3191 3364
 	}
3192 3365
 	(*tcp_connections_no)++;
3366
+	TCP_STATS_ESTABLISHED(S_CONN_ACCEPT);
3193 3367
 	
3194 3368
 	dst_su=&si->su;
3195 3369
 	if (unlikely(si->flags & SI_IS_ANY)){
... ...
@@ -3323,6 +3497,16 @@ inline static int handle_tcpconn_ev(struct tcp_connection* tcpconn, short ev,
3323 3497
 				LOG(L_CRIT, "BUG: tcpconn_ev: unhashed connection %p\n",
3324 3498
 							tcpconn);
3325 3499
 			}
3500
+			if (unlikely(ev & POLLERR)){
3501
+				if (unlikely(tcpconn->state=S_CONN_CONNECT)){
3502
+					TCP_EV_CONNECT_ERR(0, TCP_LADDR(tcpconn),
3503
+										TCP_LPORT(tcpconn), TCP_PSU(tcpconn),
3504
+										TCP_PROTO(tcpconn));
3505
+					TCP_STATS_CONNECT_FAILED();
3506
+				}else{
3507
+					TCP_STATS_CON_RESET(); /* FIXME: it could != RST */
3508
+				}
3509
+			}
3326 3510
 			tcpconn_put_destroy(tcpconn);
3327 3511
 			goto error;
3328 3512
 		}
... ...
@@ -3485,15 +3669,27 @@ static ticks_t tcpconn_main_timeout(ticks_t t, struct timer_ln* tl, void* data)
3485 3669
 		else
3486 3670
 			return (ticks_t)(c->timeout - t);
3487 3671
 	}
3488
-#ifdef USE_DST_BLACKLIST
3489 3672
 	/* if time out due to write, add it to the blacklist */
3490
-	if (tcp_async && _wbufq_non_empty(c) &&
3491
-			TICKS_GE(t, c->wbuf_q.wr_timeout) &&
3492
-			cfg_get(core, core_cfg, use_dst_blacklist))
3493
-		dst_blacklist_su((c->state==S_CONN_CONNECT)?  BLST_ERR_CONNECT:
3494
-										BLST_ERR_SEND,
3495
-								c->rcv.proto, &c->rcv.src_su, 0);
3673
+	if (tcp_async && _wbufq_non_empty(c) && TICKS_GE(t, c->wbuf_q.wr_timeout)){
3674
+		if (unlikely(c->state==S_CONN_CONNECT)){
3675
+#ifdef USE_DST_BLACKLIST
3676
+			if (cfg_get(core, core_cfg, use_dst_blacklist))
3677
+				dst_blacklist_su(BLST_ERR_CONNECT, c->rcv.proto,
3678
+									&c->rcv.src_su, 0);
3679
+#endif /* USE_DST_BLACKLIST */
3680
+			TCP_EV_CONNECT_TIMEOUT(0, TCP_LADDR(c), TCP_LPORT(c), TCP_PSU(c),
3681
+									TCP_PROTO(c));
3682
+			TCP_STATS_CONNECT_FAILED();
3683
+		}else{
3684
+#ifdef USE_DST_BLACKLIST
3685
+			if (cfg_get(core, core_cfg, use_dst_blacklist))
3686
+				dst_blacklist_su(BLST_ERR_SEND, c->rcv.proto,
3687
+									&c->rcv.src_su, 0);
3496 3688
 #endif /* USE_DST_BLACKLIST */
3689
+			TCP_EV_SEND_TIMEOUT(0, &c->rcv);
3690
+			TCP_STATS_SEND_TIMEOUT();
3691
+		}
3692
+	}
3497 3693
 #else /* ! TCP_ASYNC */
3498 3694
 	if (TICKS_LT(t, c->timeout)){
3499 3695
 		/* timeout extended, exit */
... ...
@@ -3520,6 +3716,8 @@ static ticks_t tcpconn_main_timeout(ticks_t t, struct timer_ln* tl, void* data)
3520 3716
 			c->flags&=~(F_CONN_READ_W|F_CONN_WRITE_W);
3521 3717
 		}
3522 3718
 	}
3719
+	TCP_EV_IDLE_CONN_CLOSED(0, &c->rcv);
3720
+	TCP_STATS_CON_TIMEOUT();
3523 3721
 	tcpconn_put_destroy(c);
3524 3722
 	return 0;
3525 3723
 }
... ...
@@ -3772,6 +3970,7 @@ void destroy_tcp()
3772 3970
 			shm_free(tcpconn_id_hash);
3773 3971
 			tcpconn_id_hash=0;
3774 3972
 		}
3973
+		DESTROY_TCP_STATS();
3775 3974
 		if (tcp_connections_no){
3776 3975
 			shm_free(tcp_connections_no);
3777 3976
 			tcp_connections_no=0;
... ...
@@ -3832,6 +4031,7 @@ int init_tcp()
3832 4031
 		goto error;
3833 4032
 	}
3834 4033
 	*tcp_connections_no=0;
4034
+	if (INIT_TCP_STATS()!=0) goto error;
3835 4035
 	connection_id=shm_malloc(sizeof(int));
3836 4036
 	if (connection_id==0){
3837 4037
 		LOG(L_CRIT, "ERROR: init_tcp: could not alloc globals\n");
... ...
@@ -41,6 +41,7 @@
41 41
  * 2008-02-04  optimizations: handle POLLRDHUP (if supported), detect short
42 42
  *              reads (sock. buffer empty) (andrei)
43 43
  * 2009-02-26  direct blacklist support (andrei)
44
+ * 2009-04-09  tcp ev and tcp stats macros added (andrei)
44 45
  */
45 46
 
46 47
 #ifdef USE_TCP
... ...
@@ -61,6 +62,8 @@
61 62
 
62 63
 #include "dprint.h"
63 64
 #include "tcp_conn.h"
65
+#include "tcp_stats.h"
66
+#include "tcp_ev.h"
64 67
 #include "pass_fd.h"
65 68
 #include "globals.h"
66 69
 #include "receive.h"
... ...
@@ -146,19 +149,47 @@ again:
146 149
 				bytes_read=0; /* nothing has been read */
147 150
 			}else if (errno == EINTR) goto again;
148 151
 			else{
149
-#ifdef USE_DST_BLACKLIST
150
-				if (cfg_get(core, core_cfg, use_dst_blacklist))
152
+				if (unlikely(c->state=S_CONN_CONNECT)){
151 153
 					switch(errno){
152 154
 						case ECONNRESET:
155
+#ifdef USE_DST_BLACKLIST
156
+							if (cfg_get(core, core_cfg, use_dst_blacklist))
157
+								dst_blacklist_su(BLST_ERR_CONNECT,
158
+														c->rcv.proto,
159
+														&c->rcv.src_su, 0);
160
+#endif /* USE_DST_BLACKLIST */
161
+							TCP_EV_CONNECT_RST(errno, TCP_LADDR(c),
162
+									TCP_LPORT(c), TCP_PSU(c), TCP_PROTO(c));
163
+							break;
153 164
 						case ETIMEDOUT:
154
-							dst_blacklist_su((c->state==S_CONN_CONNECT)?
155
-													BLST_ERR_CONNECT:
156
-													BLST_ERR_SEND,
157
-													c->rcv.proto,
158
-													&c->rcv.src_su, 0);
165
+#ifdef USE_DST_BLACKLIST
166
+							if (cfg_get(core, core_cfg, use_dst_blacklist))
167
+								dst_blacklist_su(BLST_ERR_CONNECT,
168
+														c->rcv.proto,
169
+														&c->rcv.src_su, 0);
170
+#endif /* USE_DST_BLACKLIST */
171
+							TCP_EV_CONNECT_TIMEOUT(errno, TCP_LADDR(c),
172
+									TCP_LPORT(c), TCP_PSU(c), TCP_PROTO(c));
159 173
 							break;
174
+						default:
175
+							TCP_EV_CONNECT_ERR(errno, TCP_LADDR(c),
176
+									TCP_LPORT(c), TCP_PSU(c), TCP_PROTO(c));
160 177
 					}
178
+					TCP_STATS_CONNECT_FAILED();
179
+				}else{
180
+						switch(errno){
181
+							case ECONNRESET:
182
+								TCP_STATS_CON_RESET();
183
+							case ETIMEDOUT:
184
+#ifdef USE_DST_BLACKLIST
185
+								if (cfg_get(core, core_cfg, use_dst_blacklist))
186
+									dst_blacklist_su(BLST_ERR_SEND,
187
+														c->rcv.proto,
188
+														&c->rcv.src_su, 0);
161 189
 #endif /* USE_DST_BLACKLIST */
190
+								break;
191
+						}
192
+				}
162 193
 				LOG(L_ERR, "ERROR: tcp_read: error reading: %s (%d)\n",
163 194
 							strerror(errno), errno);
164 195
 				r->error=TCP_READ_ERROR;
... ...
@@ -170,14 +201,18 @@ again:
170 201
 			*flags|=RD_CONN_EOF;
171 202
 			DBG("tcp_read: EOF on %p, FD %d\n", c, fd);
172 203
 		}else{
173
-			if (unlikely(c->state==S_CONN_CONNECT || c->state==S_CONN_ACCEPT))
204
+			if (unlikely(c->state==S_CONN_CONNECT || c->state==S_CONN_ACCEPT)){
205
+				TCP_STATS_ESTABLISHED(c->state);
174 206
 				c->state=S_CONN_OK;
207
+			}
175 208
 		}
176 209
 		/* short read */
177 210
 		*flags|=RD_CONN_SHORT_READ;
178 211
 	}else{ /* else normal full read */
179
-		if (unlikely(c->state==S_CONN_CONNECT || c->state==S_CONN_ACCEPT))
212
+		if (unlikely(c->state==S_CONN_CONNECT || c->state==S_CONN_ACCEPT)){
213
+			TCP_STATS_ESTABLISHED(c->state);
180 214
 			c->state=S_CONN_OK;
215
+		}
181 216
 	}
182 217
 #ifdef EXTRA_DEBUG
183 218
 	DBG("tcp_read: read %d bytes:\n%.*s\n", bytes_read, bytes_read, r->pos);
... ...
@@ -379,7 +414,7 @@ int tcp_read_headers(struct tcp_connection *c, int* read_flags)
379 414
 							r->state=H_STUN_MSG;
380 415
 						/* body will used as pointer to the last used byte */
381 416
 							r->body=p;
382
-							body_len = 0;
417
+							r->content_len = 0;
383 418
 							DBG("stun msg detected\n");
384 419
 						}else
385 420
 #endif
... ...
@@ -421,14 +456,13 @@ int tcp_read_headers(struct tcp_connection *c, int* read_flags)
421 456
 #ifdef USE_STUN
422 457
 			case H_STUN_MSG:
423 458
 				if ((r->pos - r->body) >= sizeof(struct stun_hdr)) {
424
-					r->content_len = 0;
425 459
 					/* copy second short from buffer where should be body 
426 460
 					 * length 
427 461
 					 */
428 462
 					memcpy(&body_len, &r->start[sizeof(unsigned short)], 
429 463
 						sizeof(unsigned short));
430 464
 					
431
-					body_len = ntohs(r->content_len);
465
+					body_len = ntohs(body_len);
432 466
 					
433 467
 					/* check if there is valid magic cookie */
434 468
 					memcpy(&mc, &r->start[sizeof(unsigned int)], 
... ...
@@ -455,6 +489,7 @@ int tcp_read_headers(struct tcp_connection *c, int* read_flags)
455 489
 									   SHA_DIGEST_LENGTH;
456 490
 						}
457 491
 					}
492
+					r->content_len=body_len;
458 493
 				}
459 494
 				else {
460 495
 					p = r->pos; 
... ...
@@ -463,15 +498,18 @@ int tcp_read_headers(struct tcp_connection *c, int* read_flags)
463 498
 				
464 499
 			case H_STUN_READ_BODY:
465 500
 				/* check if the whole body was read */
501
+				body_len=r->content_len;
466 502
 				if ((r->pos - r->body) >= body_len) {
467 503
 					r->body += body_len;
468 504
 					p = r->body;
469 505
 					if (is_msg_complete(r) != 0) {
506
+						r->content_len=0;
470 507
 						goto skip;
471 508
 					}
472 509
 					else {
473 510
 						/* set content_len to length of fingerprint */
474 511
 						body_len = sizeof(struct stun_attr)+SHA_DIGEST_LENGTH;
512
+						r->content_len=body_len;
475 513
 					}
476 514
 				}
477 515
 				else {
... ...
@@ -481,12 +519,14 @@ int tcp_read_headers(struct tcp_connection *c, int* read_flags)
481 519
 				
482 520
 			case H_STUN_FP:
483 521
 				/* content_len contains length of fingerprint in this place! */
522
+				body_len=r->content_len;
484 523
 				if ((r->pos - r->body) >= body_len) {
485 524
 					r->body += body_len;
486 525
 					p = r->body;
487 526
 					r->state = H_STUN_END;
488 527
 					r->flags |= F_TCP_REQ_COMPLETE |
489 528
 						F_TCP_REQ_HAS_CLEN; /* hack to avoid error check */
529
+					r->content_len=0;
490 530
 					goto skip;
491 531
 				}
492 532
 				else {
493 533
new file mode 100644
... ...
@@ -0,0 +1,92 @@
1
+/* 
2
+ * $Id$
3
+ * 
4
+ * Copyright (C) 2009 iptelorg GmbH
5
+ *
6
+ * Permission to use, copy, modify, and distribute this software for any
7
+ * purpose with or without fee is hereby granted, provided that the above
8
+ * copyright notice and this permission notice appear in all copies.
9
+ *
10
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
+ */
18
+/*
19
+ * tcp_stats.h - tcp statistics macros
20
+ */
21
+/*
22
+ * History:
23
+ * --------
24
+ *  2009-04-08  initial version (andrei)
25
+*/
26
+
27
+#ifndef __tcp_stats_h
28
+#define __tcp_stats_h
29
+
30
+#ifndef USE_TCP_STATS
31
+
32
+#define INIT_TCP_STATS() 0 /* success */
33
+#define DESTROY_TCP_STATS()
34
+
35
+#define TCP_STATS_ESTABLISHED(state)
36
+#define TCP_STATS_CONNECT_FAILED()
37
+#define TCP_STATS_LOCAL_REJECT()
38
+#define TCP_STATS_CON_TIMEOUT()
39
+#define TCP_STATS_CON_RESET()
40
+#define TCP_STATS_SEND_TIMEOUT()
41
+#define TCP_STATS_SENDQ_FULL()
42
+
43
+#else /* USE_TCP_STATS */
44
+
45
+#define INIT_TCP_STATS() 0 /* success */
46
+
47
+#define DESTROY_TCP_STATS()
48
+
49
+
50
+/** called each time a new tcp connection is established.
51
+ *  @param state - S_CONN_ACCEPT if it was the result of an accept()
52
+ *               - S_CONN_CONNECT if it was the result of a connect()
53
+ * Note: in general it will be called when the first packet was received or
54
+ *   sent on the new connection and not immediately after accept() or 
55
+ *   connect()
56
+ */
57
+#define TCP_STATS_ESTABLISHED(state)
58
+
59
+/** called each time a new outgoing connection fails.  */
60
+#define TCP_STATS_CONNECT_FAILED()
61
+
62
+/** called each time a new incoming connection is rejected.
63
+ * (accept() denied due to maximum number of TCP connections being exceeded)
64
+ */
65
+#define TCP_STATS_LOCAL_REJECT()
66
+
67
+
68
+/** called each time a connection lifetime expires.
69
+  * (the connection is closed for being idle for too long)
70
+  */
71
+#define TCP_STATS_CON_TIMEOUT()
72
+
73
+
74
+/** called each time a TCP RST is received on an established connection.  */
75
+#define TCP_STATS_CON_RESET()
76
+
77
+/** called each time a send operation fails due to a timeout.
78
+  * FIXME: it works only in async mode (in sync. mode a send might timeout
79
+  *  but the stats won't be increased).
80
+  */
81
+#define TCP_STATS_SEND_TIMEOUT()
82
+
83
+/** called each time a send fails due to the buffering capacity being exceeded.
84
+  * (used only in tcp async mode)
85
+  */
86
+#define TCP_STATS_SENDQ_FULL()
87
+
88
+#endif /* USE_TCP_STATS */
89
+
90
+#endif /*__tcp_stats_h*/
91
+
92
+/* vi: set ts=4 sw=4 tw=79:ai:cindent: */