summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--announce.c178
-rw-r--r--announce.h14
-rw-r--r--main.c7
-rw-r--r--main.h1
-rw-r--r--meson.build2
-rw-r--r--uring.c14
-rw-r--r--uring.h3
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
diff --git a/main.c b/main.c
index 2385bf8..69d47ae 100644
--- a/main.c
+++ b/main.c
@@ -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);
diff --git a/main.h b/main.h
index 5fafcc2..d327059 100644
--- a/main.h
+++ b/main.h
@@ -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)
diff --git a/uring.c b/uring.c
index 770b8c5..65277ce 100644
--- a/uring.c
+++ b/uring.c
@@ -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);
diff --git a/uring.h b/uring.h
index a851a73..fdabf68 100644
--- a/uring.h
+++ b/uring.h
@@ -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);