From ca46c321915798818d6716fb5c2be9f538f2e722 Mon Sep 17 00:00:00 2001 From: David Härdeman Date: Thu, 11 Jun 2020 12:29:43 +0200 Subject: Add some socket options to minecraft protocol sockets --- idle.c | 2 ++ main.h | 5 +++-- proxy.c | 2 ++ rcon.c | 2 ++ server.c | 21 +++++++++++++++++++-- utils.c | 27 +++++++++++++++++++++++++++ utils.h | 2 ++ 7 files changed, 57 insertions(+), 4 deletions(-) diff --git a/idle.c b/idle.c index 3fddf79..8f2530a 100644 --- a/idle.c +++ b/idle.c @@ -361,6 +361,8 @@ again: goto again; } + socket_set_gaming_options(cfg, sfd); + uring_task_set_fd(&idle->idlecheck, sfd); uring_connect(cfg, &idle->idlecheck, &idle->remote, idle_check_remote_connected); } diff --git a/main.h b/main.h index d0cb41b..578c8d7 100644 --- a/main.h +++ b/main.h @@ -3,6 +3,9 @@ #include #include + +struct cfg; + #include "utils.h" extern bool exiting; @@ -18,8 +21,6 @@ void die(const char *fmt, ...); #define perrordie(msg) die("%s: %m\n", msg) -struct cfg; - struct uring_task; /* To save typing in all the function definitions below */ diff --git a/proxy.c b/proxy.c index 9fda0c5..6b724f2 100644 --- a/proxy.c +++ b/proxy.c @@ -236,6 +236,8 @@ again: goto again; } + socket_set_gaming_options(cfg, sfd); + proxy->sfd = sfd; uring_task_set_fd(&proxy->servertask, sfd); uring_connect(cfg, &proxy->servertask, &proxy->server, proxy_server_connected); diff --git a/rcon.c b/rcon.c index a1fd90f..4229527 100644 --- a/rcon.c +++ b/rcon.c @@ -372,6 +372,8 @@ again: goto again; } + socket_set_gaming_options(cfg, sfd); + uring_task_set_fd(&rcon->task, sfd); uring_connect(cfg, &rcon->task, &rcon->rcon, rcon_connected); } diff --git a/server.c b/server.c index 0298491..3cc2398 100644 --- a/server.c +++ b/server.c @@ -10,6 +10,9 @@ #include #include #include +#include +#include +#include #include "main.h" #include "uring.h" @@ -212,7 +215,7 @@ static bool server_local_open(struct cfg *cfg, struct server *scfg, struct server_local *local) { int sfd; - int enable = 1; + int option; int r; sfd = socket(local->addr.storage.ss_family, SOCK_STREAM | SOCK_CLOEXEC, 0); @@ -221,11 +224,25 @@ server_local_open(struct cfg *cfg, struct server *scfg, struct server_local *loc goto out; } - if (setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(enable)) < 0) { + option = true; + if (setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &option, sizeof(option)) < 0) { perror("setsockopt"); goto out; } + /* The MC protocol expects the client to send data first */ + /* FIXME: could make this configurable */ + option = true; + if (setsockopt(sfd, IPPROTO_TCP, TCP_DEFER_ACCEPT, &option, sizeof(option)) < 0) + perror("setsockopt"); + + /* FIXME: could make this configurable */ + option = true; + if (setsockopt(sfd, IPPROTO_IP, IP_FREEBIND, &option, sizeof(option)) < 0) + perror("setsockopt"); + + socket_set_gaming_options(cfg, sfd); + r = bind(sfd, (struct sockaddr *)&local->addr.storage, local->addr.addrlen); if (r < 0) { perror("bind"); diff --git a/utils.c b/utils.c index 39f91f1..93bc0b8 100644 --- a/utils.c +++ b/utils.c @@ -8,6 +8,9 @@ #include #include #include +#include +#include +#include #include "main.h" #include "utils.h" @@ -155,6 +158,30 @@ debug_resource_usage() } } +void +socket_set_gaming_options(struct cfg *cfg, int sfd) +{ + int option; + + if (sfd <= 0) + return; + + /* FIXME: could make this configurable */ + option = true; + if (setsockopt(sfd, SOL_SOCKET, SO_KEEPALIVE, &option, sizeof(option)) < 0) + perror("setsockopt"); + + /* Doubtful if it has much effect, but can't hurt */ + option = IPTOS_LOWDELAY; + if (setsockopt(sfd, IPPROTO_IP, IP_TOS, &option, sizeof(option)) < 0) + perror("setsockopt"); + + /* Nagle's algorithm is a poor fit for gaming */ + option = true; + if (setsockopt(sfd, IPPROTO_TCP, TCP_NODELAY, &option, sizeof(option)) < 0) + perror("setsockopt"); +} + uint16_t sockaddr_port(struct sockaddr_in46 *addr) { switch (addr->storage.ss_family) { diff --git a/utils.h b/utils.h index 52a1078..8f8a153 100644 --- a/utils.h +++ b/utils.h @@ -104,6 +104,8 @@ struct sockaddr_in46 { struct list_head list; }; +void socket_set_gaming_options(struct cfg *cfg, int sfd); + uint16_t sockaddr_port(struct sockaddr_in46 *addr); char *sockaddr_to_str(struct sockaddr_in46 *addr, char *buf, size_t buflen); -- cgit v1.2.3