From 77071eb45391c9f0bbc593bcf2c10605ed1d5d17 Mon Sep 17 00:00:00 2001 From: David Härdeman Date: Mon, 22 Jun 2020 12:00:05 +0200 Subject: Rename proxy and cfgdir to more descriptive names --- cfgdir.c | 576 --------------------------------------------------------------- 1 file changed, 576 deletions(-) delete mode 100644 cfgdir.c (limited to 'cfgdir.c') diff --git a/cfgdir.c b/cfgdir.c deleted file mode 100644 index ec8a0bf..0000000 --- a/cfgdir.c +++ /dev/null @@ -1,576 +0,0 @@ -#define _GNU_SOURCE -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "main.h" -#include "uring.h" -#include "cfgdir.h" -#include "config.h" -#include "server.h" - -static void -scfg_dns_cb(struct dns_async *dns, bool (*server_cb)(struct server *, struct saddr *)) -{ - struct server *server; - struct sockaddr_in *in4; - struct sockaddr_in6 *in6; - struct saddr *saddr; - struct addrinfo *results = NULL, *ai; - int r; - - assert_return(dns && dns->priv && server_cb); - - server = dns->priv; - debug(DBG_DNS, "called, dns: %p, name: %s, server: %p, server->name: %s", - dns, dns->name, server, server->name); - - r = gai_error(&dns->gcb); - if (r == EAI_INPROGRESS) { - /* This shouldn't happen, assume we'll get called again */ - error("called with request in progress"); - return; - } else if (r == EAI_CANCELED) { - /* The server must be in the process of going away */ - goto out; - } else if (r < 0) { - error("DNS lookup of %s:%s failed: %s", - dns->name, dns->port, gai_strerror(r)); - goto out; - } - - results = dns->gcb.ar_result; - - for (ai = results; ai; ai = ai->ai_next) { - saddr = zmalloc(sizeof(*saddr)); - if (!saddr) { - error("DNS lookup of %s:%s failed: %m", dns->name, dns->port); - goto out; - } - - switch (ai->ai_family) { - case AF_INET: - in4 = (struct sockaddr_in *)ai->ai_addr; - saddr_set_ipv4(saddr, in4->sin_addr.s_addr, in4->sin_port); - server_cb(server, saddr); - break; - - case AF_INET6: - in6 = (struct sockaddr_in6 *)ai->ai_addr; - saddr_set_ipv6(saddr, &in6->sin6_addr, in6->sin6_port); - server_cb(server, saddr); - break; - - default: - error("getaddrinfo(%s:%s): unknown address family (%i)", - dns->name, dns->port, ai->ai_family); - xfree(saddr); - break; - } - } - -out: - freeaddrinfo(results); - list_del(&dns->list); - xfree(dns); - uring_task_put(&server->task); - server_commit(server); -} - -static void -scfg_local_dns_cb(struct dns_async *dns) -{ - assert_return(dns); - - scfg_dns_cb(dns, server_add_local); -} - -static void -scfg_remote_dns_cb(struct dns_async *dns) -{ - assert_return(dns); - - scfg_dns_cb(dns, server_add_remote); -} - -static void -scfg_rcon_dns_cb(struct dns_async *dns) -{ - assert_return(dns); - - scfg_dns_cb(dns, server_add_rcon); -} - -enum scfg_keys { - SCFG_KEY_INVALID = 0, - SCFG_KEY_TYPE, - SCFG_KEY_NAME, - SCFG_KEY_PORT, - SCFG_KEY_LOCAL, - SCFG_KEY_REMOTE, - SCFG_KEY_IDLE_TIMEOUT, - SCFG_KEY_STOP_METHOD, - SCFG_KEY_START_METHOD, - SCFG_KEY_STOP_EXEC, - SCFG_KEY_START_EXEC, - SCFG_KEY_RCON, - SCFG_KEY_RCON_PASSWORD, - SCFG_KEY_SYSTEMD_SERVICE, -}; - -struct cfg_key_value_map scfg_key_map[] = { - { - .key_name = "type", - .key_value = SCFG_KEY_TYPE, - .value_type = CFG_VAL_TYPE_STRING, - }, { - .key_name = "name", - .key_value = SCFG_KEY_NAME, - .value_type = CFG_VAL_TYPE_STRING, - }, { - .key_name = "port", - .key_value = SCFG_KEY_PORT, - .value_type = CFG_VAL_TYPE_UINT16, - }, { - .key_name = "local", - .key_value = SCFG_KEY_LOCAL, - .value_type = CFG_VAL_TYPE_ASYNC_ADDRS, - }, { - .key_name = "remote", - .key_value = SCFG_KEY_REMOTE, - .value_type = CFG_VAL_TYPE_ASYNC_ADDRS, - }, { - .key_name = "idle_timeout", - .key_value = SCFG_KEY_IDLE_TIMEOUT, - .value_type = CFG_VAL_TYPE_UINT16, - }, { - .key_name = "stop_method", - .key_value = SCFG_KEY_STOP_METHOD, - .value_type = CFG_VAL_TYPE_STRING, - }, { - .key_name = "start_method", - .key_value = SCFG_KEY_START_METHOD, - .value_type = CFG_VAL_TYPE_STRING, - }, { - .key_name = "stop_exec", - .key_value = SCFG_KEY_STOP_EXEC, - .value_type = CFG_VAL_TYPE_STRING, - }, { - .key_name = "start_exec", - .key_value = SCFG_KEY_START_EXEC, - .value_type = CFG_VAL_TYPE_STRING, - }, { - .key_name = "rcon", - .key_value = SCFG_KEY_RCON, - .value_type = CFG_VAL_TYPE_ASYNC_ADDRS, - }, { - .key_name = "rcon_password", - .key_value = SCFG_KEY_RCON_PASSWORD, - .value_type = CFG_VAL_TYPE_STRING, - }, { - .key_name = "systemd_service", - .key_value = SCFG_KEY_SYSTEMD_SERVICE, - .value_type = CFG_VAL_TYPE_STRING, - }, { - .key_name = NULL, - .key_value = SCFG_KEY_INVALID, - .value_type = CFG_VAL_TYPE_INVALID, - } -}; - -static bool -handle_dns(struct server *server, const char *type, - struct cfg_value *value, dns_cb_t *async_cb, - bool (*sync_cb)(struct server *, struct saddr *)) -{ - struct saddr *saddr, *tmp; - struct dns_async *dns; - - assert_return(server && type && value && async_cb && sync_cb, false); - - switch (value->type) { - case CFG_VAL_TYPE_ADDRS: - debug(DBG_DNS, "%s: got immediate addrs", type); - - list_for_each_entry_safe(saddr, tmp, &value->saddrs, list) { - list_del(&saddr->list); - sync_cb(server, saddr); - } - return true; - - case CFG_VAL_TYPE_ASYNC_ADDRS: - debug(DBG_DNS, "%s: doing async lookup of DNS record: %p", - type, value->dns_async); - - dns = value->dns_async; - dns->cb = async_cb; - dns->priv = server; - list_add(&dns->list, &server->dnslookups); - uring_task_get(&server->task); - return true; - - default: - return false; - } -} - -static void -scfg_parse(struct server *server) -{ - char *pos; - - assert_return(server); - - pos = server->tbuf.buf; - - if (!config_parse_header(server->name, "server", &pos)) - return; - - while (true) { - int key; - const char *keyname; - struct cfg_value value; - - if (!config_parse_line(server->name, &pos, scfg_key_map, - &key, &keyname, &value)) - break; - - if (key == SCFG_KEY_INVALID) - break; - - debug(DBG_CFG, "%s: key %s", server->name, keyname); - - switch (key) { - - case SCFG_KEY_TYPE: - if (streq(value.str, "proxy")) { - if (!server_set_type(server, SERVER_TYPE_PROXY)) - return; - } else if (streq(value.str, "announce")) { - if (!server_set_type(server, SERVER_TYPE_ANNOUNCE)) - return; - } - break; - - case SCFG_KEY_NAME: - if (!server_set_pretty_name(server, value.str)) - return; - break; - - case SCFG_KEY_PORT: - if (!server_set_port(server, value.uint16)) - return; - break; - - case SCFG_KEY_LOCAL: - if (!handle_dns(server, "local", &value, - scfg_local_dns_cb, server_add_local)) - return; - break; - - case SCFG_KEY_REMOTE: - if (!handle_dns(server, "remote", &value, - scfg_remote_dns_cb, server_add_remote)) - return; - break; - - case SCFG_KEY_IDLE_TIMEOUT: - if (!server_set_idle_timeout(server, value.uint16)) - return; - break; - - case SCFG_KEY_STOP_METHOD: - if (streq(value.str, "exec")) { - if (server_set_stop_method(server, SERVER_STOP_METHOD_EXEC)) - break; - } else if (streq(value.str, "rcon")) { - if (server_set_stop_method(server, SERVER_STOP_METHOD_RCON)) - break; - } else if (streq(value.str, "systemd")) { - if (server_set_stop_method(server, SERVER_STOP_METHOD_SYSTEMD)) - break; - } - return; - - case SCFG_KEY_START_METHOD: - if (streq(value.str, "exec")) { - if (server_set_start_method(server, SERVER_START_METHOD_EXEC)) - break; - } else if (streq(value.str, "systemd")) { - if (server_set_start_method(server, SERVER_START_METHOD_SYSTEMD)) - break; - } - return; - - case SCFG_KEY_STOP_EXEC: - if (!server_set_stop_exec(server, value.str)) - return; - break; - - case SCFG_KEY_START_EXEC: - if (!server_set_start_exec(server, value.str)) - return; - break; - - case SCFG_KEY_RCON: - if (!handle_dns(server, "rcon", &value, - scfg_rcon_dns_cb, server_add_rcon)) - return; - break; - - case SCFG_KEY_RCON_PASSWORD: - if (!server_set_rcon_password(server, value.str)) - return; - break; - - case SCFG_KEY_SYSTEMD_SERVICE: - if (!server_set_systemd_service(server, value.str)) - return; - break; - - case SCFG_KEY_INVALID: - default: - break; - } - } -} - -static void -scfg_read_cb(struct uring_task *task, int res) -{ - struct server *server = container_of(task, struct server, task); - - assert_return(task); - assert_task_alive(DBG_CFG, task); - - if (res <= 0) { - error("error reading config file for %s: %s", - server->name, strerror(-res)); - server_delete(server); - } - - debug(DBG_CFG, "%s: parsing cfg (%i bytes)", server->name, res); - uring_task_close_fd(&server->task); - scfg_parse(server); - server_commit(server); -} - -static void -scfg_open_cb(struct uring_task *task, int res) -{ - struct server *server = container_of(task, struct server, task); - - assert_return(task); - assert_task_alive(DBG_CFG, task); - - if (res < 0) { - error("open(%s) failed: %s", server->name, strerror(-res)); - server_delete(server); - return; - } - - debug(DBG_CFG, "reading server cfg %s (fd %i)", server->name, res); - uring_task_set_fd(&server->task, res); - uring_tbuf_read_until_eof(&server->task, scfg_read_cb); -} - -static bool -scfg_valid_filename(const char *name) -{ - const char *suffix; - - if (empty_str(name)) - return false; - if (name[0] == '.') - return false; - if ((suffix = strrchr(name, '.')) == NULL) - return false; - if (!streq(suffix, ".server")) - return false; - - return true; -} - -struct inotify_ev { - struct uring_task task; - char buf[4096] __attribute__((aligned(__alignof__(struct inotify_event)))); -}; - -static void -inotify_free(struct uring_task *task) -{ - struct inotify_ev *iev = container_of(task, struct inotify_ev, task); - - assert_return(task); - - debug(DBG_CFG, "called"); - xfree(iev); - cfg->iev = NULL; -} - -static void -inotify_event_dump(const struct inotify_event *event) -{ - assert_return(event); - - debug(DBG_CFG, "inotify event:"); - debug(DBG_CFG, " * WD : %i", event->wd); - debug(DBG_CFG, " * Cookie : %" PRIu32, event->cookie); - debug(DBG_CFG, " * Length : %" PRIu32, event->len); - debug(DBG_CFG, " * Name : %s", event->name); - debug(DBG_CFG, " * Mask : %" PRIu32, event->mask); - if (event->mask & IN_ACCESS) - debug(DBG_CFG, "\tIN_ACCESS"); - else if(event->mask & IN_MODIFY) - debug(DBG_CFG, "\tIN_MODIFY"); - else if(event->mask & IN_ATTRIB) - debug(DBG_CFG, "\tIN_ATTRIB"); - else if(event->mask & IN_CLOSE_WRITE) - debug(DBG_CFG, "\tIN_CLOSE_WRITE"); - else if(event->mask & IN_CLOSE_NOWRITE) - debug(DBG_CFG, "\tIN_CLOSE_NOWRITE"); - else if(event->mask & IN_OPEN) - debug(DBG_CFG, "\tIN_OPEN"); - else if(event->mask & IN_MOVED_FROM) - debug(DBG_CFG, "\tIN_MOVED_FROM"); - else if(event->mask & IN_MOVED_TO) - debug(DBG_CFG, "\tIN_MOVED_TO"); - else if(event->mask & IN_CREATE) - debug(DBG_CFG, "\tIN_CREATE"); - else if(event->mask & IN_DELETE) - debug(DBG_CFG, "\tIN_DELETE"); - else if(event->mask & IN_DELETE_SELF) - debug(DBG_CFG, "\tIN_DELETE_SELF"); - else if(event->mask & IN_MOVE_SELF) - debug(DBG_CFG, "\tIN_MOVE_SELF"); - else if(event->mask & IN_UNMOUNT) - debug(DBG_CFG, "\tIN_UNMOUNT"); - else if(event->mask & IN_Q_OVERFLOW) - debug(DBG_CFG, "\tIN_Q_OVERFLOW"); - else if(event->mask & IN_IGNORED) - debug(DBG_CFG, "\tIN_IGNORED"); -} - -static void -inotify_cb(struct uring_task *task, int res) -{ - struct inotify_ev *iev = container_of(task, struct inotify_ev, task); - const struct inotify_event *event; - char *ptr; - struct server *server; - - assert_return(task); - assert_task_alive(DBG_CFG, task); - - if (res <= 0) { - error("inotify_read: %i", res); - return; - } - - for (ptr = iev->buf; ptr < iev->buf + res; ptr += sizeof(struct inotify_event) + event->len) { - event = (const struct inotify_event *)ptr; - - if (debug_enabled(DBG_CFG)) - inotify_event_dump(event); - - if (event->mask & (IN_IGNORED | IN_MOVE_SELF | IN_DELETE_SELF | IN_UNMOUNT)) - die("configuration directory gone, exiting"); - - if (event->mask & IN_Q_OVERFLOW) { - error("inotify queue overflow"); - continue; - } - - if (!scfg_valid_filename(event->name)) - continue; - - if (event->mask & (IN_MOVED_FROM | IN_DELETE)) - server_delete_by_name(event->name); - else if (event->mask & (IN_MOVED_TO | IN_CREATE | IN_CLOSE_WRITE)) { - server = server_new(event->name); - verbose("New server config file detected: %s", server->name); - uring_openat(&server->task, server->name, scfg_open_cb); - } else - error("inotify: unknown event: 0x%08x", event->mask); - } - - uring_read(&iev->task, iev->buf, sizeof(iev->buf), inotify_cb); -} - -void -cfgdir_refdump() -{ - assert_return_silent(cfg->iev); - - uring_task_refdump(&cfg->iev->task); -} - -void -cfgdir_delete() -{ - assert_return(cfg->iev); - - debug(DBG_CFG, "closing fd %i", cfg->iev->task.fd); - uring_task_destroy(&cfg->iev->task); - cfg->iev = NULL; -} - -void -cfgdir_init() -{ - int ifd; - int iwd; - struct inotify_ev *iev; - DIR *dir; - struct dirent *dent; - struct server *server; - - assert_return(!cfg->iev); - - iev = zmalloc(sizeof(*iev)); - if (!iev) - die("malloc: %m"); - - ifd = inotify_init1(IN_CLOEXEC); - if (ifd < 0) - die("inotify_init1: %m"); - - /* ln = IN_CREATE, cp/vi/mv = IN_CREATE, IN_OPEN, IN_CLOSE_WRITE */ - iwd = inotify_add_watch(ifd, ".", - IN_CLOSE_WRITE | IN_DELETE | IN_CREATE | - IN_DELETE_SELF | IN_MOVE_SELF | IN_MOVED_TO | - IN_MOVED_FROM | IN_DONT_FOLLOW | - IN_EXCL_UNLINK | IN_ONLYDIR ); - if (iwd < 0) - die("inotify_add_watch: %m"); - - uring_task_init(&iev->task, "server_config", uring_parent(), inotify_free); - uring_task_set_fd(&iev->task, ifd); - cfg->iev = iev; - uring_read(&iev->task, iev->buf, sizeof(iev->buf), inotify_cb); - - dir = opendir("."); - if (!dir) - die("opendir(%s): %m", cfg->homedir); - - while ((dent = readdir(dir)) != NULL) { - if (dent->d_type != DT_REG && dent->d_type != DT_UNKNOWN) - continue; - if (!scfg_valid_filename(dent->d_name)) - continue; - - server = server_new(dent->d_name); - if (server) - uring_openat(&server->task, server->name, scfg_open_cb); - } - - closedir(dir); -} - -- cgit v1.2.3