diff options
-rw-r--r-- | main.c | 87 | ||||
-rw-r--r-- | main.h | 11 | ||||
-rw-r--r-- | server-proxy.c | 34 | ||||
-rw-r--r-- | utils.c | 26 |
4 files changed, 131 insertions, 27 deletions
@@ -32,6 +32,14 @@ #define DEFAULT_HOMEDIR_PATH "/home/david/intest" #define DEFAULT_MAIN_CONFIG_FILE_PATH "./mcproxy.conf" #define DEFAULT_ANNOUNCE_INTERVAL 3 +#define DEFAULT_PROXY_CONN_INTERVAL 3 +#define DEFAULT_PROXY_CONN_ATTEMPTS 20 +#define DEFAULT_SOCKET_DEFER true +#define DEFAULT_SOCKET_FREEBIND true +#define DEFAULT_SOCKET_KEEPALIVE true +#define DEFAULT_SOCKET_IPTOS true +#define DEFAULT_SOCKET_NODELAY true + /* Global */ struct cfg *cfg = NULL; @@ -199,6 +207,13 @@ enum mcfg_keys { MCFG_KEY_IGMP, MCFG_KEY_IGMP_IFACE, MCFG_KEY_ANN_INTERVAL, + MCFG_KEY_PROXY_CONN_INTERVAL, + MCFG_KEY_PROXY_CONN_ATTEMPTS, + MCFG_KEY_SOCKET_DEFER, + MCFG_KEY_SOCKET_FREEBIND, + MCFG_KEY_SOCKET_KEEPALIVE, + MCFG_KEY_SOCKET_IPTOS, + MCFG_KEY_SOCKET_NODELAY, }; struct cfg_key_value_map mcfg_key_map[] = { @@ -215,6 +230,34 @@ struct cfg_key_value_map mcfg_key_map[] = { .key_value = MCFG_KEY_ANN_INTERVAL, .value_type = CFG_VAL_TYPE_UINT16, }, { + .key_name = "proxy_connection_interval", + .key_value = MCFG_KEY_PROXY_CONN_INTERVAL, + .value_type = CFG_VAL_TYPE_UINT16, + }, { + .key_name = "proxy_connection_attempts", + .key_value = MCFG_KEY_PROXY_CONN_ATTEMPTS, + .value_type = CFG_VAL_TYPE_UINT16, + }, { + .key_name = "socket_defer", + .key_value = MCFG_KEY_SOCKET_DEFER, + .value_type = CFG_VAL_TYPE_BOOL, + }, { + .key_name = "socket_freebind", + .key_value = MCFG_KEY_SOCKET_FREEBIND, + .value_type = CFG_VAL_TYPE_BOOL, + }, { + .key_name = "socket_keepalive", + .key_value = MCFG_KEY_SOCKET_KEEPALIVE, + .value_type = CFG_VAL_TYPE_BOOL, + }, { + .key_name = "socket_iptos", + .key_value = MCFG_KEY_SOCKET_IPTOS, + .value_type = CFG_VAL_TYPE_BOOL, + }, { + .key_name = "socket_nodelay", + .key_value = MCFG_KEY_SOCKET_NODELAY, + .value_type = CFG_VAL_TYPE_BOOL, + }, { .key_name = NULL, .key_value = MCFG_KEY_INVALID, .value_type = CFG_VAL_TYPE_INVALID, @@ -303,6 +346,34 @@ cfg_read() cfg->announce_interval = value.uint16; break; + case MCFG_KEY_PROXY_CONN_INTERVAL: + cfg->proxy_connection_interval = value.uint16; + break; + + case MCFG_KEY_PROXY_CONN_ATTEMPTS: + cfg->proxy_connection_attempts = value.uint16; + break; + + case MCFG_KEY_SOCKET_DEFER: + cfg->socket_defer = value.boolean; + break; + + case MCFG_KEY_SOCKET_FREEBIND: + cfg->socket_freebind = value.boolean; + break; + + case MCFG_KEY_SOCKET_KEEPALIVE: + cfg->socket_keepalive = value.boolean; + break; + + case MCFG_KEY_SOCKET_IPTOS: + cfg->socket_iptos = value.boolean; + break; + + case MCFG_KEY_SOCKET_NODELAY: + cfg->socket_nodelay = value.boolean; + break; + case MCFG_KEY_INVALID: default: die("main config file (%s) invalid", path); @@ -397,11 +468,20 @@ cfg_init(int argc, char **argv) if (!cfg) die("malloc: %m"); + uring_task_init(&cfg->task, "main", NULL, cfg_free); + list_init(&cfg->servers); + + cfg->homedir = DEFAULT_HOMEDIR_PATH; cfg->announce_interval = DEFAULT_ANNOUNCE_INTERVAL; + cfg->proxy_connection_interval = DEFAULT_PROXY_CONN_INTERVAL; + cfg->proxy_connection_attempts = DEFAULT_PROXY_CONN_ATTEMPTS; + cfg->socket_defer = DEFAULT_SOCKET_DEFER; + cfg->socket_freebind = DEFAULT_SOCKET_FREEBIND; + cfg->socket_keepalive = DEFAULT_SOCKET_KEEPALIVE; + cfg->socket_iptos = DEFAULT_SOCKET_IPTOS; + cfg->socket_nodelay = DEFAULT_SOCKET_NODELAY; cfg->uid = geteuid(); cfg->gid = getegid(); - uring_task_init(&cfg->task, "main", NULL, cfg_free); - list_init(&cfg->servers); while (true) { int option_index = 0; @@ -495,9 +575,6 @@ cfg_init(int argc, char **argv) if (optind < argc) usage(argc, argv, true); - - if (!cfg->homedir) - cfg->homedir = DEFAULT_HOMEDIR_PATH; } static void @@ -141,6 +141,7 @@ struct uring_task { }; struct cfg { + /* Options */ uid_t uid; gid_t gid; const char *homedir; @@ -149,7 +150,15 @@ struct cfg { char *igmp_iface; bool splice_supported; uint16_t announce_interval; - + uint16_t proxy_connection_interval; + uint16_t proxy_connection_attempts; + bool socket_defer; + bool socket_freebind; + bool socket_keepalive; + bool socket_iptos; + bool socket_nodelay; + + /* Bookkeeping */ struct uring_ev *uring; struct server_cfg_monitor *server_cfg_monitor; struct signal_ev *signal; diff --git a/server-proxy.c b/server-proxy.c index f897aa2..4cbbb87 100644 --- a/server-proxy.c +++ b/server-proxy.c @@ -402,9 +402,15 @@ proxy_new(struct server *server, struct saddr *client, int fd) list_add(&proxy->list, &server->proxys); if (server->state != SERVER_STATE_RUNNING) { - server_start(server); - ptask_init(&proxy->ptask, 3, 20, proxy_connect_timer_cb); - ptimer_add_task(&proxy->ptask); + if (server_start(server) && + cfg->proxy_connection_interval > 0 && + cfg->proxy_connection_attempts > 0) { + ptask_init(&proxy->ptask, + cfg->proxy_connection_interval, + cfg->proxy_connection_attempts, + proxy_connect_timer_cb); + ptimer_add_task(&proxy->ptask); + } } proxy->connecting = true; @@ -481,15 +487,21 @@ local_open(struct server_local *local) } /* 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) - error("setsockopt: %m"); + if (cfg->socket_defer) { + option = true; + if (setsockopt(sfd, IPPROTO_TCP, TCP_DEFER_ACCEPT, &option, sizeof(option)) < 0) + error("setsockopt: %m"); + } - /* FIXME: could make this configurable */ - option = true; - if (setsockopt(sfd, IPPROTO_IP, IP_FREEBIND, &option, sizeof(option)) < 0) - error("setsockopt: %m"); + /* + * This has the advantage that interfaces don't need to be up but + * it means that cfg errors will not be caught. + */ + if (cfg->socket_freebind) { + option = true; + if (setsockopt(sfd, IPPROTO_IP, IP_FREEBIND, &option, sizeof(option)) < 0) + error("setsockopt: %m"); + } socket_set_low_latency(sfd); @@ -175,20 +175,26 @@ socket_set_low_latency(int sfd) assert_return(sfd >= 0); - /* FIXME: could make this configurable */ - option = true; - if (setsockopt(sfd, SOL_SOCKET, SO_KEEPALIVE, &option, sizeof(option)) < 0) - error("setsockopt: %m"); + /* Probably not necessary, but can't hurt */ + if (cfg->socket_defer) { + option = true; + if (setsockopt(sfd, SOL_SOCKET, SO_KEEPALIVE, &option, sizeof(option)) < 0) + error("setsockopt: %m"); + } /* Doubtful if it has much effect, but can't hurt */ - option = IPTOS_LOWDELAY; - if (setsockopt(sfd, IPPROTO_IP, IP_TOS, &option, sizeof(option)) < 0) - error("setsockopt: %m"); + if (cfg->socket_iptos) { + option = IPTOS_LOWDELAY; + if (setsockopt(sfd, IPPROTO_IP, IP_TOS, &option, sizeof(option)) < 0) + error("setsockopt: %m"); + } /* Nagle's algorithm is a poor fit for gaming */ - option = true; - if (setsockopt(sfd, IPPROTO_TCP, TCP_NODELAY, &option, sizeof(option)) < 0) - error("setsockopt: %m"); + if (cfg->socket_nodelay) { + option = true; + if (setsockopt(sfd, IPPROTO_TCP, TCP_NODELAY, &option, sizeof(option)) < 0) + error("setsockopt: %m"); + } } void |