#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); }