#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "main.h" #include "uring.h" #include "config.h" #include "server.h" #include "cfgdir.h" #include "announce.h" #include "systemd.h" int debuglvl = 0; bool exiting = false; struct cfg *cfghack = NULL; void debug(unsigned lvl, const char *fmt, ...) { va_list ap; if (lvl > debuglvl) return; va_start(ap, fmt); vfprintf(stdout, fmt, ap); va_end(ap); } #define info(...) fprintf(stderr, __VA_ARGS__) #define error(...) fprintf(stderr, __VA_ARGS__) __attribute__((noreturn)) void die(const char *fmt, ...) { va_list ap; va_start(ap, fmt); vfprintf(stderr, fmt, ap); va_end(ap); exit(EXIT_FAILURE); }; #define perrordie(msg) die("%s: %m\n", msg) static void cfg_free(struct uring_task *task) { struct cfg *cfg = container_of(task, struct cfg, task); fprintf(stderr, "%s: called\n", __func__); systemd_delete(cfg); xfree(cfg); fprintf(stderr, "All resources free, exiting\n"); exiting = true; } static void cfg_read(struct cfg *cfg) { FILE *cfgfile; cfgfile = fopen("./mcproxy.conf", "r"); if (!cfgfile) { if (errno == ENOENT) return; else perrordie("fopen"); } printf("Opened config file\n"); fclose(cfgfile); } static struct cfg * cfg_init(int argc, char **argv) { struct cfg *cfg; int c; cfg = zmalloc(sizeof(*cfg)); if (!cfg) { perror("malloc"); return NULL; } uring_task_init(&cfg->task, "cfg", NULL, cfg_free); list_init(&cfg->servers); while (true) { int option_index = 0; static struct option long_options[] = { { "homedir", required_argument, 0, 'h' }, { "debug", no_argument, 0, 'd' }, { 0, 0, 0, 0 } }; c = getopt_long(argc, argv, ":h:d", long_options, &option_index); if (c == -1) break; switch (c) { case 'h': cfg->homedir = optarg; break; case 'd': debuglvl++; break; default: die("Invalid arguments\n"); } } if (optind < argc) die("Invalid arguments\n"); if (!cfg->homedir) cfg->homedir = "/home/david/intest"; printf("Homedir is %s\n", cfg->homedir); if (chdir(cfg->homedir)) perrordie("chdir"); return cfg; } struct signalfd_ev { struct uring_task task; //struct signalfd_siginfo buf; struct cfg *cfg; uint64_t buf; }; static void signalfd_free(struct uring_task *task) { struct signalfd_ev *sev = container_of(task, struct signalfd_ev, task); fprintf(stderr, "%s: called\n", __func__); sev->cfg->sev = NULL; xfree(sev); } static void dump_tree(struct cfg *cfg) { struct server *server; fprintf(stderr, "\n\n\n\n"); fprintf(stderr, "Dumping Tree\n"); fprintf(stderr, "============\n"); uring_task_refdump(&cfg->task); uring_refdump(cfg->uev); if (cfg->sev) uring_task_refdump(&cfg->sev->task); announce_refdump(cfg->aev); if (cfg->iev) cfgdir_refdump(cfg->iev); list_for_each_entry(server, &cfg->servers, list) server_refdump(server); fprintf(stderr, "============\n"); fprintf(stderr, "\n\n\n\n"); } static void signalfd_read(struct cfg *cfg, struct uring_task *task, int res) { struct signalfd_ev *sev = container_of(task, struct signalfd_ev, task); struct server *server, *stmp; static int count = 0; count++; if (count > 5) exit(EXIT_FAILURE); if (res != sizeof(sev->buf)) die("Error in signalfd (%i)\n", res); if (sev->buf < 1000) { fprintf(stderr, "Got a signal to quit\n"); exit(EXIT_SUCCESS); } 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); fprintf(stderr, "%s: putting sev task 0x%p\n", __func__, &sev->task); uring_task_put(cfg, &sev->task); //uring_read(cfg, &sev->task, &sev->buf, sizeof(sev->buf), signalfd_read); } } static int hack_efd = -1; static void hack_handler(int signum) { uint64_t val; static int count = 0; switch (signum) { case SIGINT: fprintf(stderr, "Got a SIGINT\n"); val = 1000; if (count > 3) dump_tree(cfghack); break; case SIGHUP: fprintf(stderr, "Got a SIGHUP\n"); val = 1000; break; case SIGTERM: fprintf(stderr, "Got a SIGTERM\n"); val = 1; break; default: fprintf(stderr, "Got an unknown sig (%i)\n", signum); val = 1; break; } write(hack_efd, &val, sizeof(val)); count++; } static void signalfd_init(struct cfg *cfg) { int sfd; //sigset_t mask; struct signalfd_ev *sev; sev = zmalloc(sizeof(*sev)); if (!sev) perrordie("malloc"); /* sigfillset(&mask); if (sigprocmask(SIG_BLOCK, &mask, NULL) < 0) perrordie("sigprocmask"); sfd = signalfd(-1, &mask, SFD_CLOEXEC); if (sfd < 0) perrordie("signalfd"); */ struct sigaction action; sigfillset(&action.sa_mask); action.sa_handler = hack_handler; action.sa_flags = 0; sigaction(SIGINT, &action, NULL); sigaction(SIGHUP, &action, NULL); sigaction(SIGTERM, &action, NULL); action.sa_handler = SIG_IGN; sigaction(SIGPIPE, &action, NULL); sfd = eventfd(0, EFD_CLOEXEC); if (sfd < 0) perrordie("eventfd"); fprintf(stderr, "signalfd init: %i\n", sfd); uring_task_init(&sev->task, "sev", uring_parent(cfg), signalfd_free); uring_task_set_fd(&sev->task, sfd); cfg->sev = sev; sev->cfg = cfg; hack_efd = sfd; uring_read(cfg, &sev->task, &sev->buf, sizeof(sev->buf), signalfd_read); } int main(int argc, char **argv) { struct cfg *cfg; cfg = cfg_init(argc, argv); cfghack = cfg; cfg_read(cfg); uring_init(cfg); signalfd_init(cfg); cfgdir_init(cfg); announce_init(cfg); announce_start(cfg->aev); uring_task_put(cfg, &cfg->task); uring_event_loop(cfg); fprintf(stderr, "Event loop exited\n"); debug_resource_usage(); exit(EXIT_SUCCESS); }