summaryrefslogtreecommitdiff
path: root/util/netevent.c
diff options
context:
space:
mode:
Diffstat (limited to 'util/netevent.c')
-rw-r--r--util/netevent.c59
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) {