... | ... |
@@ -58,7 +58,7 @@ MAIN_NAME=ser |
58 | 58 |
VERSION = 0 |
59 | 59 |
PATCHLEVEL = 10 |
60 | 60 |
SUBLEVEL = 99 |
61 |
-EXTRAVERSION = -dev11-tcp |
|
61 |
+EXTRAVERSION = -dev12-tcp |
|
62 | 62 |
|
63 | 63 |
RELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) |
64 | 64 |
OS = $(shell uname -s | sed -e s/SunOS/solaris/ | tr "[A-Z]" "[a-z]") |
... | ... |
@@ -1140,6 +1140,9 @@ ifeq ($(OS), darwin) |
1140 | 1140 |
else |
1141 | 1141 |
LIBS= -lfl -lresolv #dlopen is in libc |
1142 | 1142 |
endif |
1143 |
+ ifeq ($(NO_KQUEUE),) |
|
1144 |
+ DEFS+=-DHAVE_KQUEUE |
|
1145 |
+ endif |
|
1143 | 1146 |
ifeq ($(NO_SELECT),) |
1144 | 1147 |
DEFS+=-DHAVE_SELECT |
1145 | 1148 |
endif |
... | ... |
@@ -7,18 +7,31 @@ $Id$ |
7 | 7 |
|
8 | 8 |
|
9 | 9 |
new archs: |
10 |
- - powerpc64 support |
|
11 |
- - alpha experimental support |
|
10 |
+ |
|
11 |
+core: |
|
12 |
+ - tcp: - improved performance (io event handling), using OS specific |
|
13 |
+ optimizations |
|
14 |
+ - 1024 connections limit removed (see tcp_max_connections) |
|
15 |
+new config variables: |
|
16 |
+ tcp_connection_lifetime = value (s) - how long the lifetime of a |
|
17 |
+ tcp connection will be exteneded after an IO event (accept, connect, |
|
18 |
+ read, write). Default: 120 s. |
|
19 |
+ tcp_poll_method = poll|select|epoll_et|epoll-lt|kqueue|devpoll - poll |
|
20 |
+ method used (by default the best one for the current OS is selected) |
|
21 |
+ tcp_max_connections = no - maximum number of tcp connections (if the number |
|
22 |
+ is exceeded no new tcp connections will be accepted). Default: 2048. |
|
12 | 23 |
|
13 | 24 |
|
14 |
-0.8.99-dev changes |
|
25 |
+0.9.0 changes |
|
15 | 26 |
|
16 | 27 |
|
17 | 28 |
new archs: |
29 |
+ - alpha experimental support |
|
18 | 30 |
- mips2/cobalt experimental support |
19 | 31 |
- x86_64 support |
20 | 32 |
- OS X (darwin) support |
21 | 33 |
- sparc32 single cpu highly experimental support |
34 |
+ - ppc64 support |
|
22 | 35 |
|
23 | 36 |
modules: |
24 | 37 |
- enum - support for more than one NAPTR |
... | ... |
@@ -52,6 +52,8 @@ |
52 | 52 |
* 2004-10-08 more escapes: \", \xHH, \nnn and minor optimizations (andrei) |
53 | 53 |
* 2004-10-19 added FROM_URI and TO_URI (andrei) |
54 | 54 |
* 2004-11-30 added force_send_socket |
55 |
+ * 2005-07-08 added tcp_connection_lifetime, tcp_poll_method, |
|
56 |
+ * tcp_max_connections (andrei) |
|
55 | 57 |
*/ |
56 | 58 |
|
57 | 59 |
|
... | ... |
@@ -209,6 +211,9 @@ TCP_CHILDREN "tcp_children" |
209 | 211 |
TCP_ACCEPT_ALIASES "tcp_accept_aliases" |
210 | 212 |
TCP_SEND_TIMEOUT "tcp_send_timeout" |
211 | 213 |
TCP_CONNECT_TIMEOUT "tcp_connect_timeout" |
214 |
+TCP_CON_LIFETIME "tcp_connection_lifetime" |
|
215 |
+TCP_POLL_METHOD "tcp_poll_method" |
|
216 |
+TCP_MAX_CONNECTIONS "tcp_max_connections" |
|
212 | 217 |
DISABLE_TLS "disable_tls" |
213 | 218 |
TLSLOG "tlslog"|"tls_log" |
214 | 219 |
TLS_PORT_NO "tls_port_no" |
... | ... |
@@ -372,6 +377,12 @@ EAT_ABLE [\ \t\b\r] |
372 | 377 |
return TCP_SEND_TIMEOUT; } |
373 | 378 |
<INITIAL>{TCP_CONNECT_TIMEOUT} { count(); yylval.strval=yytext; |
374 | 379 |
return TCP_CONNECT_TIMEOUT; } |
380 |
+<INITIAL>{TCP_CON_LIFETIME} { count(); yylval.strval=yytext; |
|
381 |
+ return TCP_CON_LIFETIME; } |
|
382 |
+<INITIAL>{TCP_POLL_METHOD} { count(); yylval.strval=yytext; |
|
383 |
+ return TCP_POLL_METHOD; } |
|
384 |
+<INITIAL>{TCP_MAX_CONNECTIONS} { count(); yylval.strval=yytext; |
|
385 |
+ return TCP_MAX_CONNECTIONS; } |
|
375 | 386 |
<INITIAL>{DISABLE_TLS} { count(); yylval.strval=yytext; return DISABLE_TLS; } |
376 | 387 |
<INITIAL>{TLSLOG} { count(); yylval.strval=yytext; return TLS_PORT_NO; } |
377 | 388 |
<INITIAL>{TLS_PORT_NO} { count(); yylval.strval=yytext; return TLS_PORT_NO; } |
... | ... |
@@ -53,11 +53,13 @@ |
53 | 53 |
* 2004-03-30 added DISABLE_CORE and OPEN_FD_LIMIT (andrei) |
54 | 54 |
* 2004-04-29 added SOCK_MODE, SOCK_USER & SOCK_GROUP (andrei) |
55 | 55 |
* 2004-05-03 applied multicast support patch (MCAST_LOOPBACK) from janakj |
56 |
- added MCAST_TTL (andrei) |
|
56 |
+ * added MCAST_TTL (andrei) |
|
57 | 57 |
* 2004-07-05 src_ip & dst_ip will detect ip addresses between quotes |
58 | 58 |
* (andrei) |
59 | 59 |
* 2004-10-19 added FROM_URI, TO_URI (andrei) |
60 | 60 |
* 2004-11-30 added force_send_socket (andrei) |
61 |
+ * 2005-07-08 added TCP_CON_LIFETIME, TCP_POLL_METHOD, TCP_MAX_CONNECTIONS |
|
62 |
+ * (andrei) |
|
61 | 63 |
*/ |
62 | 64 |
|
63 | 65 |
|
... | ... |
@@ -224,6 +226,9 @@ static struct socket_id* mk_listen_id(char*, int, int); |
224 | 226 |
%token TCP_CHILDREN |
225 | 227 |
%token TCP_CONNECT_TIMEOUT |
226 | 228 |
%token TCP_SEND_TIMEOUT |
229 |
+%token TCP_CON_LIFETIME |
|
230 |
+%token TCP_POLL_METHOD |
|
231 |
+%token TCP_MAX_CONNECTIONS |
|
227 | 232 |
%token DISABLE_TLS |
228 | 233 |
%token TLSLOG |
229 | 234 |
%token TLS_PORT_NO |
... | ... |
@@ -490,6 +495,51 @@ assign_stm: DEBUG EQUAL NUMBER { debug=$3; } |
490 | 495 |
#endif |
491 | 496 |
} |
492 | 497 |
| TCP_SEND_TIMEOUT EQUAL error { yyerror("number expected"); } |
498 |
+ | TCP_CON_LIFETIME EQUAL NUMBER { |
|
499 |
+ #ifdef USE_TCP |
|
500 |
+ tcp_con_lifetime=$3; |
|
501 |
+ #else |
|
502 |
+ warn("tcp support not compiled in"); |
|
503 |
+ #endif |
|
504 |
+ } |
|
505 |
+ | TCP_CON_LIFETIME EQUAL error { yyerror("number expected"); } |
|
506 |
+ | TCP_POLL_METHOD EQUAL ID { |
|
507 |
+ #ifdef USE_TCP |
|
508 |
+ tcp_poll_method=get_poll_type($3); |
|
509 |
+ if (tcp_poll_method==POLL_NONE){ |
|
510 |
+ LOG(L_CRIT, "bad poll method name:" |
|
511 |
+ " %s\n, try one of %s.\n", |
|
512 |
+ $3, poll_support); |
|
513 |
+ yyerror("bad tcp_poll_method " |
|
514 |
+ "value"); |
|
515 |
+ } |
|
516 |
+ #else |
|
517 |
+ warn("tcp support not compiled in"); |
|
518 |
+ #endif |
|
519 |
+ } |
|
520 |
+ | TCP_POLL_METHOD EQUAL STRING { |
|
521 |
+ #ifdef USE_TCP |
|
522 |
+ tcp_poll_method=get_poll_type($3); |
|
523 |
+ if (tcp_poll_method==POLL_NONE){ |
|
524 |
+ LOG(L_CRIT, "bad poll method name:" |
|
525 |
+ " %s\n, try one of %s.\n", |
|
526 |
+ $3, poll_support); |
|
527 |
+ yyerror("bad tcp_poll_method " |
|
528 |
+ "value"); |
|
529 |
+ } |
|
530 |
+ #else |
|
531 |
+ warn("tcp support not compiled in"); |
|
532 |
+ #endif |
|
533 |
+ } |
|
534 |
+ | TCP_POLL_METHOD EQUAL error { yyerror("poll method name expected"); } |
|
535 |
+ | TCP_MAX_CONNECTIONS EQUAL NUMBER { |
|
536 |
+ #ifdef USE_TCP |
|
537 |
+ tcp_max_connections=$3; |
|
538 |
+ #else |
|
539 |
+ warn("tcp support not compiled in"); |
|
540 |
+ #endif |
|
541 |
+ } |
|
542 |
+ | TCP_MAX_CONNECTIONS EQUAL error { yyerror("number expected"); } |
|
493 | 543 |
| DISABLE_TLS EQUAL NUMBER { |
494 | 544 |
#ifdef USE_TLS |
495 | 545 |
tls_disable=$3; |
... | ... |
@@ -81,8 +81,10 @@ extern int tcp_disable; |
81 | 81 |
extern int tcp_accept_aliases; |
82 | 82 |
extern int tcp_connect_timeout; |
83 | 83 |
extern int tcp_send_timeout; |
84 |
+extern int tcp_con_lifetime; /* connection lifetime */ |
|
84 | 85 |
extern enum poll_types tcp_poll_method; |
85 | 86 |
extern int tcp_max_fd_no; |
87 |
+extern int tcp_max_connections; |
|
86 | 88 |
#endif |
87 | 89 |
#ifdef USE_TLS |
88 | 90 |
extern int tls_disable; |
... | ... |
@@ -374,7 +374,7 @@ char* check_poll_method(enum poll_types poll_method) |
374 | 374 |
#ifndef HAVE_KQUEUE |
375 | 375 |
ret="kqueue not supported, try re-compiling with -DHAVE_KQUEUE"; |
376 | 376 |
#else |
377 |
- /* only in FreeBSD 4.1, NETBSD 2.0, OpenBSD ???, Darwin ??? FIXME */ |
|
377 |
+ /* only in FreeBSD 4.1, NETBSD 2.0, OpenBSD 2.9, Darwin */ |
|
378 | 378 |
#ifdef __OS_freebsd |
379 | 379 |
if (os_ver<0x0401) /* if ver < 4.1 */ |
380 | 380 |
ret="kqueue not supported on FreeBSD < 4.1"; |
... | ... |
@@ -422,7 +422,7 @@ enum poll_types choose_poll_method() |
422 | 422 |
#endif |
423 | 423 |
#ifdef HAVE_KQUEUE |
424 | 424 |
if (poll_method==0) |
425 |
- /* only in FreeBSD 4.1, NETBSD 2.0, OpenBSD ???, Darwin ??? FIXME */ |
|
425 |
+ /* only in FreeBSD 4.1, NETBSD 2.0, OpenBSD 2.9, Darwin */ |
|
426 | 426 |
#ifdef __OS_freebsd |
427 | 427 |
if (os_ver>=0x0401) /* if ver >= 4.1 */ |
428 | 428 |
#elif defined (__OS_netbsd) |
... | ... |
@@ -44,13 +44,12 @@ |
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 120 /* in seconds */ |
|
48 |
-#define TCP_CON_SEND_TIMEOUT 120 /* timeout after a send */ |
|
47 |
+#define DEFAULT_TCP_CONNECTION_LIFETIME 120 /* in seconds */ |
|
49 | 48 |
#define DEFAULT_TCP_SEND_TIMEOUT 10 /* if a send can't write for more then 10s, |
50 | 49 |
timeout */ |
51 | 50 |
#define DEFAULT_TCP_CONNECT_TIMEOUT 10 /* if a connect doesn't complete in this |
52 | 51 |
time, timeout */ |
53 |
-#define DEFAULT_TCP_MAX_FD_NO 2048 /* maximum fd number */ |
|
52 |
+#define DEFAULT_TCP_MAX_CONNECTIONS 2048 /* maximum connections */ |
|
54 | 53 |
#define TCP_CHILD_TIMEOUT 5 /* after 5 seconds, the child "returns" |
55 | 54 |
the connection to the tcp master process */ |
56 | 55 |
#define TCP_MAIN_SELECT_TIMEOUT 5 /* how often "tcp main" checks for timeout*/ |
... | ... |
@@ -56,6 +56,8 @@ |
56 | 56 |
* signals, poll & select (andrei) |
57 | 57 |
* 2005-06-26 *bsd kqueue support (andrei) |
58 | 58 |
* 2005-07-04 solaris /dev/poll support (andrei) |
59 |
+ * 2005-07-08 tcp_max_connections, tcp_connection_lifetime, don't accept |
|
60 |
+ * more connections if tcp_max_connections is exceeded (andrei) |
|
59 | 61 |
*/ |
60 | 62 |
|
61 | 63 |
|
... | ... |
@@ -133,8 +135,12 @@ struct tcp_child{ |
133 | 135 |
int tcp_accept_aliases=0; /* by default don't accept aliases */ |
134 | 136 |
int tcp_connect_timeout=DEFAULT_TCP_CONNECT_TIMEOUT; |
135 | 137 |
int tcp_send_timeout=DEFAULT_TCP_SEND_TIMEOUT; |
138 |
+int tcp_con_lifetime=DEFAULT_TCP_CONNECTION_LIFETIME; |
|
136 | 139 |
enum poll_types tcp_poll_method=0; /* by default choose the best method */ |
137 |
-int tcp_max_fd_no=DEFAULT_TCP_MAX_FD_NO; |
|
140 |
+int tcp_max_connections=DEFAULT_TCP_MAX_CONNECTIONS; |
|
141 |
+int tcp_max_fd_no=0; |
|
142 |
+ |
|
143 |
+static int tcp_connections_no=0; /* current open connections */ |
|
138 | 144 |
|
139 | 145 |
/* connection hash table (after ip&port) , includes also aliases */ |
140 | 146 |
struct tcp_conn_alias** tcpconn_aliases_hash=0; |
... | ... |
@@ -412,10 +418,11 @@ struct tcp_connection* tcpconn_new(int sock, union sockaddr_union* su, |
412 | 418 |
c->type=PROTO_TCP; |
413 | 419 |
c->rcv.proto=PROTO_TCP; |
414 | 420 |
c->flags=0; |
415 |
- c->timeout=get_ticks()+TCP_CON_TIMEOUT; |
|
421 |
+ c->timeout=get_ticks()+tcp_con_lifetime; |
|
416 | 422 |
} |
417 | 423 |
|
418 | 424 |
|
425 |
+ tcp_connections_no++; |
|
419 | 426 |
return c; |
420 | 427 |
|
421 | 428 |
error: |
... | ... |
@@ -703,9 +710,9 @@ int tcp_send(int type, char* buf, unsigned len, union sockaddr_union* to, |
703 | 710 |
if (to){ |
704 | 711 |
su2ip_addr(&ip, to); |
705 | 712 |
port=su_getport(to); |
706 |
- c=tcpconn_get(id, &ip, port, TCP_CON_SEND_TIMEOUT); |
|
713 |
+ c=tcpconn_get(id, &ip, port, tcp_con_lifetime); |
|
707 | 714 |
}else if (id){ |
708 |
- c=tcpconn_get(id, 0, 0, TCP_CON_SEND_TIMEOUT); |
|
715 |
+ c=tcpconn_get(id, 0, 0, tcp_con_lifetime); |
|
709 | 716 |
}else{ |
710 | 717 |
LOG(L_CRIT, "BUG: tcp_send called with null id & to\n"); |
711 | 718 |
return -1; |
... | ... |
@@ -715,7 +722,7 @@ int tcp_send(int type, char* buf, unsigned len, union sockaddr_union* to, |
715 | 722 |
if (c==0) { |
716 | 723 |
if (to){ |
717 | 724 |
/* try again w/o id */ |
718 |
- c=tcpconn_get(0, &ip, port, TCP_CON_SEND_TIMEOUT); |
|
725 |
+ c=tcpconn_get(0, &ip, port, tcp_con_lifetime); |
|
719 | 726 |
goto no_id; |
720 | 727 |
}else{ |
721 | 728 |
LOG(L_ERR, "ERROR: tcp_send: id %d not found, dropping\n", |
... | ... |
@@ -983,6 +990,12 @@ static inline int handle_new_connect(struct socket_info* si) |
983 | 990 |
" connection(%d): %s\n", errno, strerror(errno)); |
984 | 991 |
return -1; |
985 | 992 |
} |
993 |
+ if (tcp_connections_no>=tcp_max_connections){ |
|
994 |
+ LOG(L_ERR, "ERROR: maximum number of connections exceeded: %d/%d\n", |
|
995 |
+ tcp_connections_no, tcp_max_connections); |
|
996 |
+ close(new_sock); |
|
997 |
+ return 1; /* success, because the accept was succesfull */ |
|
998 |
+ } |
|
986 | 999 |
if (init_sock_opt(new_sock)<0){ |
987 | 1000 |
LOG(L_ERR, "ERROR: handle_new_connect: init_sock_opt failed\n"); |
988 | 1001 |
close(new_sock); |
... | ... |
@@ -1037,6 +1050,7 @@ static void tcpconn_destroy(struct tcp_connection* tcpconn) |
1037 | 1050 |
#endif |
1038 | 1051 |
_tcpconn_rm(tcpconn); |
1039 | 1052 |
close(fd); |
1053 |
+ tcp_connections_no--; |
|
1040 | 1054 |
}else{ |
1041 | 1055 |
/* force timeout */ |
1042 | 1056 |
tcpconn->timeout=0; |
... | ... |
@@ -1175,7 +1189,7 @@ inline static int handle_tcp_child(struct tcp_child* tcp_c, int fd_i) |
1175 | 1189 |
break; |
1176 | 1190 |
} |
1177 | 1191 |
/* update the timeout*/ |
1178 |
- tcpconn->timeout=get_ticks()+TCP_CON_TIMEOUT; |
|
1192 |
+ tcpconn->timeout=get_ticks()+tcp_con_lifetime; |
|
1179 | 1193 |
tcpconn_put(tcpconn); |
1180 | 1194 |
/* must be after the de-ref*/ |
1181 | 1195 |
io_watch_add(&io_h, tcpconn->s, F_TCPCONN, tcpconn); |
... | ... |
@@ -1311,7 +1325,7 @@ inline static int handle_ser_child(struct process_table* p, int fd_i) |
1311 | 1325 |
/* add tcpconn to the list*/ |
1312 | 1326 |
tcpconn_add(tcpconn); |
1313 | 1327 |
/* update the timeout*/ |
1314 |
- tcpconn->timeout=get_ticks()+TCP_CON_TIMEOUT; |
|
1328 |
+ tcpconn->timeout=get_ticks()+tcp_con_lifetime; |
|
1315 | 1329 |
io_watch_add(&io_h, tcpconn->s, F_TCPCONN, tcpconn); |
1316 | 1330 |
break; |
1317 | 1331 |
default: |
... | ... |
@@ -1566,6 +1580,8 @@ void destroy_tcp() |
1566 | 1580 |
|
1567 | 1581 |
int init_tcp() |
1568 | 1582 |
{ |
1583 |
+ char* poll_err; |
|
1584 |
+ |
|
1569 | 1585 |
/* init lock */ |
1570 | 1586 |
tcpconn_lock=lock_alloc(); |
1571 | 1587 |
if (tcpconn_lock==0){ |
... | ... |
@@ -1604,6 +1620,25 @@ int init_tcp() |
1604 | 1620 |
memset((void*)tcpconn_id_hash, 0, |
1605 | 1621 |
TCP_ID_HASH_SIZE * sizeof(struct tcp_connection*)); |
1606 | 1622 |
|
1623 |
+ /* fix config variables */ |
|
1624 |
+ /* they can have only positive values due the config parser so we can |
|
1625 |
+ * ignore most of them */ |
|
1626 |
+ poll_err=check_poll_method(tcp_poll_method); |
|
1627 |
+ |
|
1628 |
+ /* set an appropiate poll method */ |
|
1629 |
+ if (poll_err || (tcp_poll_method==0)){ |
|
1630 |
+ tcp_poll_method=choose_poll_method(); |
|
1631 |
+ if (poll_err){ |
|
1632 |
+ LOG(L_ERR, "ERROR: init_tcp: %s, using %s instead\n", |
|
1633 |
+ poll_err, poll_method_name(tcp_poll_method)); |
|
1634 |
+ }else{ |
|
1635 |
+ LOG(L_INFO, "init_tcp: using %s as the io watch method" |
|
1636 |
+ " (auto detected)\n", poll_method_name(tcp_poll_method)); |
|
1637 |
+ } |
|
1638 |
+ }else{ |
|
1639 |
+ LOG(L_INFO, "init_tcp: using %s io watch method (config)\n", |
|
1640 |
+ poll_method_name(tcp_poll_method)); |
|
1641 |
+ } |
|
1607 | 1642 |
|
1608 | 1643 |
return 0; |
1609 | 1644 |
error: |
... | ... |
@@ -1621,7 +1656,20 @@ int tcp_init_children() |
1621 | 1656 |
int sockfd[2]; |
1622 | 1657 |
int reader_fd[2]; /* for comm. with the tcp children read */ |
1623 | 1658 |
pid_t pid; |
1659 |
+ struct socket_info *si; |
|
1660 |
+ |
|
1661 |
+ /* estimate max fd. no: |
|
1662 |
+ * 1 tcp send unix socket/all_proc, |
|
1663 |
+ * + 1 udp sock/udp proc + 1 tcp_child sock/tcp child* |
|
1664 |
+ * + no_listen_tcp */ |
|
1665 |
+ for(r=0, si=tcp_listen; si; si=si->next, r++); |
|
1666 |
+#ifdef USE_TLS |
|
1667 |
+ if (! tls_disable) |
|
1668 |
+ for (si=tls_listen; si; si=si->next; r++); |
|
1669 |
+#endif |
|
1624 | 1670 |
|
1671 |
+ tcp_max_fd_no=process_count()*2 +r-1 /* timer */ +3; /* stdin/out/err*/ |
|
1672 |
+ tcp_max_fd_no+=tcp_max_connections; |
|
1625 | 1673 |
|
1626 | 1674 |
/* create the tcp sock_info structures */ |
1627 | 1675 |
/* copy the sockets --moved to main_loop*/ |