summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Härdeman <david@hardeman.nu>2020-06-23 20:56:22 +0200
committerDavid Härdeman <david@hardeman.nu>2020-06-23 20:56:22 +0200
commitea053d96f7e89e053d4af8d39b04c5428760345f (patch)
tree8182ca73675ad3933b0f38cb48a99c69101309b4
parent8c27290245b7bcc7cd2f72f3b4a7562294b43bbe (diff)
Big renaming, move some more functionality to shared lib
-rw-r--r--mcserverctl/meson.build14
-rw-r--r--mcserverproxy/utils.h245
-rw-r--r--meson.build6
-rw-r--r--minecctl/meson.build14
-rw-r--r--minecctl/minecctl.c (renamed from mcserverctl/mcserverctl.c)0
-rw-r--r--minecproxy/announce.c (renamed from mcserverproxy/announce.c)0
-rw-r--r--minecproxy/announce.h (renamed from mcserverproxy/announce.h)0
-rw-r--r--minecproxy/config-parser.c (renamed from mcserverproxy/config-parser.c)2
-rw-r--r--minecproxy/config-parser.h (renamed from mcserverproxy/config-parser.h)0
-rw-r--r--minecproxy/idle.c (renamed from mcserverproxy/idle.c)0
-rw-r--r--minecproxy/idle.h (renamed from mcserverproxy/idle.h)0
-rw-r--r--minecproxy/igmp.c (renamed from mcserverproxy/igmp.c)0
-rw-r--r--minecproxy/igmp.h (renamed from mcserverproxy/igmp.h)0
-rw-r--r--minecproxy/main.c (renamed from mcserverproxy/main.c)3
-rw-r--r--minecproxy/main.h107
-rw-r--r--minecproxy/meson.build (renamed from mcserverproxy/meson.build)12
-rw-r--r--minecproxy/misc.c (renamed from mcserverproxy/utils.c)155
-rw-r--r--minecproxy/misc.h36
-rw-r--r--minecproxy/ptimer.c (renamed from mcserverproxy/ptimer.c)0
-rw-r--r--minecproxy/ptimer.h (renamed from mcserverproxy/ptimer.h)0
-rw-r--r--minecproxy/server-config.c (renamed from mcserverproxy/server-config.c)0
-rw-r--r--minecproxy/server-config.h (renamed from mcserverproxy/server-config.h)0
-rw-r--r--minecproxy/server-proxy.c (renamed from mcserverproxy/server-proxy.c)4
-rw-r--r--minecproxy/server-proxy.h (renamed from mcserverproxy/server-proxy.h)0
-rw-r--r--minecproxy/server-rcon.c (renamed from mcserverproxy/server-rcon.c)0
-rw-r--r--minecproxy/server-rcon.h (renamed from mcserverproxy/server-rcon.h)0
-rw-r--r--minecproxy/server.c (renamed from mcserverproxy/server.c)1
-rw-r--r--minecproxy/server.h (renamed from mcserverproxy/server.h)0
-rw-r--r--minecproxy/signal-handler.c (renamed from mcserverproxy/signal-handler.c)0
-rw-r--r--minecproxy/signal-handler.h (renamed from mcserverproxy/signal-handler.h)0
-rw-r--r--minecproxy/systemd.c (renamed from mcserverproxy/systemd.c)0
-rw-r--r--minecproxy/systemd.h (renamed from mcserverproxy/systemd.h)0
-rw-r--r--minecproxy/uring.c (renamed from mcserverproxy/uring.c)0
-rw-r--r--minecproxy/uring.h (renamed from mcserverproxy/uring.h)0
-rw-r--r--shared/debug.h (renamed from mcserverproxy/main.h)91
-rw-r--r--shared/list.h77
-rw-r--r--shared/meson.build1
-rw-r--r--shared/utils.c169
-rw-r--r--shared/utils.h106
39 files changed, 532 insertions, 511 deletions
diff --git a/mcserverctl/meson.build b/mcserverctl/meson.build
deleted file mode 100644
index 4e960b7..0000000
--- a/mcserverctl/meson.build
+++ /dev/null
@@ -1,14 +0,0 @@
-mcserverctl_sources = [
- 'mcserverctl.c',
-]
-
-mcserverctl_deps = [
- dep_libshared,
-]
-
-executable(
- 'mcserverctl',
- mcserverctl_sources,
- dependencies: mcserverctl_deps,
-)
-
diff --git a/mcserverproxy/utils.h b/mcserverproxy/utils.h
deleted file mode 100644
index c36a36c..0000000
--- a/mcserverproxy/utils.h
+++ /dev/null
@@ -1,245 +0,0 @@
-#ifndef fooutilshfoo
-#define fooutilshfoo
-
-#include <stdio.h>
-#include <string.h>
-#include <stdbool.h>
-#include <stdlib.h>
-#include <linux/if_packet.h>
-
-struct list_head {
- struct list_head *next;
- struct list_head *prev;
-};
-
-#define zmalloc(s) __zmalloc(__func__, __LINE__, s)
-void *__zmalloc(const char *fn, int line, size_t s);
-
-#define xstrdup(s) __xstrdup(__func__, __LINE__, s)
-char *__xstrdup(const char *fn, int line, const char *s);
-
-#define xstrndup(s, n) __xstrndup(__func__, __LINE__, s, n)
-char *__xstrndup(const char *fn, int line, const char *s, size_t n);
-
-#define xfree(s) __xfree(__func__, __LINE__, s)
-void __xfree(const char *fn, int line, void *ptr);
-
-void debug_resource_usage();
-
-/* Length of longest DNS name = 253 + trailing dot */
-#define FQDN_STR_LEN 254
-
-/* Length of longest port string = strlen("65535") */
-#define PORT_STR_LEN 5
-
-/* Length of longest address family string = strlen("AF_INETX") */
-#define AF_STR_LEN 8
-
-/* Length of longest addrstr, format = "AF_INETX <IPADDR> <PORT> */
-#define ADDRSTRLEN (AF_STR_LEN + 1 + INET6_ADDRSTRLEN + 1 + PORT_STR_LEN + 1)
-struct saddr {
- union {
- struct sockaddr_storage storage;
- struct sockaddr_in in4;
- struct sockaddr_in6 in6;
- struct sockaddr_ll ll;
- };
- socklen_t addrlen;
- char addrstr[ADDRSTRLEN];
- struct list_head list;
-};
-
-struct connection;
-
-typedef void(*connection_cb_t)(struct connection *, bool);
-
-struct connection {
- struct saddr remote;
- struct saddr local;
-
- struct list_head *addrs;
- unsigned next_addr;
-
- connection_cb_t cb;
-};
-
-struct uring_task;
-
-void socket_set_low_latency(int sfd);
-
-void connection_set_local(struct connection *conn, int fd);
-
-void connection_set_remote(struct connection *conn, struct saddr *remote);
-
-void connect_any(struct uring_task *task,
- struct list_head *addrs, struct connection *conn,
- connection_cb_t cb);
-
-char *saddr_addr(struct saddr *saddr, char *buf, size_t len);
-
-uint16_t saddr_port(struct saddr *saddr);
-
-void saddr_set_ipv4(struct saddr *saddr, in_addr_t ip, in_port_t port);
-
-void saddr_set_ipv6(struct saddr *saddr, const struct in6_addr *ip, in_port_t port);
-
-void saddr_set_addrstr(struct saddr *saddr);
-
-int strtou16_strict(const char *str, uint16_t *result);
-
-static inline bool empty_str(const char *str)
-{
- if (!str || str[0] == '\0')
- return true;
- else
- return false;
-}
-
-static inline bool streq(const char *a, const char *b)
-{
- return strcmp(a, b) == 0;
-}
-
-static inline bool strcaseeq(const char *a, const char *b)
-{
- return strcasecmp(a, b) == 0;
-}
-
-#if __BYTE_ORDER == __LITTLE_ENDIAN
-#define chtobe32(x) __bswap_constant_32(x)
-#else
-#define chtobe32(x) (x)
-#endif
-
-#if __BYTE_ORDER == __LITTLE_ENDIAN
-#define cinet_addr(a,b,c,d) ((uint32_t)((a)<<0|(b)<<8|(c)<<16|(d)<<24))
-#else
-#define cinet_addr(a,b,c,d) ((uint32_t)((a)<<24|(b)<<16|(c)<<8|(d)<<0))
-#endif
-
-#define LIST_HEAD_INIT(name) { &(name), &(name) }
-
-#define LIST_HEAD(name) struct list_head name = LIST_HEAD_INIT(name)
-
-static inline void list_init(struct list_head *list)
-{
- list->next = list;
- list->prev = list;
-}
-
-static inline void list_del(struct list_head *list)
-{
- list->next->prev = list->prev;
- list->prev->next = list->next;
-}
-
-static inline void list_add(struct list_head *new, struct list_head *list)
-{
- list->next->prev = new;
- new->next = list->next;
- new->prev = list;
- list->next = new;
-}
-
-static inline void list_replace(struct list_head *old, struct list_head *new)
-{
- old->prev->next = new;
- old->next->prev = new;
- new->next = old->next;
- new->prev = old->prev;
- old->next = old->prev = NULL;
-}
-
-static inline bool list_empty(struct list_head *list)
-{
- return list->next == list;
-}
-
-#define PIPE_RD 0
-#define PIPE_WR 1
-
-#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
-
-#define MAX(a, b) ((a) > (b) ? (a) : (b))
-
-#define DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d))
-
-#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
-
-#define container_of(ptr, type, member) ({ \
- const typeof( ((type *)0)->member ) *__mptr = (ptr); \
- (type *)( (char *)__mptr - offsetof(type,member) );})
-
-#define list_entry(ptr, type, member) \
- container_of(ptr, type, member)
-
-#define list_first_entry(ptr, type, member) \
- list_entry((ptr)->next, type, member)
-
-#define list_next_entry(pos, member) \
- list_entry((pos)->member.next, typeof(*(pos)), member)
-
-#define list_for_each(pos, head) \
- for (pos = (head)->next; pos != (head); pos = pos->next)
-
-#define list_for_each_entry(pos, head, member) \
- for (pos = list_first_entry(head, typeof(*pos), member); \
- &pos->member != (head); \
- pos = list_next_entry(pos, member))
-
-#define list_for_each_entry_safe(pos, n, head, member) \
- for (pos = list_entry((head)->next, typeof(*pos), member), \
- n = list_entry(pos->member.next, typeof(*pos), member); \
- &pos->member != (head); \
- pos = n, n = list_entry(n->member.next, typeof(*n), member))
-
-/*
-#define _cleanup_(x) __attribute__((cleanup(x)))
-
-#define DEFINE_TRIVIAL_CLEANUP_FUNC(type, func) \
- static inline void func##p(type *p) { \
- if (*p) \
- func(*p); \
- } \
- struct __useless_struct_to_allow_trailing_semicolon__
-
-static inline unsigned
-strv_length(char **strv)
-{
- unsigned len;
-
- for (len = 0; strv && *strv; strv++)
- len++;
-
- return len;
-}
-
-static inline void strv_free(char **l) {
- char **k;
- if (l) {
- for (k = l; *k; k++)
- free(k);
- free(l);
- }
-}
-DEFINE_TRIVIAL_CLEANUP_FUNC(char **, strv_free);
-#define _cleanup_strv_free_ _cleanup_(strv_freep)
-
-static inline void freep(void *p) {
- free(*(void**) p);
-}
-#define _cleanup_free_ _cleanup_(freep)
-
-DEFINE_TRIVIAL_CLEANUP_FUNC(int, close);
-#define _cleanup_close_ _cleanup_(closep)
-
-DEFINE_TRIVIAL_CLEANUP_FUNC(FILE *, fclose);
-#define _cleanup_fclose_ _cleanup_(fclosep)
-
-DEFINE_TRIVIAL_CLEANUP_FUNC(DIR *, closedir);
-#define _cleanup_closedir_ _cleanup_(closedirp)
-
-*/
-
-#endif
-
diff --git a/meson.build b/meson.build
index 1f8424a..cc9edc1 100644
--- a/meson.build
+++ b/meson.build
@@ -1,4 +1,4 @@
-project('mcproxy',
+project('minecproxy',
'c',
version: '0.1.0',
license: 'GPL2+',
@@ -29,6 +29,6 @@ dep_config_h = declare_dependency(
)
subdir('shared')
-subdir('mcserverproxy')
-subdir('mcserverctl')
+subdir('minecproxy')
+subdir('minecctl')
diff --git a/minecctl/meson.build b/minecctl/meson.build
new file mode 100644
index 0000000..3490338
--- /dev/null
+++ b/minecctl/meson.build
@@ -0,0 +1,14 @@
+minecctl_sources = [
+ 'minecctl.c',
+]
+
+minecctl_deps = [
+ dep_libshared,
+]
+
+executable(
+ 'minecctl',
+ minecctl_sources,
+ dependencies: minecctl_deps,
+)
+
diff --git a/mcserverctl/mcserverctl.c b/minecctl/minecctl.c
index e29dcef..e29dcef 100644
--- a/mcserverctl/mcserverctl.c
+++ b/minecctl/minecctl.c
diff --git a/mcserverproxy/announce.c b/minecproxy/announce.c
index 13ef423..13ef423 100644
--- a/mcserverproxy/announce.c
+++ b/minecproxy/announce.c
diff --git a/mcserverproxy/announce.h b/minecproxy/announce.h
index 77a36f2..77a36f2 100644
--- a/mcserverproxy/announce.h
+++ b/minecproxy/announce.h
diff --git a/mcserverproxy/config-parser.c b/minecproxy/config-parser.c
index ffed7f1..9c89cf2 100644
--- a/mcserverproxy/config-parser.c
+++ b/minecproxy/config-parser.c
@@ -8,7 +8,7 @@
#include <arpa/inet.h>
#include <inttypes.h>
-#include "main.h"
+#include "utils.h"
#include "config-parser.h"
static void
diff --git a/mcserverproxy/config-parser.h b/minecproxy/config-parser.h
index 3a117a3..3a117a3 100644
--- a/mcserverproxy/config-parser.h
+++ b/minecproxy/config-parser.h
diff --git a/mcserverproxy/idle.c b/minecproxy/idle.c
index c49846d..c49846d 100644
--- a/mcserverproxy/idle.c
+++ b/minecproxy/idle.c
diff --git a/mcserverproxy/idle.h b/minecproxy/idle.h
index d7e4ab0..d7e4ab0 100644
--- a/mcserverproxy/idle.h
+++ b/minecproxy/idle.h
diff --git a/mcserverproxy/igmp.c b/minecproxy/igmp.c
index dc43a9f..dc43a9f 100644
--- a/mcserverproxy/igmp.c
+++ b/minecproxy/igmp.c
diff --git a/mcserverproxy/igmp.h b/minecproxy/igmp.h
index 80875b0..80875b0 100644
--- a/mcserverproxy/igmp.h
+++ b/minecproxy/igmp.h
diff --git a/mcserverproxy/main.c b/minecproxy/main.c
index 047e70e..bbe3fad 100644
--- a/mcserverproxy/main.c
+++ b/minecproxy/main.c
@@ -33,7 +33,6 @@
/* Global */
struct cfg *cfg = NULL;
bool exiting = false;
-unsigned debug_mask = DBG_ERROR | DBG_INFO;
/* Local */
static bool daemonize = false;
@@ -655,6 +654,8 @@ main(int argc, char **argv)
unsigned server_count;
struct rlimit old_rlimit;
+ debug_mask = DBG_ERROR | DBG_INFO;
+
cfg_init(argc, argv);
cfg_apply();
diff --git a/minecproxy/main.h b/minecproxy/main.h
new file mode 100644
index 0000000..f1f5df2
--- /dev/null
+++ b/minecproxy/main.h
@@ -0,0 +1,107 @@
+#ifndef foomainhfoo
+#define foomainhfoo
+
+#include <sys/socket.h>
+#include <netinet/ip.h>
+
+struct cfg;
+struct uring_task;
+
+#include "misc.h"
+#include "utils.h"
+
+extern struct cfg *cfg;
+extern bool exiting;
+
+/*
+enum debug_lvl {
+ DBG_ERROR = (0x1 << 1),
+ DBG_INFO = (0x1 << 2),
+ DBG_VERBOSE = (0x1 << 3),
+ DBG_CFG = (0x1 << 4),
+ DBG_REF = (0x1 << 5),
+ DBG_MALLOC = (0x1 << 6),
+ DBG_ANN = (0x1 << 7),
+ DBG_SIG = (0x1 << 8),
+ DBG_UR = (0x1 << 9),
+ DBG_SRV = (0x1 << 10),
+ DBG_PROXY = (0x1 << 11),
+ DBG_RCON = (0x1 << 12),
+ DBG_IDLE = (0x1 << 13),
+ DBG_IGMP = (0x1 << 14),
+ DBG_SYSD = (0x1 << 15),
+ DBG_DNS = (0x1 << 16),
+ DBG_TIMER = (0x1 << 17),
+};
+*/
+
+void dump_tree();
+
+/* To save typing in all the function definitions below */
+typedef void (*utask_cb_t)(struct uring_task *, int res);
+typedef int (*rutask_cb_t)(struct uring_task *, int res);
+
+struct uring_task_buf {
+ char buf[4096];
+ size_t len;
+ size_t done;
+ struct iovec iov;
+ struct msghdr msg;
+};
+
+struct uring_task {
+ const char *name;
+ unsigned refcount;
+ int fd;
+ struct uring_task *parent;
+ void (*free)(struct uring_task *);
+ bool dead;
+ struct uring_task_buf *tbuf;
+
+ /* called once or repeatedly until is_complete_cb is satisfied */
+ utask_cb_t cb;
+
+ /* returns: 0 = not complete; < 0 = error; > 0 = complete */
+ rutask_cb_t is_complete_cb;
+
+ /* called once tbuf processing is done */
+ utask_cb_t final_cb;
+
+ /* used for recvmsg/sendmsg */
+ struct saddr saddr;
+ void *priv;
+};
+
+struct cfg {
+ /* Options */
+ uid_t uid;
+ gid_t gid;
+ const char *cfg_dir;
+ const char *cfg_file;
+ bool do_igmp;
+ 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;
+ struct announce *announce;
+ struct ptimer *ptimer;
+ struct igmp *igmp;
+ struct idle *idle;
+ struct sd_bus *sd_bus;
+ bool sd_bus_failed;
+ struct uring_task task;
+ struct list_head servers;
+};
+
+#endif
diff --git a/mcserverproxy/meson.build b/minecproxy/meson.build
index e5fa7bc..db6a31b 100644
--- a/mcserverproxy/meson.build
+++ b/minecproxy/meson.build
@@ -1,4 +1,4 @@
-mcproxy_sources = [
+minecproxy_sources = [
'main.c',
'uring.c',
'signal-handler.c',
@@ -12,14 +12,14 @@ mcproxy_sources = [
'ptimer.c',
'igmp.c',
'systemd.c',
- 'utils.c'
+ 'misc.c',
]
dep_liburing = dependency('liburing')
dep_libsystemd = dependency('libsystemd')
dep_libcapng = dependency('libcap-ng')
-mcproxy_deps = [
+minecproxy_deps = [
dep_liburing,
dep_libsystemd,
dep_libcapng,
@@ -28,9 +28,9 @@ mcproxy_deps = [
]
executable(
- 'mcproxy',
- mcproxy_sources,
+ 'minecproxy',
+ minecproxy_sources,
link_args: [ '-lanl' ],
- dependencies: mcproxy_deps,
+ dependencies: minecproxy_deps,
)
diff --git a/mcserverproxy/utils.c b/minecproxy/misc.c
index eacc586..f954618 100644
--- a/mcserverproxy/utils.c
+++ b/minecproxy/misc.c
@@ -14,7 +14,7 @@
#include <inttypes.h>
#include "main.h"
-#include "utils.h"
+#include "misc.h"
#include "uring.h"
static unsigned total_malloc_count = 0;
@@ -169,35 +169,6 @@ debug_resource_usage()
}
void
-socket_set_low_latency(int sfd)
-{
- int option;
-
- assert_return(sfd >= 0);
-
- /* 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 */
- 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 */
- if (cfg->socket_nodelay) {
- option = true;
- if (setsockopt(sfd, IPPROTO_TCP, TCP_NODELAY, &option, sizeof(option)) < 0)
- error("setsockopt: %m");
- }
-}
-
-void
connection_set_local(struct connection *conn, int fd)
{
assert_return(conn && fd >= 0);
@@ -283,7 +254,8 @@ again:
goto again;
}
- socket_set_low_latency(sfd);
+ socket_set_low_latency(sfd, cfg->socket_keepalive,
+ cfg->socket_iptos, cfg->socket_nodelay);
task->priv = conn;
uring_task_set_fd(task, sfd);
@@ -307,124 +279,3 @@ connect_any(struct uring_task *task,
connect_next(task, conn);
}
-uint16_t
-saddr_port(struct saddr *saddr)
-{
- assert_return(saddr, 0);
-
- switch (saddr->storage.ss_family) {
- case AF_INET:
- return ntohs(saddr->in4.sin_port);
- case AF_INET6:
- return ntohs(saddr->in6.sin6_port);
- default:
- return 0;
- }
-}
-
-char *
-saddr_addr(struct saddr *saddr, char *buf, size_t len)
-{
- assert_return(saddr && buf && len > 0, NULL);
-
- switch (saddr->storage.ss_family) {
- case AF_INET:
- if (inet_ntop(saddr->in4.sin_family, &saddr->in4.sin_addr, buf, len))
- return buf;
- break;
- case AF_INET6:
- if (inet_ntop(saddr->in6.sin6_family, &saddr->in6.sin6_addr, buf, len))
- return buf;
- break;
- default:
- break;
- }
-
- snprintf(buf, len, "<unknown>");
- return buf;
-}
-
-void
-saddr_set_ipv4(struct saddr *saddr, in_addr_t ip, in_port_t port)
-{
- assert_return(saddr);
-
- memset(&saddr->in4, 0, sizeof(saddr->in4));
- saddr->in4.sin_family = AF_INET;
- saddr->in4.sin_port = port;
- saddr->in4.sin_addr.s_addr = ip;
- saddr->addrlen = sizeof(saddr->in4);
- saddr_set_addrstr(saddr);
-}
-
-void
-saddr_set_ipv6(struct saddr *saddr, const struct in6_addr *ip, in_port_t port)
-{
- assert_return(saddr && ip);
-
- memset(&saddr->in6, 0, sizeof(saddr->in6));
- saddr->in6.sin6_family = AF_INET6;
- saddr->in6.sin6_port = port;
- if (ip)
- saddr->in6.sin6_addr = *ip;
- saddr->addrlen = sizeof(saddr->in6);
- saddr_set_addrstr(saddr);
-}
-
-void
-saddr_set_addrstr(struct saddr *saddr)
-{
- assert_return(saddr);
-
- char abuf[ADDRSTRLEN];
-
- switch (saddr->storage.ss_family) {
- case AF_INET:
- snprintf(saddr->addrstr, sizeof(saddr->addrstr),
- "AF_INET4 %s %" PRIu16,
- saddr_addr(saddr, abuf, sizeof(abuf)),
- saddr_port(saddr));
- break;
- case AF_INET6:
- snprintf(saddr->addrstr, sizeof(saddr->addrstr),
- "AF_INET6 %s %" PRIu16,
- saddr_addr(saddr, abuf, sizeof(abuf)),
- saddr_port(saddr));
- break;
- default:
- snprintf(saddr->addrstr, sizeof(saddr->addrstr), "AF_UNKNOWN");
- break;
- }
-}
-
-int
-strtou16_strict(const char *str, uint16_t *result)
-{
- char *end;
- long val;
-
- assert_return(!empty_str(str) && result, -EINVAL);
-
- errno = 0;
- val = strtol(str, &end, 10);
-
- if (errno == ERANGE && (val == LONG_MAX || val == LONG_MIN))
- return -EINVAL;
-
- if (errno != 0 && val == 0)
- return -EINVAL;
-
- if (end == str)
- return -EINVAL;
-
- if (*end != '\0')
- return -EINVAL;
-
- if (val < 1 || val > UINT16_MAX)
- return -EINVAL;
-
- if (result)
- *result = val;
- return 0;
-}
-
diff --git a/minecproxy/misc.h b/minecproxy/misc.h
new file mode 100644
index 0000000..6627913
--- /dev/null
+++ b/minecproxy/misc.h
@@ -0,0 +1,36 @@
+#ifndef foomischfoo
+#define foomischfoo
+
+#include <stdio.h>
+#include <string.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <linux/if_packet.h>
+
+#include "utils.h"
+
+void debug_resource_usage();
+
+struct connection;
+
+typedef void(*connection_cb_t)(struct connection *, bool);
+
+struct connection {
+ struct saddr remote;
+ struct saddr local;
+
+ struct list_head *addrs;
+ unsigned next_addr;
+
+ connection_cb_t cb;
+};
+
+void connection_set_local(struct connection *conn, int fd);
+
+void connection_set_remote(struct connection *conn, struct saddr *remote);
+
+void connect_any(struct uring_task *task,
+ struct list_head *addrs, struct connection *conn,
+ connection_cb_t cb);
+
+#endif
diff --git a/mcserverproxy/ptimer.c b/minecproxy/ptimer.c
index 5f9cf5d..5f9cf5d 100644
--- a/mcserverproxy/ptimer.c
+++ b/minecproxy/ptimer.c
diff --git a/mcserverproxy/ptimer.h b/minecproxy/ptimer.h
index 0b53590..0b53590 100644
--- a/mcserverproxy/ptimer.h
+++ b/minecproxy/ptimer.h
diff --git a/mcserverproxy/server-config.c b/minecproxy/server-config.c
index 549cf16..549cf16 100644
--- a/mcserverproxy/server-config.c
+++ b/minecproxy/server-config.c
diff --git a/mcserverproxy/server-config.h b/minecproxy/server-config.h
index 590dae0..590dae0 100644
--- a/mcserverproxy/server-config.h
+++ b/minecproxy/server-config.h
diff --git a/mcserverproxy/server-proxy.c b/minecproxy/server-proxy.c
index 4cbbb87..d8ff0cf 100644
--- a/mcserverproxy/server-proxy.c
+++ b/minecproxy/server-proxy.c
@@ -13,7 +13,6 @@
#include "ptimer.h"
#include "server.h"
#include "server-proxy.h"
-#include "utils.h"
static void
format_bytes(char *buf, size_t len, uint64_t val)
@@ -503,7 +502,8 @@ local_open(struct server_local *local)
error("setsockopt: %m");
}
- socket_set_low_latency(sfd);
+ socket_set_low_latency(sfd, cfg->socket_keepalive,
+ cfg->socket_iptos, cfg->socket_nodelay);
r = bind(sfd, (struct sockaddr *)&local->local.storage, local->local.addrlen);
if (r < 0) {
diff --git a/mcserverproxy/server-proxy.h b/minecproxy/server-proxy.h
index ee3bda3..ee3bda3 100644
--- a/mcserverproxy/server-proxy.h
+++ b/minecproxy/server-proxy.h
diff --git a/mcserverproxy/server-rcon.c b/minecproxy/server-rcon.c
index 1f8ef70..1f8ef70 100644
--- a/mcserverproxy/server-rcon.c
+++ b/minecproxy/server-rcon.c
diff --git a/mcserverproxy/server-rcon.h b/minecproxy/server-rcon.h
index 6625f25..6625f25 100644
--- a/mcserverproxy/server-rcon.h
+++ b/minecproxy/server-rcon.h
diff --git a/mcserverproxy/server.c b/minecproxy/server.c
index de42721..534ceca 100644
--- a/mcserverproxy/server.c
+++ b/minecproxy/server.c
@@ -17,7 +17,6 @@
#include "server.h"
#include "server-proxy.h"
#include "server-rcon.h"
-#include "utils.h"
#include "config-parser.h"
#include "idle.h"
#include "systemd.h"
diff --git a/mcserverproxy/server.h b/minecproxy/server.h
index ff4c28e..ff4c28e 100644
--- a/mcserverproxy/server.h
+++ b/minecproxy/server.h
diff --git a/mcserverproxy/signal-handler.c b/minecproxy/signal-handler.c
index 67c2e0b..67c2e0b 100644
--- a/mcserverproxy/signal-handler.c
+++ b/minecproxy/signal-handler.c
diff --git a/mcserverproxy/signal-handler.h b/minecproxy/signal-handler.h
index e0140b3..e0140b3 100644
--- a/mcserverproxy/signal-handler.h
+++ b/minecproxy/signal-handler.h
diff --git a/mcserverproxy/systemd.c b/minecproxy/systemd.c
index a44b0d8..a44b0d8 100644
--- a/mcserverproxy/systemd.c
+++ b/minecproxy/systemd.c
diff --git a/mcserverproxy/systemd.h b/minecproxy/systemd.h
index d455044..d455044 100644
--- a/mcserverproxy/systemd.h
+++ b/minecproxy/systemd.h
diff --git a/mcserverproxy/uring.c b/minecproxy/uring.c
index e979471..e979471 100644
--- a/mcserverproxy/uring.c
+++ b/minecproxy/uring.c
diff --git a/mcserverproxy/uring.h b/minecproxy/uring.h
index 9c33104..9c33104 100644
--- a/mcserverproxy/uring.h
+++ b/minecproxy/uring.h
diff --git a/mcserverproxy/main.h b/shared/debug.h
index 256ddae..8581a9a 100644
--- a/mcserverproxy/main.h
+++ b/shared/debug.h
@@ -1,16 +1,5 @@
-#ifndef foomainhfoo
-#define foomainhfoo
-
-#include <sys/socket.h>
-#include <netinet/ip.h>
-
-struct cfg;
-
-#include "utils.h"
-
-extern struct cfg *cfg;
-extern bool exiting;
-extern unsigned debug_mask;
+#ifndef foodebughfoo
+#define foodebughfoo
enum debug_lvl {
DBG_ERROR = (0x1 << 1),
@@ -38,8 +27,11 @@ debug_enabled(enum debug_lvl lvl)
return !!(lvl & debug_mask);
}
+/* These need to be defined in the linking binary */
void __debug(enum debug_lvl lvl, const char *fmt, ...) __attribute__((format(printf, 2, 3)));
+void __die(const char *fmt, ...) __attribute__((format(printf, 1, 2)));
+
#define __ifdebug(lvl, fmt, ...) \
do { \
if (debug_enabled((lvl))) \
@@ -55,8 +47,6 @@ void __debug(enum debug_lvl lvl, const char *fmt, ...) __attribute__((format(pri
__FILE__, __func__, __LINE__ \
__VA_OPT__(,) __VA_ARGS__)
-void __die(const char *fmt, ...) __attribute__((format(printf, 1, 2)));
-
#define die(fmt, ...) \
__die("%s:%s:%i: " fmt "\n", \
__FILE__, __func__, __LINE__ \
@@ -101,75 +91,4 @@ do { \
#define assert_task_alive(lvl, t) assert_task_alive_or((lvl), (t), return)
-void dump_tree();
-
-struct uring_task;
-
-/* To save typing in all the function definitions below */
-typedef void (*utask_cb_t)(struct uring_task *, int res);
-typedef int (*rutask_cb_t)(struct uring_task *, int res);
-
-struct uring_task_buf {
- char buf[4096];
- size_t len;
- size_t done;
- struct iovec iov;
- struct msghdr msg;
-};
-
-struct uring_task {
- const char *name;
- unsigned refcount;
- int fd;
- struct uring_task *parent;
- void (*free)(struct uring_task *);
- bool dead;
- struct uring_task_buf *tbuf;
-
- /* called once or repeatedly until is_complete_cb is satisfied */
- utask_cb_t cb;
-
- /* returns: 0 = not complete; < 0 = error; > 0 = complete */
- rutask_cb_t is_complete_cb;
-
- /* called once tbuf processing is done */
- utask_cb_t final_cb;
-
- /* used for recvmsg/sendmsg */
- struct saddr saddr;
- void *priv;
-};
-
-struct cfg {
- /* Options */
- uid_t uid;
- gid_t gid;
- const char *cfg_dir;
- const char *cfg_file;
- bool do_igmp;
- 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;
- struct announce *announce;
- struct ptimer *ptimer;
- struct igmp *igmp;
- struct idle *idle;
- struct sd_bus *sd_bus;
- bool sd_bus_failed;
- struct uring_task task;
- struct list_head servers;
-};
-
#endif
diff --git a/shared/list.h b/shared/list.h
new file mode 100644
index 0000000..df4092a
--- /dev/null
+++ b/shared/list.h
@@ -0,0 +1,77 @@
+#ifndef foolisthfoo
+#define foolisthfoo
+
+struct list_head {
+ struct list_head *next;
+ struct list_head *prev;
+};
+
+#define LIST_HEAD_INIT(name) { &(name), &(name) }
+
+#define LIST_HEAD(name) struct list_head name = LIST_HEAD_INIT(name)
+
+static inline void list_init(struct list_head *list)
+{
+ list->next = list;
+ list->prev = list;
+}
+
+static inline void list_del(struct list_head *list)
+{
+ list->next->prev = list->prev;
+ list->prev->next = list->next;
+}
+
+static inline void list_add(struct list_head *new, struct list_head *list)
+{
+ list->next->prev = new;
+ new->next = list->next;
+ new->prev = list;
+ list->next = new;
+}
+
+static inline void list_replace(struct list_head *old, struct list_head *new)
+{
+ old->prev->next = new;
+ old->next->prev = new;
+ new->next = old->next;
+ new->prev = old->prev;
+ old->next = old->prev = NULL;
+}
+
+static inline bool list_empty(struct list_head *list)
+{
+ return list->next == list;
+}
+
+#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
+
+#define container_of(ptr, type, member) ({ \
+ const typeof( ((type *)0)->member ) *__mptr = (ptr); \
+ (type *)( (char *)__mptr - offsetof(type,member) );})
+
+#define list_entry(ptr, type, member) \
+ container_of(ptr, type, member)
+
+#define list_first_entry(ptr, type, member) \
+ list_entry((ptr)->next, type, member)
+
+#define list_next_entry(pos, member) \
+ list_entry((pos)->member.next, typeof(*(pos)), member)
+
+#define list_for_each(pos, head) \
+ for (pos = (head)->next; pos != (head); pos = pos->next)
+
+#define list_for_each_entry(pos, head, member) \
+ for (pos = list_first_entry(head, typeof(*pos), member); \
+ &pos->member != (head); \
+ pos = list_next_entry(pos, member))
+
+#define list_for_each_entry_safe(pos, n, head, member) \
+ for (pos = list_entry((head)->next, typeof(*pos), member), \
+ n = list_entry(pos->member.next, typeof(*pos), member); \
+ &pos->member != (head); \
+ pos = n, n = list_entry(n->member.next, typeof(*n), member))
+
+#endif
+
diff --git a/shared/meson.build b/shared/meson.build
index cbb7dca..ccf502e 100644
--- a/shared/meson.build
+++ b/shared/meson.build
@@ -1,5 +1,6 @@
srcs_libshared = [
'rcon-protocol.c',
+ 'utils.c',
]
inc_libshared = include_directories('.')
diff --git a/shared/utils.c b/shared/utils.c
new file mode 100644
index 0000000..1284a73
--- /dev/null
+++ b/shared/utils.c
@@ -0,0 +1,169 @@
+#include <stdlib.h>
+#include <errno.h>
+#include <stdint.h>
+#include <limits.h>
+#include <arpa/inet.h>
+#include <string.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <netinet/ip.h>
+#include <netinet/tcp.h>
+#include <inttypes.h>
+
+#include "utils.h"
+
+unsigned debug_mask = 0;
+
+void
+socket_set_low_latency(int sfd, bool keepalive, bool iptos, bool nodelay)
+{
+ int option;
+
+ assert_return(sfd >= 0);
+
+ /* Probably not necessary, but can't hurt */
+ if (keepalive) {
+ 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 */
+ if (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 */
+ if (nodelay) {
+ option = true;
+ if (setsockopt(sfd, IPPROTO_TCP, TCP_NODELAY, &option, sizeof(option)) < 0)
+ error("setsockopt: %m");
+ }
+}
+
+uint16_t
+saddr_port(struct saddr *saddr)
+{
+ //assert_return(saddr, 0);
+
+ switch (saddr->storage.ss_family) {
+ case AF_INET:
+ return ntohs(saddr->in4.sin_port);
+ case AF_INET6:
+ return ntohs(saddr->in6.sin6_port);
+ default:
+ return 0;
+ }
+}
+
+char *
+saddr_addr(struct saddr *saddr, char *buf, size_t len)
+{
+ //assert_return(saddr && buf && len > 0, NULL);
+
+ switch (saddr->storage.ss_family) {
+ case AF_INET:
+ if (inet_ntop(saddr->in4.sin_family, &saddr->in4.sin_addr, buf, len))
+ return buf;
+ break;
+ case AF_INET6:
+ if (inet_ntop(saddr->in6.sin6_family, &saddr->in6.sin6_addr, buf, len))
+ return buf;
+ break;
+ default:
+ break;
+ }
+
+ snprintf(buf, len, "<unknown>");
+ return buf;
+}
+
+void
+saddr_set_ipv4(struct saddr *saddr, in_addr_t ip, in_port_t port)
+{
+ //assert_return(saddr);
+
+ memset(&saddr->in4, 0, sizeof(saddr->in4));
+ saddr->in4.sin_family = AF_INET;
+ saddr->in4.sin_port = port;
+ saddr->in4.sin_addr.s_addr = ip;
+ saddr->addrlen = sizeof(saddr->in4);
+ saddr_set_addrstr(saddr);
+}
+
+void
+saddr_set_ipv6(struct saddr *saddr, const struct in6_addr *ip, in_port_t port)
+{
+ //assert_return(saddr && ip);
+
+ memset(&saddr->in6, 0, sizeof(saddr->in6));
+ saddr->in6.sin6_family = AF_INET6;
+ saddr->in6.sin6_port = port;
+ if (ip)
+ saddr->in6.sin6_addr = *ip;
+ saddr->addrlen = sizeof(saddr->in6);
+ saddr_set_addrstr(saddr);
+}
+
+void
+saddr_set_addrstr(struct saddr *saddr)
+{
+ //assert_return(saddr);
+
+ char abuf[ADDRSTRLEN];
+
+ switch (saddr->storage.ss_family) {
+ case AF_INET:
+ snprintf(saddr->addrstr, sizeof(saddr->addrstr),
+ "AF_INET4 %s %" PRIu16,
+ saddr_addr(saddr, abuf, sizeof(abuf)),
+ saddr_port(saddr));
+ break;
+ case AF_INET6:
+ snprintf(saddr->addrstr, sizeof(saddr->addrstr),
+ "AF_INET6 %s %" PRIu16,
+ saddr_addr(saddr, abuf, sizeof(abuf)),
+ saddr_port(saddr));
+ break;
+ default:
+ snprintf(saddr->addrstr, sizeof(saddr->addrstr), "AF_UNKNOWN");
+ break;
+ }
+}
+
+int
+strtou16_strict(const char *str, uint16_t *result)
+{
+ char *end;
+ long val;
+
+ //assert_return(!empty_str(str) && result, -EINVAL);
+
+ errno = 0;
+ val = strtol(str, &end, 10);
+
+ if (errno == ERANGE && (val == LONG_MAX || val == LONG_MIN))
+ return -EINVAL;
+
+ if (errno != 0 && val == 0)
+ return -EINVAL;
+
+ if (end == str)
+ return -EINVAL;
+
+ if (*end != '\0')
+ return -EINVAL;
+
+ if (val < 1 || val > UINT16_MAX)
+ return -EINVAL;
+
+ if (result)
+ *result = val;
+ return 0;
+}
+
diff --git a/shared/utils.h b/shared/utils.h
new file mode 100644
index 0000000..df728b2
--- /dev/null
+++ b/shared/utils.h
@@ -0,0 +1,106 @@
+#ifndef fooutilshfoo
+#define fooutilshfoo
+
+#include <stdio.h>
+#include <string.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <linux/if_packet.h>
+
+extern unsigned debug_mask;
+
+#include "list.h"
+#include "debug.h"
+
+/* These functions need to be defined in the linking binary */
+#define zmalloc(s) __zmalloc(__func__, __LINE__, s)
+void *__zmalloc(const char *fn, int line, size_t s);
+
+#define xstrdup(s) __xstrdup(__func__, __LINE__, s)
+char *__xstrdup(const char *fn, int line, const char *s);
+
+#define xstrndup(s, n) __xstrndup(__func__, __LINE__, s, n)
+char *__xstrndup(const char *fn, int line, const char *s, size_t n);
+
+#define xfree(s) __xfree(__func__, __LINE__, s)
+void __xfree(const char *fn, int line, void *ptr);
+
+/* Length of longest DNS name = 253 + trailing dot */
+#define FQDN_STR_LEN 254
+
+/* Length of longest port string = strlen("65535") */
+#define PORT_STR_LEN 5
+
+/* Length of longest address family string = strlen("AF_INETX") */
+#define AF_STR_LEN 8
+
+/* Length of longest addrstr, format = "AF_INETX <IPADDR> <PORT> */
+#define ADDRSTRLEN (AF_STR_LEN + 1 + INET6_ADDRSTRLEN + 1 + PORT_STR_LEN + 1)
+
+struct saddr {
+ union {
+ struct sockaddr_storage storage;
+ struct sockaddr_in in4;
+ struct sockaddr_in6 in6;
+ struct sockaddr_ll ll;
+ };
+ socklen_t addrlen;
+ char addrstr[ADDRSTRLEN];
+ struct list_head list;
+};
+
+void socket_set_low_latency(int sfd, bool keepalive, bool iptos, bool nodelay);
+
+char *saddr_addr(struct saddr *saddr, char *buf, size_t len);
+
+uint16_t saddr_port(struct saddr *saddr);
+
+void saddr_set_ipv4(struct saddr *saddr, in_addr_t ip, in_port_t port);
+
+void saddr_set_ipv6(struct saddr *saddr, const struct in6_addr *ip, in_port_t port);
+
+void saddr_set_addrstr(struct saddr *saddr);
+
+int strtou16_strict(const char *str, uint16_t *result);
+
+static inline bool empty_str(const char *str)
+{
+ if (!str || str[0] == '\0')
+ return true;
+ else
+ return false;
+}
+
+static inline bool streq(const char *a, const char *b)
+{
+ return strcmp(a, b) == 0;
+}
+
+static inline bool strcaseeq(const char *a, const char *b)
+{
+ return strcasecmp(a, b) == 0;
+}
+
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+#define chtobe32(x) __bswap_constant_32(x)
+#else
+#define chtobe32(x) (x)
+#endif
+
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+#define cinet_addr(a,b,c,d) ((uint32_t)((a)<<0|(b)<<8|(c)<<16|(d)<<24))
+#else
+#define cinet_addr(a,b,c,d) ((uint32_t)((a)<<24|(b)<<16|(c)<<8|(d)<<0))
+#endif
+
+#define PIPE_RD 0
+#define PIPE_WR 1
+
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+
+#define MAX(a, b) ((a) > (b) ? (a) : (b))
+
+#define DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d))
+
+#endif
+