summaryrefslogtreecommitdiff
path: root/announce.c
diff options
context:
space:
mode:
authorDavid Härdeman <david@hardeman.nu>2020-06-06 00:05:45 +0200
committerDavid Härdeman <david@hardeman.nu>2020-06-06 00:05:45 +0200
commited8cb35c9ff4547275b03bd93baeff1cda3de76e (patch)
tree8b7f187613c0cab24076bf94d0db3ae3f79618b2 /announce.c
parent8e301216143cb96d39a941a9c5fcb90319ef53c7 (diff)
Add skeleton functionality for announcing servers
Diffstat (limited to 'announce.c')
-rw-r--r--announce.c178
1 files changed, 178 insertions, 0 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);
+}
+