return fd;
}
+/// Optionally set a socket option and log error on failure.
+static void set_so(int fd, int so_option, int value, const char *descr)
+{
+ if (!value) return;
+ if (setsockopt(fd, SOL_SOCKET, so_option, &value, sizeof(value))) {
+ kr_log_error(IO, "failed to set %s to %d: %s\n",
+ descr, value, strerror(errno));
+ // we treat this as non-critical failure
+ }
+}
+
int io_listen_udp(uv_loop_t *loop, uv_udp_t *handle, int fd)
{
if (!handle) {
ret = uv_udp_open(handle, fd);
if (ret) return ret;
+ set_so(fd, SO_SNDBUF, the_network->listen_udp_buflens.snd, "UDP send buffer size");
+ set_so(fd, SO_RCVBUF, the_network->listen_udp_buflens.rcv, "UDP receive buffer size");
+
uv_handle_t *h = (uv_handle_t *)handle;
check_bufsize(h);
/* Handle is already created, just create context. */
}
#endif
+ /* These get inherited into the individual connections (on Linux at least). */
+ set_so(fd, SO_SNDBUF, the_network->listen_tcp_buflens.snd, "TCP send buffer size");
+ set_so(fd, SO_RCVBUF, the_network->listen_tcp_buflens.rcv, "TCP receive buffer size");
+#ifdef TCP_USER_TIMEOUT
+ val = the_network->tcp.user_timeout;
+ if (val && setsockopt(fd, IPPROTO_TCP, TCP_USER_TIMEOUT, &val, sizeof(val))) {
+ kr_log_error(IO, "listen TCP (user_timeout): %s\n", strerror(errno));
+ }
+ // TODO: also for upstream connections, at least this one option?
+#endif
+
handle->data = NULL;
return 0;
}
tls_session_ticket_ctx_create(loop, NULL, 0);
the_network->tcp.in_idle_timeout = 10000;
the_network->tcp.tls_handshake_timeout = TLS_MAX_HANDSHAKE_TIME;
+ the_network->tcp.user_timeout = 1000; // 1s should be more than enough
the_network->tcp_backlog = tcp_backlog;
+
+ // On Linux, unset means some auto-tuning mechanism also depending on RAM,
+ // which might be OK default (together with the user_timeout above)
+ //the_network->listen_{tcp,udp}_buflens.{snd,rcv}
}
/** Notify the registered function about endpoint getting open.
struct net_tcp_param {
uint64_t in_idle_timeout;
uint64_t tls_handshake_timeout;
+
+ /** Milliseconds of unacknowledged data; see TCP_USER_TIMEOUT in man tcp.7
+ * Linux only, probably. */
+ unsigned int user_timeout;
};
/** Information about an address that is allowed to use PROXYv2. */
struct tls_session_ticket_ctx *tls_session_ticket_ctx;
struct net_tcp_param tcp;
int tcp_backlog;
+
+ /** Kernel-side buffer sizes for sending and receiving. (in bytes)
+ * They are per socket, so in the TCP case they are per connection.
+ * See SO_SNDBUF and SO_RCVBUF in man socket.7 These are in POSIX. */
+ struct {
+ int snd, rcv;
+ } listen_udp_buflens, listen_tcp_buflens;
};
/** Pointer to the singleton network state. NULL if not initialized. */