summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Härdeman <david@hardeman.nu>2020-06-05 16:27:31 +0200
committerDavid Härdeman <david@hardeman.nu>2020-06-05 16:27:31 +0200
commitcf87432e410cbe2ee61e90b8f4c2e8d2a75f09ca (patch)
tree73a38b16215515ce7d3cd87b9f8ccfb55e22e885
parentdb66484c4300f5f0e857eff01d15fd3593002a79 (diff)
Split config into generic and dir watching parts
-rw-r--r--.gitignore2
-rw-r--r--cfgdir.c (renamed from inotify.c)413
-rw-r--r--cfgdir.h10
-rw-r--r--config.c456
-rw-r--r--config.h25
-rw-r--r--inotify.h12
-rw-r--r--main.c9
-rw-r--r--meson.build2
8 files changed, 116 insertions, 813 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..f7cb71c
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+build
+attic
diff --git a/inotify.c b/cfgdir.c
index f362920..34283f4 100644
--- a/inotify.c
+++ b/cfgdir.c
@@ -14,408 +14,62 @@
#include "main.h"
#include "uring.h"
+#include "cfgdir.h"
#include "config.h"
#include "server.h"
-static void
-eat_whitespace_and_comments(char **pos)
-{
- while (true) {
- while (isspace(**pos))
- (*pos)++;
-
- if (**pos == '#') {
- while (**pos != '\r' && **pos != '\n' && **pos != '\0')
- (*pos)++;
- continue;
- }
-
- return;
- }
-}
-
-static char *
-get_line(char **pos)
-{
- char *begin = *pos;
- char *end;
-
- while (isspace(*begin))
- begin++;
-
- if (*begin == '\0')
- return NULL;
-
- end = begin;
- while (*end != '\n' && *end != '\0')
- end++;
-
- if (*end == '\0')
- *pos = end;
- else
- *pos = end + 1;
-
- while (isspace(*end)) {
- *end = '\0';
- end--;
- }
-
- return begin;
-}
-
-static bool
-strtosockaddrs(const char *str, struct list_head *list)
-{
- char *tmp;
- uint16_t port;
- int r;
- struct sockaddr_in46 *addr;
-
- if (!str || *str == '\0' || !list)
- return false;
- list_init(list);
-
- if (*str == '[') {
- /* IPv6, [a:b:c...h]:p or [*]:p */
- str++;
- tmp = strchr(str, ']');
- if (!tmp)
- goto out;
- *tmp = '\0';
-
- addr = zmalloc(sizeof(*addr));
- if (!addr)
- goto out;
- list_add(&addr->list, list);
-
- if (!strcmp(str, "*"))
- addr->in6.sin6_addr = in6addr_any;
- else if (inet_pton(AF_INET6, str, &addr->in6.sin6_addr) <= 0)
- goto out;
-
- tmp++;
- if (*tmp != ':')
- goto out;
-
- tmp++;
- if (strtou16_strict(tmp, &port) < 0)
- goto out;
-
- addr->in6.sin6_family = AF_INET6;
- addr->in6.sin6_port = htons(port);
- addr->addrlen = sizeof(addr->in6);
-
- } else if (*str == '*') {
- /* IPv4, *:p */
- str++;
- if (*str != ':')
- goto out;
-
- str++;
- if (strtou16_strict(str, &port) < 0)
- goto out;
-
- addr = zmalloc(sizeof(*addr));
- if (!addr)
- goto out;
- list_add(&addr->list, list);
-
- addr->in4.sin_family = AF_INET;
- addr->in4.sin_addr.s_addr = INADDR_ANY;
- addr->in4.sin_port = htons(port);
- addr->addrlen = sizeof(addr->in4);
-
- } else if ((tmp = strchr(str, ':'))) {
- /* IPv4, a.b.c.d:p or IPv4/6 hostname:p */
- fprintf(stderr, "Got an IPv4:port or hostname:port\n");
- *tmp = '\0';
- tmp++;
- if (strtou16_strict(tmp, &port) < 0)
- goto out;
-
- addr = zmalloc(sizeof(*addr));
- if (!addr)
- goto out;
-
- if (inet_pton(AF_INET, str, &addr->in4.sin_addr) > 0) {
- fprintf(stderr, "...Got an IPv4:port (0x%p, list 0x%p)\n", addr, &addr->list);
- addr->in4.sin_family = AF_INET;
- addr->in4.sin_port = htons(port);
- addr->addrlen = sizeof(addr->in4);
- list_add(&addr->list, list);
- goto success;
- } else {
- free(addr);
- }
-
- struct addrinfo hints = {
- .ai_family = AF_UNSPEC,
- .ai_socktype = SOCK_STREAM,
- .ai_protocol = 0,
- .ai_flags = 0,
- };
- struct addrinfo *results, *ai;
-
- /* FIXME: This is completely synchronous but getaddrinfo_a is not very ergonomic */
- r = getaddrinfo(str, tmp, &hints, &results);
- if (r != 0) {
- fprintf(stderr, "gettaddrinfo(%s): %s\n", str, gai_strerror(r));
- goto out;
- }
-
- fprintf(stderr, "...Got an hostname:port\n");
- for (ai = results; ai; ai = ai->ai_next) {
- fprintf(stderr, "Got a result from getaddrinfo\n");
-
- addr = zmalloc(sizeof(*addr));
- if (!addr) {
- freeaddrinfo(results);
- goto out;
- }
-
- switch (ai->ai_family) {
- case AF_INET: {
- struct sockaddr_in *naddr = (struct sockaddr_in *)ai->ai_addr;
-
- addr->in4.sin_family = AF_INET;
- addr->in4.sin_addr = naddr->sin_addr;
- addr->in4.sin_port = naddr->sin_port;
- addr->addrlen = sizeof(addr->in4);
- list_add(&addr->list, list);
- break;
- }
- case AF_INET6: {
- struct sockaddr_in6 *naddr = (struct sockaddr_in6 *)ai->ai_addr;
-
- addr->in6.sin6_family = AF_INET6;
- addr->in6.sin6_addr = naddr->sin6_addr;
- addr->in6.sin6_port = naddr->sin6_port;
- addr->addrlen = sizeof(addr->in6);
- list_add(&addr->list, list);
- break;
- }
- default:
- fprintf(stderr, " Fam: Unknown (%i)\n", ai->ai_family);
- free(addr);
- continue;
- }
- }
-
- freeaddrinfo(results);
-
- } else if (strtou16_strict(tmp, &port) == 0) {
- /* Port */
-
- addr = zmalloc(sizeof(*addr));
- if (!addr)
- goto out;
- addr->in6.sin6_family = AF_INET6;
- addr->in6.sin6_addr = in6addr_any;
- addr->in6.sin6_port = htons(port);
- addr->addrlen = sizeof(addr->in6);
- list_add(&addr->list, list);
-
- addr = zmalloc(sizeof(*addr));
- if (!addr)
- goto out;
- addr->in4.sin_family = AF_INET;
- addr->in4.sin_addr.s_addr = INADDR_ANY;
- addr->in4.sin_port = htons(port);
- addr->addrlen = sizeof(addr->in4);
- list_add(&addr->list, list);
- }
-
-success:
- if (list_empty(list)) {
- fprintf(stderr, "Success but empty list!?\n");
- return false;
- } else {
- int i = 0;
- struct list_head *pos;
-
- list_for_each(pos, list)
- i++;
- fprintf(stderr, "Success, %i entries\n", i);
- }
-
- return true;
-
-out:
- if (!list_empty(list)) {
- struct sockaddr_in46 *tmpaddr;
-
- list_for_each_entry_safe(addr, tmpaddr, list, list) {
- list_del(&addr->list);
- free(addr);
- }
- }
- return false;
-}
-
enum scfg_keys {
+ SCFG_KEY_INVALID = 0,
SCFG_KEY_TYPE,
SCFG_KEY_NAME,
SCFG_KEY_PORT,
SCFG_KEY_LOCAL,
SCFG_KEY_REMOTE,
- SCFG_KEY_INVALID
-};
-
-enum value_type {
- VAL_TYPE_STRING,
- VAL_TYPE_UINT16,
- VAL_TYPE_ADDR,
- VAL_TYPE_INVALID
};
-struct scfg_key_map {
- const char *key_name;
- enum scfg_keys key_value;
- enum value_type value_type;
-} scfg_key_map[] = {
+struct cfg_key_value_map scfg_key_map[] = {
{
.key_name = "type",
.key_value = SCFG_KEY_TYPE,
- .value_type = VAL_TYPE_STRING,
+ .value_type = CFG_VAL_TYPE_STRING,
}, {
.key_name = "name",
.key_value = SCFG_KEY_NAME,
- .value_type = VAL_TYPE_STRING,
+ .value_type = CFG_VAL_TYPE_STRING,
}, {
.key_name = "port",
.key_value = SCFG_KEY_PORT,
- .value_type = VAL_TYPE_UINT16,
+ .value_type = CFG_VAL_TYPE_UINT16,
}, {
.key_name = "local",
.key_value = SCFG_KEY_LOCAL,
- .value_type = VAL_TYPE_ADDR,
+ .value_type = CFG_VAL_TYPE_ADDRS,
}, {
.key_name = "remote",
.key_value = SCFG_KEY_REMOTE,
- .value_type = VAL_TYPE_ADDR,
+ .value_type = CFG_VAL_TYPE_ADDRS,
+ }, {
+ .key_name = NULL,
+ .key_value = SCFG_KEY_INVALID,
+ .value_type = CFG_VAL_TYPE_INVALID,
}
};
-union cfg_value {
- const char *str;
- uint16_t uint16;
- struct list_head addr_list;
-};
-
-
-static void
-line_get_key_value(char *line, enum scfg_keys *rkey, union cfg_value *rvalue)
-{
- char *tmp, *key;
- int i;
-
- *rkey = SCFG_KEY_INVALID;
- if (!line)
- return;
-
- tmp = line;
- while (isspace(*tmp))
- tmp++;
-
- if (*tmp == '\0')
- return;
-
- key = tmp;
- while (*tmp != '\0' && !isspace(*tmp))
- tmp++;
-
- if (*tmp == '\0')
- return;
-
- *tmp = '\0';
- tmp++;
-
- while (isspace(*tmp))
- tmp++;
-
- if (*tmp != '=')
- return;
-
- tmp++;
- while (isspace(*tmp))
- tmp++;
-
- if (*tmp == '\0')
- return;
-
- for (i = 0; i < ARRAY_SIZE(scfg_key_map); i++) {
- if (strcmp(scfg_key_map[i].key_name, key))
- continue;
-
- switch (scfg_key_map[i].value_type) {
-
- case VAL_TYPE_STRING:
- rvalue->str = tmp;
- break;
-
- case VAL_TYPE_UINT16: {
- uint16_t v;
-
- if (strtou16_strict(tmp, &v) < 0)
- return;
- rvalue->uint16 = v;
- break;
- }
-
- case VAL_TYPE_ADDR: {
- if (!strtosockaddrs(tmp, &rvalue->addr_list))
- return;
- if (list_empty(&rvalue->addr_list)) {
- fprintf(stderr, "VAL_TYPE_ADDR with zero list!?\n");
- return;
- } else {
- int i = 0;
- struct list_head *pos;
-
- list_for_each(pos, &rvalue->addr_list)
- i++;
- fprintf(stderr, "VAL_TYPE_ADDR with list %i entries\n", i);
- }
- break;
- }
-
- case VAL_TYPE_INVALID:
- /* fall through */
- default:
- return;
- }
- *rkey = scfg_key_map[i].key_value;
- break;
- }
-}
-
static void
scfg_parse(struct cfg *cfg, struct server *scfg)
{
char *pos = &scfg->buf[0];
- char *line;
-
- eat_whitespace_and_comments(&pos);
- line = get_line(&pos);
- if (!line) {
- printf("Cfg: premature EOF\n");
+ if (!config_parse_header(cfg, "server", &pos))
return;
- }
-
- if (strcmp(line, "[server]")) {
- printf("Invalid line: %s\n", line);
- return;
- }
while (true) {
- enum scfg_keys key;
+ int key;
union cfg_value value;
- eat_whitespace_and_comments(&pos);
- line = get_line(&pos);
- printf("Examining line: %s\n", line);
- line_get_key_value(line, &key, &value);
+ if (!config_parse_line(cfg, &pos, scfg_key_map, &key, &value))
+ break;
+
if (key == SCFG_KEY_INVALID)
break;
printf("Got a key-value pair: %i = something\n", key);
@@ -646,13 +300,13 @@ inotify_cb(struct cfg *cfg, struct uring_task *task, int res)
}
void
-inotify_refdump(struct inotify_ev *iev)
+cfgdir_refdump(struct inotify_ev *iev)
{
uring_task_refdump(&iev->task);
}
void
-scfg_stop_monitor_dir(struct cfg *cfg)
+cfgdir_delete(struct cfg *cfg)
{
if (!cfg->iev) {
fprintf(stderr, "%s called with no iev!\n", __func__);
@@ -665,11 +319,14 @@ scfg_stop_monitor_dir(struct cfg *cfg)
}
void
-scfg_monitor_dir(struct cfg *cfg)
+cfgdir_init(struct cfg *cfg)
{
int ifd;
int iwd;
struct inotify_ev *iev;
+ DIR *cfgdir;
+ struct dirent *dent;
+ struct server *scfg;
iev = malloc(sizeof(*iev));
if (!iev)
@@ -692,33 +349,15 @@ scfg_monitor_dir(struct cfg *cfg)
uring_task_set_fd(&iev->task, ifd);
cfg->iev = iev;
uring_read(cfg, &iev->task, iev->buf, sizeof(iev->buf), 0, inotify_cb);
-}
-
-void
-scfg_read_all(struct cfg *cfg)
-{
-
- DIR *cfgdir;
- struct dirent *dent;
- struct server *scfg;
cfgdir = opendir(".");
- if (!cfgdir) {
- perror("opendir");
- free(cfg);
- return;
- }
+ if (!cfgdir)
+ perrordie("opendir");
while ((dent = readdir(cfgdir)) != NULL) {
- char *suffix;
-
- if (dent->d_name[0] == '.')
- continue;
if (dent->d_type != DT_REG && dent->d_type != DT_UNKNOWN)
continue;
- if ((suffix = strrchr(dent->d_name, '.')) == NULL)
- continue;
- if (strcmp(suffix, ".server"))
+ if (!scfg_valid_filename(dent->d_name))
continue;
scfg = server_new(cfg, dent->d_name);
diff --git a/cfgdir.h b/cfgdir.h
new file mode 100644
index 0000000..ff55fb9
--- /dev/null
+++ b/cfgdir.h
@@ -0,0 +1,10 @@
+#ifndef foocfgdirhfoo
+#define foocfgdirhfoo
+
+void cfgdir_delete(struct cfg *cfg);
+
+void cfgdir_refdump(struct inotify_ev *iev);
+
+void cfgdir_init(struct cfg *cfg);
+
+#endif
diff --git a/config.c b/config.c
index f362920..f13191b 100644
--- a/config.c
+++ b/config.c
@@ -2,8 +2,6 @@
#include <ctype.h>
#include <string.h>
#include <stdbool.h>
-#include <sys/inotify.h>
-#include <dirent.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
@@ -252,80 +250,37 @@ out:
return false;
}
-enum scfg_keys {
- SCFG_KEY_TYPE,
- SCFG_KEY_NAME,
- SCFG_KEY_PORT,
- SCFG_KEY_LOCAL,
- SCFG_KEY_REMOTE,
- SCFG_KEY_INVALID
-};
-
-enum value_type {
- VAL_TYPE_STRING,
- VAL_TYPE_UINT16,
- VAL_TYPE_ADDR,
- VAL_TYPE_INVALID
-};
-
-struct scfg_key_map {
- const char *key_name;
- enum scfg_keys key_value;
- enum value_type value_type;
-} scfg_key_map[] = {
- {
- .key_name = "type",
- .key_value = SCFG_KEY_TYPE,
- .value_type = VAL_TYPE_STRING,
- }, {
- .key_name = "name",
- .key_value = SCFG_KEY_NAME,
- .value_type = VAL_TYPE_STRING,
- }, {
- .key_name = "port",
- .key_value = SCFG_KEY_PORT,
- .value_type = VAL_TYPE_UINT16,
- }, {
- .key_name = "local",
- .key_value = SCFG_KEY_LOCAL,
- .value_type = VAL_TYPE_ADDR,
- }, {
- .key_name = "remote",
- .key_value = SCFG_KEY_REMOTE,
- .value_type = VAL_TYPE_ADDR,
- }
-};
-
-union cfg_value {
- const char *str;
- uint16_t uint16;
- struct list_head addr_list;
-};
-
-
-static void
-line_get_key_value(char *line, enum scfg_keys *rkey, union cfg_value *rvalue)
+/* Returns true if theres data left to parse in buf */
+bool
+config_parse_line(struct cfg *cfg, char **buf, struct cfg_key_value_map *kvmap,
+ int *rkey, union cfg_value *rvalue)
{
- char *tmp, *key;
+ char *line, *tmp, *key;
int i;
- *rkey = SCFG_KEY_INVALID;
+ if (!cfg || !buf || !*buf || !kvmap || !rkey || !rvalue)
+ die("%s: called with invalid parameters\n", __func__);
+
+ eat_whitespace_and_comments(buf);
+ line = get_line(buf);
if (!line)
- return;
+ return false;
+
+ printf("%s: examining line: %s\n", __func__, line);
tmp = line;
while (isspace(*tmp))
tmp++;
if (*tmp == '\0')
- return;
+ goto out;
key = tmp;
while (*tmp != '\0' && !isspace(*tmp))
tmp++;
if (*tmp == '\0')
- return;
+ goto out;
*tmp = '\0';
tmp++;
@@ -334,397 +289,90 @@ line_get_key_value(char *line, enum scfg_keys *rkey, union cfg_value *rvalue)
tmp++;
if (*tmp != '=')
- return;
+ goto out;
tmp++;
while (isspace(*tmp))
tmp++;
if (*tmp == '\0')
- return;
+ goto out;
- for (i = 0; i < ARRAY_SIZE(scfg_key_map); i++) {
- if (strcmp(scfg_key_map[i].key_name, key))
+ for (i = 0; kvmap[i].key_name; i++) {
+ if (strcmp(kvmap[i].key_name, key))
continue;
- switch (scfg_key_map[i].value_type) {
+ switch (kvmap[i].value_type) {
- case VAL_TYPE_STRING:
+ case CFG_VAL_TYPE_STRING:
rvalue->str = tmp;
break;
- case VAL_TYPE_UINT16: {
+ case CFG_VAL_TYPE_UINT16: {
uint16_t v;
if (strtou16_strict(tmp, &v) < 0)
- return;
+ goto out;
rvalue->uint16 = v;
break;
}
- case VAL_TYPE_ADDR: {
+ case CFG_VAL_TYPE_ADDRS: {
if (!strtosockaddrs(tmp, &rvalue->addr_list))
- return;
+ goto out;
if (list_empty(&rvalue->addr_list)) {
- fprintf(stderr, "VAL_TYPE_ADDR with zero list!?\n");
- return;
+ fprintf(stderr, "CFG_VAL_TYPE_ADDRS with zero list!?\n");
+ goto out;
} else {
int i = 0;
struct list_head *pos;
list_for_each(pos, &rvalue->addr_list)
i++;
- fprintf(stderr, "VAL_TYPE_ADDR with list %i entries\n", i);
+ fprintf(stderr, "CFG_VAL_TYPE_ADDRS with list %i entries\n", i);
}
break;
}
- case VAL_TYPE_INVALID:
+ case CFG_VAL_TYPE_INVALID:
/* fall through */
default:
- return;
- }
- *rkey = scfg_key_map[i].key_value;
- break;
- }
-}
-
-static void
-scfg_parse(struct cfg *cfg, struct server *scfg)
-{
- char *pos = &scfg->buf[0];
- char *line;
-
- eat_whitespace_and_comments(&pos);
-
- line = get_line(&pos);
- if (!line) {
- printf("Cfg: premature EOF\n");
- return;
- }
-
- if (strcmp(line, "[server]")) {
- printf("Invalid line: %s\n", line);
- return;
- }
-
- while (true) {
- enum scfg_keys key;
- union cfg_value value;
-
- eat_whitespace_and_comments(&pos);
- line = get_line(&pos);
- printf("Examining line: %s\n", line);
- line_get_key_value(line, &key, &value);
- if (key == SCFG_KEY_INVALID)
- break;
- printf("Got a key-value pair: %i = something\n", key);
-
- switch (key) {
-
- case SCFG_KEY_TYPE:
- if (!strcmp(value.str, "proxy")) {
- if (!server_set_type(cfg, scfg, SERVER_TYPE_PROXY))
- return;
- } else if (!strcmp(value.str, "announce")) {
- if (!server_set_type(cfg, scfg, SERVER_TYPE_ANNOUNCE))
- return;
- }
- break;
-
- case SCFG_KEY_NAME:
- if (!server_set_pretty_name(cfg, scfg, value.str))
- return;
- break;
-
- case SCFG_KEY_PORT:
- if (!server_set_port(cfg, scfg, value.uint16))
- return;
- break;
-
- case SCFG_KEY_LOCAL: {
- struct sockaddr_in46 *addr, *tmp;
-
- list_for_each_entry_safe(addr, tmp, &value.addr_list, list) {
- list_del(&addr->list);
- server_add_local(cfg, scfg, addr);
- }
- break;
- }
-
- case SCFG_KEY_REMOTE: {
- struct sockaddr_in46 *addr, *tmp;
-
- list_for_each_entry_safe(addr, tmp, &value.addr_list, list) {
- list_del(&addr->list);
- server_add_remote(cfg, scfg, addr);
- }
- break;
- }
-
- case SCFG_KEY_INVALID:
- default:
- break;
- }
- }
-
- //printf("Cfg:\n%s\n\n", pos);
-}
-
-static void
-scfg_read_cb(struct cfg *cfg, struct uring_task *task, int res)
-{
- struct server *scfg = container_of(task, struct server, task);
-
- printf("Asked to parse server cfg %s (bytes %i)\n", scfg->name, res);
-
- if (res < 0) {
- perrordie("read");
- } else if (res > 0) {
- scfg->len += res;
- if (scfg->len + 1 >= sizeof(scfg->buf)) {
- fprintf(stderr, "Server config too large\n");
- server_delete(cfg, scfg);
- return;
+ goto out;
}
- uring_read(cfg, &scfg->task, scfg->buf + scfg->len, sizeof(scfg->buf) - scfg->len, scfg->len, scfg_read_cb);
- return;
- } else {
- /* EOF */
- scfg->buf[scfg->len] = '\0';
- uring_task_close_fd(cfg, &scfg->task);
- scfg_parse(cfg, scfg);
- server_commit(cfg, scfg);
+ *rkey = kvmap[i].key_value;
+ return true;
}
-}
-
-static void
-scfg_open_cb(struct cfg *cfg, struct uring_task *task, int res)
-{
- struct server *scfg = container_of(task, struct server, task);
-
- if (res < 0) {
- fprintf(stderr, "Open failed\n");
- server_delete(cfg, scfg);
- return;
- }
-
- printf("Asked to read server cfg %s (fd %i)\n", scfg->name, res);
- uring_task_set_fd(&scfg->task, res);
- scfg->len = 0;
- uring_read(cfg, &scfg->task, scfg->buf, sizeof(scfg->buf), 0, scfg_read_cb);
-}
-
-static bool
-scfg_valid_filename(const char *name)
-{
- const char *suffix;
-
- if (!name)
- return false;
- if (name[0] == '\0')
- return false;
- if (name[0] == '.')
- return false;
- if ((suffix = strrchr(name, '.')) == NULL)
- return false;
- if (strcmp(suffix, ".server"))
- return false;
+out:
+ fprintf(stderr, "Invalid line\n");
+ *rkey = 0;
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)
+bool
+config_parse_header(struct cfg *cfg, const char *title, char **buf)
{
- struct inotify_ev *iev = container_of(task, struct inotify_ev, task);
- struct cfg *cfg = container_of(task->parent, struct cfg, task);
-
- fprintf(stderr, "%s called\n", __func__);
- if (!iev || !cfg)
- die("%s: iev or cfg is NULL!?\n", __func__);
-
- free(iev);
- cfg->iev = NULL;
- uring_task_put(cfg, &cfg->task);
-}
-
-static void
-inotify_event_dump(const struct inotify_event *event)
-{
- printf("Event:\n");
- printf(" * WD : %i\n", event->wd);
- printf(" * Cookie : %" PRIu32 "\n", event->cookie);
- printf(" * Length : %" PRIu32 "\n", event->len);
- printf(" * Name : %s\n", event->name);
- printf(" * Mask : %" PRIu32 "\n", event->mask);
- if (event->mask & IN_ACCESS)
- printf("\tIN_ACCESS\n");
- else if(event->mask & IN_MODIFY)
- printf("\tIN_MODIFY\n");
- else if(event->mask & IN_ATTRIB)
- printf("\tIN_ATTRIB\n");
- else if(event->mask & IN_CLOSE_WRITE)
- printf("\tIN_CLOSE_WRITE\n");
- else if(event->mask & IN_CLOSE_NOWRITE)
- printf("\tIN_CLOSE_NOWRITE\n");
- else if(event->mask & IN_OPEN)
- printf("\tIN_OPEN\n");
- else if(event->mask & IN_MOVED_FROM)
- printf("\tIN_MOVED_FROM\n");
- else if(event->mask & IN_MOVED_TO)
- printf("\tIN_MOVED_TO\n");
- else if(event->mask & IN_CREATE)
- printf("\tIN_CREATE\n");
- else if(event->mask & IN_DELETE)
- printf("\tIN_DELETE\n");
- else if(event->mask & IN_DELETE_SELF)
- printf("\tIN_DELETE_SELF\n");
- else if(event->mask & IN_MOVE_SELF)
- printf("\tIN_MOVE_SELF\n");
- else if(event->mask & IN_UNMOUNT)
- printf("\tIN_UNMOUNT\n");
- else if(event->mask & IN_Q_OVERFLOW)
- printf("\tIN_Q_OVERFLOW\n");
- else if(event->mask & IN_IGNORED)
- printf("\tIN_IGNORED\n");
- printf("\n");
-}
-
-static void
-inotify_cb(struct cfg *cfg, 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 *scfg;
-
- fprintf(stderr, "%s: ret is %i (ref %u)\n", __func__, res, task->refcount);
-
- if (task->dead) {
- fprintf(stderr, "%s: task is dead\n", __func__);
- uring_task_put(cfg, task);
- return;
- }
-
- if (res <= 0)
- perrordie("inotify_read");
+ char *line;
- for (ptr = iev->buf; ptr < iev->buf + res; ptr += sizeof(struct inotify_event) + event->len) {
- event = (const struct inotify_event *)ptr;
+ if (!cfg || !title || !buf || !*buf)
+ return false;
- if (debuglvl > 0)
- inotify_event_dump(event);
+ eat_whitespace_and_comments(buf);
- if (event->mask & (IN_IGNORED | IN_MOVE_SELF | IN_DELETE_SELF | IN_UNMOUNT))
- die("Configuration directory gone, exiting\n");
+ line = get_line(buf);
+ if (!line) {
+ printf("Cfg: premature EOF\n");
+ return false;
+ } else {
+ char titlehdr[strlen(title) + 3];
- if (event->mask & IN_Q_OVERFLOW) {
- error("inotify queue overflow!\n");
- continue;
+ sprintf(titlehdr, "[%s]", title);
+ if (strcmp(line, titlehdr)) {
+ printf("Invalid header: %s\n", line);
+ return false;
}
-
- if (!scfg_valid_filename(event->name))
- continue;
-
- if (event->mask & (IN_MOVED_FROM | IN_DELETE))
- server_delete_by_name(cfg, event->name);
- else if (event->mask & (IN_MOVED_TO | IN_CREATE | IN_CLOSE_WRITE)) {
- scfg = server_new(cfg, event->name);
- uring_openat(cfg, &scfg->task, event->name, scfg_open_cb);
- } else
- error("inotify: weird, unknown event: 0x%08x\n", event->mask);
- }
-
- uring_read(cfg, &iev->task, iev->buf, sizeof(iev->buf), 0, inotify_cb);
-}
-
-void
-inotify_refdump(struct inotify_ev *iev)
-{
- uring_task_refdump(&iev->task);
-}
-
-void
-scfg_stop_monitor_dir(struct cfg *cfg)
-{
- if (!cfg->iev) {
- fprintf(stderr, "%s called with no iev!\n", __func__);
- return;
}
- fprintf(stderr, "%s called, closing fd %i\n", __func__, cfg->iev->task.fd);
- uring_cancel(cfg, &cfg->iev->task);
- cfg->iev = NULL;
-}
-
-void
-scfg_monitor_dir(struct cfg *cfg)
-{
- int ifd;
- int iwd;
- struct inotify_ev *iev;
-
- iev = malloc(sizeof(*iev));
- if (!iev)
- perrordie("malloc");
-
- ifd = inotify_init1(IN_CLOEXEC);
- if (ifd < 0)
- perrordie("inotify_init1");
-
- /* 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)
- perrordie("inotify_add_watch");
-
- uring_task_init(&iev->task, "iev", &cfg->task, inotify_free);
- uring_task_set_fd(&iev->task, ifd);
- cfg->iev = iev;
- uring_read(cfg, &iev->task, iev->buf, sizeof(iev->buf), 0, inotify_cb);
-}
-
-void
-scfg_read_all(struct cfg *cfg)
-{
-
- DIR *cfgdir;
- struct dirent *dent;
- struct server *scfg;
-
- cfgdir = opendir(".");
- if (!cfgdir) {
- perror("opendir");
- free(cfg);
- return;
- }
-
- while ((dent = readdir(cfgdir)) != NULL) {
- char *suffix;
-
- if (dent->d_name[0] == '.')
- continue;
- if (dent->d_type != DT_REG && dent->d_type != DT_UNKNOWN)
- continue;
- if ((suffix = strrchr(dent->d_name, '.')) == NULL)
- continue;
- if (strcmp(suffix, ".server"))
- continue;
-
- scfg = server_new(cfg, dent->d_name);
- uring_openat(cfg, &scfg->task, dent->d_name, scfg_open_cb);
- }
-
- closedir(cfgdir);
+ return true;
}
-
diff --git a/config.h b/config.h
index c70c6ef..30be385 100644
--- a/config.h
+++ b/config.h
@@ -1,12 +1,29 @@
#ifndef fooconfighfoo
#define fooconfighfoo
-void scfg_monitor_dir(struct cfg *cfg);
+enum cfg_value_type {
+ CFG_VAL_TYPE_INVALID,
+ CFG_VAL_TYPE_STRING,
+ CFG_VAL_TYPE_UINT16,
+ CFG_VAL_TYPE_ADDRS,
+};
-void inotify_refdump(struct inotify_ev *iev);
+struct cfg_key_value_map {
+ const char *key_name;
+ int key_value;
+ enum cfg_value_type value_type;
+};
-void scfg_stop_monitor_dir(struct cfg *cfg);
+union cfg_value {
+ const char *str;
+ uint16_t uint16;
+ struct list_head addr_list; /* FIXME: addrs */
+};
-void scfg_read_all(struct cfg *cfg);
+bool config_parse_line(struct cfg *cfg, char **buf,
+ struct cfg_key_value_map *kvmap,
+ int *key, union cfg_value *value);
+
+bool config_parse_header(struct cfg *cfg, const char *title, char **buf);
#endif
diff --git a/inotify.h b/inotify.h
deleted file mode 100644
index c70c6ef..0000000
--- a/inotify.h
+++ /dev/null
@@ -1,12 +0,0 @@
-#ifndef fooconfighfoo
-#define fooconfighfoo
-
-void scfg_monitor_dir(struct cfg *cfg);
-
-void inotify_refdump(struct inotify_ev *iev);
-
-void scfg_stop_monitor_dir(struct cfg *cfg);
-
-void scfg_read_all(struct cfg *cfg);
-
-#endif
diff --git a/main.c b/main.c
index 70d1b1e..f9df355 100644
--- a/main.c
+++ b/main.c
@@ -17,6 +17,7 @@
#include "uring.h"
#include "config.h"
#include "server.h"
+#include "cfgdir.h"
int debuglvl = 0;
@@ -156,7 +157,7 @@ dump_tree(struct cfg *cfg)
uring_task_refdump(&cfg->sev->task);
uring_refdump(cfg->uev);
if (cfg->iev)
- inotify_refdump(cfg->iev);
+ cfgdir_refdump(cfg->iev);
list_for_each_entry(server, &cfg->servers, list)
server_refdump(server);
fprintf(stderr, "============\n");
@@ -183,7 +184,7 @@ signalfd_read(struct cfg *cfg, struct uring_task *task, int res)
} else {
fprintf(stderr, "Got a signal to dump tree\n");
dump_tree(cfg);
- scfg_stop_monitor_dir(cfg);
+ cfgdir_delete(cfg);
list_for_each_entry_safe(server, stmp, &cfg->servers, list)
server_delete(cfg, server);
uring_read(cfg, &sev->task, &sev->buf, sizeof(sev->buf), 0, signalfd_read);
@@ -274,9 +275,7 @@ main(int argc, char **argv)
signalfd_init(cfg);
- scfg_monitor_dir(cfg);
-
- scfg_read_all(cfg);
+ cfgdir_init(cfg);
uring_event_loop(cfg);
diff --git a/meson.build b/meson.build
index afc5f0d..efa0cdb 100644
--- a/meson.build
+++ b/meson.build
@@ -4,6 +4,6 @@ uring = dependency('liburing')
executable('ctest', 'ctest.c')
executable('stest', 'stest.c')
executable('mcproxy',
- ['main.c', 'uring.c', 'server.c', 'config.c', 'utils.c'],
+ ['main.c', 'uring.c', 'server.c', 'cfgdir.c', 'config.c', 'utils.c'],
dependencies: uring)