From ed8cb35c9ff4547275b03bd93baeff1cda3de76e Mon Sep 17 00:00:00 2001 From: David Härdeman Date: Sat, 6 Jun 2020 00:05:45 +0200 Subject: Add skeleton functionality for announcing servers --- announce.c | 178 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 178 insertions(+) create mode 100644 announce.c (limited to 'announce.c') 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 +#include +#include +#include +#include +#include + +#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); +} + -- cgit v1.2.3