if (s->closing || nread <= 0 || comm_addr->sa_family == AF_UNSPEC)
return;
- if (s->outgoing) {
+ if (!the_network->enable_connect_udp && s->outgoing) {
const struct sockaddr *peer = session2_get_peer(s);
if (kr_fails_assert(peer->sa_family != AF_UNSPEC))
return;
int snd;
int rcv;
} listen_tcp_buflens;
+ _Bool enable_connect_udp;
};
struct args *the_args;
struct endpoint {
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;
+ the_network->enable_connect_udp = true;
// On Linux, unset means some auto-tuning mechanism also depending on RAM,
// which might be OK default (together with the user_timeout above)
struct {
int snd, rcv;
} listen_udp_buflens, listen_tcp_buflens;
+
+ /** Use uv_udp_connect as the transport method for UDP.
+ * Enabling this increases the total number of syscalls, with a variable
+ * impact on the time spent processing them, sometimes resulting in
+ * a slight improvement in syscall processing efficiency.
+ * Note: This does not necessarily lead to overall performance gains. */
+ bool enable_connect_udp;
};
/** Pointer to the singleton network state. NULL if not initialized. */
ctx);
return kr_ok();
} else {
- int ret = uv_udp_try_send((uv_udp_t*)handle,
- (uv_buf_t *)iov, iovcnt, comm->comm_addr);
+ int ret = uv_udp_try_send((uv_udp_t*)handle, (uv_buf_t *)iov, iovcnt,
+ the_network->enable_connect_udp ? NULL : comm->comm_addr);
if (ret > 0) // equals buffer size, only confuses us
ret = 0;
if (ret == UV_EAGAIN) {
struct comm_info out_comm = {
.comm_addr = (struct sockaddr *)choice
};
+
+ if (the_network->enable_connect_udp && session->outgoing && !session->stream) {
+ uv_udp_t *udp = (uv_udp_t *)session2_get_handle(session);
+ int connect_tries = 3;
+
+ do {
+ ret = uv_udp_connect(udp, out_comm.comm_addr);
+ } while (ret == UV_EADDRINUSE && --connect_tries > 0);
+ if (ret < 0)
+ kr_log_error(IO, "Failed to establish udp connection: %s\n", uv_strerror(ret));
+ }
ret = qr_task_send(task, session, &out_comm, task->pktbuf);
if (ret) {
session2_close(session);