diff options
-rw-r--r-- | announce.c | 178 | ||||
-rw-r--r-- | announce.h | 14 | ||||
-rw-r--r-- | main.c | 7 | ||||
-rw-r--r-- | main.h | 1 | ||||
-rw-r--r-- | meson.build | 2 | ||||
-rw-r--r-- | uring.c | 14 | ||||
-rw-r--r-- | uring.h | 3 |
7 files changed, 218 insertions, 1 deletions
diff --git a/announce.c b/announce.c new file mode 100644 index 0000000..8194f1c --- /dev/null +++ b/announce.c @@ -0,0 +1,178 @@ +#include <inttypes.h> +#include <sys/timerfd.h> +#include <sys/socket.h> +#include <netinet/ip.h> +#include <arpa/inet.h> +#include <string.h> + +#include "main.h" +#include "uring.h" +#include "config.h" +#include "announce.h" + +struct announce { + uint64_t value; + struct uring_task task; + struct uring_task mcast_task; +}; + +static void +mcast_free(struct uring_task *task) +{ + struct announce *aev = container_of(task, struct announce, mcast_task); + + fprintf(stderr, "%s: called with task 0x%p and aev 0x%p\n", __func__, task, aev); +} + +static void +mcast_sent(struct cfg *cfg, struct uring_task *task, int res) +{ + fprintf(stderr, "%s: result %i\n", __func__, res); +} + +static void +mcast_send(struct cfg *cfg, struct announce *aev) +{ + 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) + }; + + 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); +} + +static void +announce_cb(struct cfg *cfg, struct uring_task *task, int res) +{ + struct announce *aev = container_of(task, struct announce, task); + + 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 != sizeof(aev->value)) + perrordie("timerfd_read"); + + fprintf(stderr, "%s: called with value %" PRIu64 "\n", __func__, aev->value); + mcast_send(cfg, aev); + uring_read(cfg, &aev->task, &aev->value, sizeof(aev->value), 0, announce_cb); +} + +static void +announce_free(struct uring_task *task) +{ + struct announce *aev = container_of(task, struct announce, task); + + fprintf(stderr, "%s: called with task 0x%p and aev 0x%p\n", __func__, task, aev); +} + +void +announce_refdump(struct announce *aev) +{ + if (!aev) + return; + + uring_task_refdump(&aev->task); + uring_task_refdump(&aev->mcast_task); +} + +void +announce_delete(struct cfg *cfg) +{ + if (!cfg->aev) { + fprintf(stderr, "%s called with no announce!\n", __func__); + return; + } + + fprintf(stderr, "%s called, closing fd %i\n", __func__, cfg->aev->task.fd); + uring_cancel(cfg, &cfg->aev->task); + cfg->aev = NULL; +} + +void +announce_stop(struct announce *aev) +{ + struct itimerspec tspec = { + .it_interval = { + .tv_sec = 0, + .tv_nsec = 0 + }, + .it_value = { + .tv_sec = 0, + .tv_nsec = 0 + } + }; + + if (timerfd_settime(aev->task.fd, 0, &tspec, NULL) != 0) + perrordie("timerfd_settime"); +} + +void +announce_start(struct announce *aev) +{ + struct itimerspec tspec = { + .it_interval = { + .tv_sec = 3, + .tv_nsec = 0 + }, + .it_value = { + .tv_sec = 3, + .tv_nsec = 0 + } + }; + + if (timerfd_settime(aev->task.fd, 0, &tspec, NULL) != 0) + perrordie("timerfd_settime"); +} + +void +announce_init(struct cfg *cfg) +{ + struct announce *aev; + int afd; + int sfd; + + aev = zmalloc(sizeof(*aev)); + if (!aev) + perrordie("malloc"); + + afd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC); + if (afd < 0) + perrordie("timerfd_create"); + + sfd = socket(AF_INET, SOCK_DGRAM, 0); + if (sfd < 0) + perrordie("socket"); + + uring_task_init(&aev->task, "aev", &cfg->task, announce_free); + uring_task_set_fd(&aev->task, afd); + + uring_task_init(&aev->mcast_task, "aev_mcast", &aev->task, mcast_free); + uring_task_set_fd(&aev->mcast_task, sfd); + + cfg->aev = aev; + uring_read(cfg, &aev->task, &aev->value, sizeof(aev->value), 0, announce_cb); +} + diff --git a/announce.h b/announce.h new file mode 100644 index 0000000..6f805f1 --- /dev/null +++ b/announce.h @@ -0,0 +1,14 @@ +#ifndef fooannouncehfoo +#define fooannouncehfoo + +void announce_refdump(struct announce *aev); + +void announce_delete(struct cfg *cfg); + +void announce_stop(struct announce *aev); + +void announce_start(struct announce *aev); + +void announce_init(struct cfg *cfg); + +#endif @@ -18,6 +18,7 @@ #include "config.h" #include "server.h" #include "cfgdir.h" +#include "announce.h" int debuglvl = 0; @@ -155,6 +156,7 @@ dump_tree(struct cfg *cfg) fprintf(stderr, "============\n"); uring_task_refdump(&cfg->task); uring_task_refdump(&cfg->sev->task); + announce_refdump(cfg->aev); uring_refdump(cfg->uev); if (cfg->iev) cfgdir_refdump(cfg->iev); @@ -184,6 +186,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); + announce_delete(cfg); cfgdir_delete(cfg); list_for_each_entry_safe(server, stmp, &cfg->servers, list) server_delete(cfg, server); @@ -280,6 +283,10 @@ main(int argc, char **argv) cfgdir_init(cfg); + announce_init(cfg); + + announce_start(cfg->aev); + uring_event_loop(cfg); exit(EXIT_SUCCESS); @@ -38,6 +38,7 @@ struct cfg { struct uring_ev *uev; struct inotify_ev *iev; struct signalfd_ev *sev; + struct announce *aev; struct uring_task task; struct list_head servers; }; diff --git a/meson.build b/meson.build index 4c7fb08..051cdd2 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', 'proxy.c', 'cfgdir.c', 'config.c', 'utils.c'], + ['main.c', 'uring.c', 'server.c', 'proxy.c', 'announce.c', 'cfgdir.c', 'config.c', 'utils.c'], dependencies: uring) @@ -191,6 +191,20 @@ uring_openat(struct cfg *cfg, struct uring_task *task, const char *path, callbac } void +uring_sendmsg(struct cfg *cfg, struct uring_task *task, struct msghdr *msg, callback_t callback) +{ + struct io_uring_sqe *sqe = io_uring_get_sqe(&cfg->uev->uring); + + if (!sqe) + perrordie("io_uring_sqe"); + + uring_task_get(cfg, task); + task->callback = callback; + io_uring_prep_sendmsg(sqe, task->fd, msg, 0); + io_uring_sqe_set_data(sqe, task); +} + +void uring_connect(struct cfg *cfg, struct uring_task *task, struct sockaddr_in46 *addr, callback_t callback) { struct io_uring_sqe *sqe = io_uring_get_sqe(&cfg->uev->uring); @@ -27,6 +27,9 @@ void uring_read(struct cfg *cfg, struct uring_task *task, void *buf, void uring_openat(struct cfg *cfg, struct uring_task *task, const char *path, callback_t callback); +void uring_sendmsg(struct cfg *cfg, struct uring_task *task, struct msghdr *msg, + callback_t callback); + void uring_connect(struct cfg *cfg, struct uring_task *task, struct sockaddr_in46 *addr, callback_t callback); |