summaryrefslogtreecommitdiff
path: root/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'main.c')
-rw-r--r--main.c284
1 files changed, 284 insertions, 0 deletions
diff --git a/main.c b/main.c
new file mode 100644
index 0000000..70d1b1e
--- /dev/null
+++ b/main.c
@@ -0,0 +1,284 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdbool.h>
+#include <getopt.h>
+#include <sys/signalfd.h>
+#include <sys/eventfd.h>
+#include <signal.h>
+
+#include "main.h"
+#include "uring.h"
+#include "config.h"
+#include "server.h"
+
+int debuglvl = 0;
+
+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);
+
+ free(cfg);
+ exit(EXIT_SUCCESS);
+}
+
+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;
+ uint64_t buf;
+};
+
+static void
+signalfd_free(struct uring_task *task)
+{
+ struct signalfd_ev *sev = container_of(task, struct signalfd_ev, task);
+
+ debug(2, "Freeing signalfd\n");
+ free(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_task_refdump(&cfg->sev->task);
+ uring_refdump(cfg->uev);
+ if (cfg->iev)
+ inotify_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);
+ scfg_stop_monitor_dir(cfg);
+ list_for_each_entry_safe(server, stmp, &cfg->servers, list)
+ server_delete(cfg, server);
+ uring_read(cfg, &sev->task, &sev->buf, sizeof(sev->buf), 0, signalfd_read);
+ }
+}
+
+static int hack_efd = -1;
+
+static void
+hack_handler(int signum)
+{
+ uint64_t val;
+
+ switch (signum) {
+ case SIGINT:
+ fprintf(stderr, "Got a SIGINT\n");
+ val = 1000;
+ 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));
+}
+
+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);
+
+ sfd = eventfd(0, EFD_CLOEXEC);
+ if (sfd < 0)
+ perrordie("eventfd");
+
+ fprintf(stderr, "signalfd init: %i\n", sfd);
+ uring_task_init(&sev->task, "sev", &cfg->task, signalfd_free);
+ uring_task_set_fd(&sev->task, sfd);
+ cfg->sev = sev;
+ hack_efd = sfd;
+ uring_read(cfg, &sev->task, &sev->buf, sizeof(sev->buf), 0, signalfd_read);
+}
+
+int
+main(int argc, char **argv)
+{
+ struct cfg *cfg;
+
+ cfg = cfg_init(argc, argv);
+
+ cfg_read(cfg);
+
+ uring_init(cfg);
+
+ signalfd_init(cfg);
+
+ scfg_monitor_dir(cfg);
+
+ scfg_read_all(cfg);
+
+ uring_event_loop(cfg);
+
+ exit(EXIT_SUCCESS);
+}