diff options
Diffstat (limited to 'util/netevent.c')
-rw-r--r-- | util/netevent.c | 59 |
1 files changed, 51 insertions, 8 deletions
diff --git a/util/netevent.c b/util/netevent.c index 5cc8606fad3e..373538041420 100644 --- a/util/netevent.c +++ b/util/netevent.c @@ -43,6 +43,7 @@ #include "util/ub_event.h" #include "util/log.h" #include "util/net_help.h" +#include "util/tcp_conn_limit.h" #include "util/fptr_wlist.h" #include "sldns/pkthdr.h" #include "sldns/sbuffer.h" @@ -82,10 +83,11 @@ # endif #endif -/** The TCP reading or writing query timeout in milliseconds */ +/** The TCP writing query timeout in milliseconds */ #define TCP_QUERY_TIMEOUT 120000 -/** The TCP timeout in msec for fast queries, above half are used */ -#define TCP_QUERY_TIMEOUT_FAST 200 +/** The minimum actual TCP timeout to use, regardless of what we advertise, + * in msec */ +#define TCP_QUERY_TIMEOUT_MINIMUM 200 #ifndef NONBLOCKING_IS_BROKEN /** number of UDP reads to perform per read indication from select */ @@ -728,6 +730,7 @@ comm_point_udp_callback(int fd, short event, void* arg) static void setup_tcp_handler(struct comm_point* c, int fd, int cur, int max) { + int handler_usage; log_assert(c->type == comm_tcp); log_assert(c->fd == -1); sldns_buffer_clear(c->buffer); @@ -737,13 +740,29 @@ setup_tcp_handler(struct comm_point* c, int fd, int cur, int max) #endif c->tcp_is_reading = 1; c->tcp_byte_count = 0; - c->tcp_timeout_msec = TCP_QUERY_TIMEOUT; /* if more than half the tcp handlers are in use, use a shorter * timeout for this TCP connection, we need to make space for * other connections to be able to get attention */ - if(cur > max/2) - c->tcp_timeout_msec = TCP_QUERY_TIMEOUT_FAST; - comm_point_start_listening(c, fd, c->tcp_timeout_msec); + /* If > 50% TCP handler structures in use, set timeout to 1/100th + * configured value. + * If > 65%TCP handler structures in use, set to 1/500th configured + * value. + * If > 80% TCP handler structures in use, set to 0. + * + * If the timeout to use falls below 200 milliseconds, an actual + * timeout of 200ms is used. + */ + handler_usage = (cur * 100) / max; + if(handler_usage > 50 && handler_usage <= 65) + c->tcp_timeout_msec /= 100; + else if (handler_usage > 65 && handler_usage <= 80) + c->tcp_timeout_msec /= 500; + else if (handler_usage > 80) + c->tcp_timeout_msec = 0; + comm_point_start_listening(c, fd, + c->tcp_timeout_msec < TCP_QUERY_TIMEOUT_MINIMUM + ? TCP_QUERY_TIMEOUT_MINIMUM + : c->tcp_timeout_msec); } void comm_base_handle_slow_accept(int ATTR_UNUSED(fd), @@ -832,6 +851,16 @@ int comm_point_perform_accept(struct comm_point* c, #endif return -1; } + if(c->tcp_conn_limit && c->type == comm_tcp_accept) { + c->tcl_addr = tcl_addr_lookup(c->tcp_conn_limit, addr, *addrlen); + if(!tcl_new_connection(c->tcl_addr)) { + if(verbosity >= 3) + log_err_addr("accept rejected", + "connection limit exceeded", addr, *addrlen); + close(new_fd); + return -1; + } + } #ifndef HAVE_ACCEPT4 fd_set_nonblock(new_fd); #endif @@ -2525,6 +2554,10 @@ comm_point_create_tcp_handler(struct comm_base *base, c->tcp_is_reading = 0; c->tcp_byte_count = 0; c->tcp_parent = parent; + c->tcp_timeout_msec = parent->tcp_timeout_msec; + c->tcp_conn_limit = parent->tcp_conn_limit; + c->tcl_addr = NULL; + c->tcp_keepalive = 0; c->max_tcp_count = 0; c->cur_tcp_count = 0; c->tcp_handlers = NULL; @@ -2565,7 +2598,8 @@ comm_point_create_tcp_handler(struct comm_base *base, } struct comm_point* -comm_point_create_tcp(struct comm_base *base, int fd, int num, size_t bufsize, +comm_point_create_tcp(struct comm_base *base, int fd, int num, + int idle_timeout, struct tcl_list* tcp_conn_limit, size_t bufsize, comm_point_callback_type* callback, void* callback_arg) { struct comm_point* c = (struct comm_point*)calloc(1, @@ -2587,6 +2621,10 @@ comm_point_create_tcp(struct comm_base *base, int fd, int num, size_t bufsize, c->timeout = NULL; c->tcp_is_reading = 0; c->tcp_byte_count = 0; + c->tcp_timeout_msec = idle_timeout; + c->tcp_conn_limit = tcp_conn_limit; + c->tcl_addr = NULL; + c->tcp_keepalive = 0; c->tcp_parent = NULL; c->max_tcp_count = num; c->cur_tcp_count = 0; @@ -2665,6 +2703,10 @@ comm_point_create_tcp_out(struct comm_base *base, size_t bufsize, c->timeout = NULL; c->tcp_is_reading = 0; c->tcp_byte_count = 0; + c->tcp_timeout_msec = TCP_QUERY_TIMEOUT; + c->tcp_conn_limit = NULL; + c->tcl_addr = NULL; + c->tcp_keepalive = 0; c->tcp_parent = NULL; c->max_tcp_count = 0; c->cur_tcp_count = 0; @@ -2906,6 +2948,7 @@ comm_point_close(struct comm_point* c) log_err("could not event_del on close"); } } + tcl_close_connection(c->tcl_addr); /* close fd after removing from event lists, or epoll.. is messed up */ if(c->fd != -1 && !c->do_not_close) { if(c->type == comm_tcp || c->type == comm_http) { |