From 459c4ae387ce3bf02a4ab27c2fc382974f3e1fae Mon Sep 17 00:00:00 2001 From: David Härdeman Date: Sat, 6 Jun 2020 12:48:27 +0200 Subject: Fixup announce multicast messages to create real per-server messages --- announce.c | 64 ++++++++++++++++++++++++++++++++++----------------------- cfgdir.c | 8 +++++--- server.c | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- server.h | 9 +++++++- utils.c | 12 +++++++++++ utils.h | 5 ++++- 6 files changed, 136 insertions(+), 31 deletions(-) diff --git a/announce.c b/announce.c index 8194f1c..9af2236 100644 --- a/announce.c +++ b/announce.c @@ -9,11 +9,14 @@ #include "uring.h" #include "config.h" #include "announce.h" +#include "server.h" struct announce { uint64_t value; struct uring_task task; + struct uring_task mcast_task; + struct sockaddr_in mcast_addr; }; static void @@ -31,32 +34,39 @@ mcast_sent(struct cfg *cfg, struct uring_task *task, int res) } static void -mcast_send(struct cfg *cfg, struct announce *aev) +mcast_send(struct cfg *cfg, struct announce *aev, struct server *server) { - struct sockaddr_in addr; - struct msghdr msg; - char buf[] = "[MOTD]fumbor - test[/MOTD][AD]1234[/AD]"; - struct iovec iov = { - .iov_base = buf, - .iov_len = sizeof(buf) - }; + int len; + + if (!server || !server->pretty_name || server->announce_port < 1) + return; + + len = snprintf(server->mcast_buf, sizeof(server->mcast_buf), + "[MOTD]%s[/MOTD][AD]%" PRIu16 "[/AD]", + server->pretty_name, server->announce_port); + + if (len < 1 || len >= sizeof(server->mcast_buf)) { + error("%s: snprintf returned %i\n", __func__, len); + return; + } - memset(&addr, 0, sizeof(addr)); - addr.sin_family = AF_INET; - addr.sin_addr.s_addr = inet_addr("224.0.2.60"); - addr.sin_port = htons(4445); - - memset(&msg, 0, sizeof(msg)); - msg.msg_name = &addr; - msg.msg_namelen = sizeof(addr); - msg.msg_iov = &iov; - msg.msg_iovlen = 1; - msg.msg_control = NULL; - msg.msg_controllen = 0; - msg.msg_flags = 0; - - fprintf(stderr, "Manual: %zi\n", sendmsg(aev->mcast_task.fd, &msg, 0)); - uring_sendmsg(cfg, &aev->mcast_task, &msg, mcast_sent); + server->mcast_msg.msg_name = &aev->mcast_addr; + server->mcast_msg.msg_namelen = sizeof(aev->mcast_addr); + server->mcast_iov.iov_len = len; + + //uring_task_get(cfg, &server->task); <--- need to put in mcast_sent + uring_sendmsg(cfg, &aev->mcast_task, &server->mcast_msg, mcast_sent); +} + +static void +mcast_send_all(struct cfg *cfg, struct announce *aev) +{ + struct server *server; + + list_for_each_entry(server, &cfg->servers, list) { + fprintf(stderr, "Announcing server: %s\n", server->name); + mcast_send(cfg, aev, server); + } } static void @@ -76,7 +86,7 @@ announce_cb(struct cfg *cfg, struct uring_task *task, int res) perrordie("timerfd_read"); fprintf(stderr, "%s: called with value %" PRIu64 "\n", __func__, aev->value); - mcast_send(cfg, aev); + mcast_send_all(cfg, aev); uring_read(cfg, &aev->task, &aev->value, sizeof(aev->value), 0, announce_cb); } @@ -171,6 +181,10 @@ announce_init(struct cfg *cfg) uring_task_init(&aev->mcast_task, "aev_mcast", &aev->task, mcast_free); uring_task_set_fd(&aev->mcast_task, sfd); + memset(&aev->mcast_addr, 0, sizeof(aev->mcast_addr)); + aev->mcast_addr.sin_family = AF_INET; + aev->mcast_addr.sin_addr.s_addr = inet_addr("224.0.2.60"); + aev->mcast_addr.sin_port = htons(4445); cfg->aev = aev; uring_read(cfg, &aev->task, &aev->value, sizeof(aev->value), 0, announce_cb); diff --git a/cfgdir.c b/cfgdir.c index 34283f4..443ec5e 100644 --- a/cfgdir.c +++ b/cfgdir.c @@ -159,7 +159,8 @@ 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"); + fprintf(stderr, "%s: open(%s) failed: %s\n", + __func__, scfg->name, strerror(-res)); server_delete(cfg, scfg); return; } @@ -291,7 +292,8 @@ inotify_cb(struct cfg *cfg, struct uring_task *task, int res) 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); + fprintf(stderr, "%s: calling openat(%s)\n", __func__, scfg->name); + uring_openat(cfg, &scfg->task, scfg->name, scfg_open_cb); } else error("inotify: weird, unknown event: 0x%08x\n", event->mask); } @@ -361,7 +363,7 @@ cfgdir_init(struct cfg *cfg) continue; scfg = server_new(cfg, dent->d_name); - uring_openat(cfg, &scfg->task, dent->d_name, scfg_open_cb); + uring_openat(cfg, &scfg->task, scfg->name, scfg_open_cb); } closedir(cfgdir); diff --git a/server.c b/server.c index 9b9788b..25cfad7 100644 --- a/server.c +++ b/server.c @@ -203,9 +203,71 @@ bool server_commit(struct cfg *cfg, struct server *scfg) { struct server_local *local; + uint16_t port; + + if (!scfg || !scfg->name) + return false; + + if (!list_empty(&scfg->proxys)) + return false; + + /* FIXME: running? */ + + switch (scfg->type) { + case SERVER_TYPE_ANNOUNCE: + if (scfg->announce_port < 1) + return false; + if (!list_empty(&scfg->locals)) + return false; + if (!list_empty(&scfg->remotes)) + return false; + break; + + case SERVER_TYPE_PROXY: + if (scfg->announce_port >= 1) + return false; + if (list_empty(&scfg->locals)) + return false; + if (list_empty(&scfg->remotes)) + return false; + + list_for_each_entry(local, &scfg->locals, list) { + port = sockaddr_port(&local->addr); + + if (port == 0) + return false; + + if (scfg->announce_port < 1) + scfg->announce_port = port; + + if (scfg->announce_port != port) { + fprintf(stderr, "Multiple announce ports!?\n"); + return false; + } + } + + if (scfg->announce_port < 1) + return false; + + break; + + default: + return false; + } + + if (!scfg->pretty_name) { + char *suffix; + + suffix = strrchr(scfg->name, '.'); + if (!suffix || suffix == scfg->name) + return false; + + scfg->pretty_name = strndup(scfg->name, suffix - scfg->name); + if (!scfg->pretty_name) + return false; + } /* FIXME: config, dont reread config if server running, make sure fd is available before this is called */ - /* FIXME: verify correct cfg */ server_dump(scfg); list_for_each_entry(local, &scfg->locals, list) { @@ -315,6 +377,11 @@ server_new(struct cfg *cfg, const char *name) list_init(&scfg->remotes); list_init(&scfg->locals); list_init(&scfg->proxys); + memset(&scfg->mcast_iov, 0, sizeof(scfg->mcast_iov)); + scfg->mcast_iov.iov_base = scfg->mcast_buf; + memset(&scfg->mcast_msg, 0, sizeof(scfg->mcast_msg)); + scfg->mcast_msg.msg_iov = &scfg->mcast_iov; + scfg->mcast_msg.msg_iovlen = 1; list_add(&scfg->list, &cfg->servers); return scfg; diff --git a/server.h b/server.h index d066588..a6936cd 100644 --- a/server.h +++ b/server.h @@ -17,9 +17,16 @@ struct server { struct list_head proxys; bool running; - struct uring_task task; + /* For config files */ char buf[4096]; size_t len; + + /* For announce messages */ + struct iovec mcast_iov; + struct msghdr mcast_msg; + char mcast_buf[4096]; + + struct uring_task task; struct list_head list; }; diff --git a/utils.c b/utils.c index 91e44b3..87ed0fe 100644 --- a/utils.c +++ b/utils.c @@ -7,6 +7,18 @@ #include "main.h" #include "utils.h" +uint16_t sockaddr_port(struct sockaddr_in46 *addr) +{ + switch (addr->storage.ss_family) { + case AF_INET: + return ntohs(addr->in4.sin_port); + case AF_INET6: + return ntohs(addr->in6.sin6_port); + default: + return 0; + } +} + char * sockaddr_to_str(struct sockaddr_in46 *addr, char *buf, size_t buflen) { diff --git a/utils.h b/utils.h index 89bcccc..7110265 100644 --- a/utils.h +++ b/utils.h @@ -95,10 +95,13 @@ struct sockaddr_in46 { struct list_head list; }; -int strtou16_strict(const char *str, uint16_t *result); +uint16_t sockaddr_port(struct sockaddr_in46 *addr); char *sockaddr_to_str(struct sockaddr_in46 *addr, char *buf, size_t buflen); +int strtou16_strict(const char *str, uint16_t *result); + + /* #define _cleanup_(x) __attribute__((cleanup(x))) -- cgit v1.2.3