summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/config.c26
-rw-r--r--src/main.c14
-rw-r--r--src/server.c92
3 files changed, 131 insertions, 1 deletions
diff --git a/src/config.c b/src/config.c
index 9bc251c..f3172d2 100644
--- a/src/config.c
+++ b/src/config.c
@@ -31,7 +31,9 @@ parse_listen(struct gmnisrv_config *conf, const char *value)
char *port = tok;
struct gmnisrv_bind *bind =
calloc(1, sizeof(struct gmnisrv_bind));
+ assert(bind);
bind->port = 1965;
+ bind->name = strdup(tok);
if (tok[0] == '[') {
bind->family = AF_INET6;
@@ -133,6 +135,7 @@ conf_ini_handler(void *user, const char *section,
struct gmnisrv_host *host = gmnisrv_config_get_host(conf, section);
if (!host) {
host = calloc(1, sizeof(struct gmnisrv_host));
+ assert(host);
host->hostname = strdup(section);
host->next = conf->hosts;
conf->hosts = host;
@@ -194,3 +197,26 @@ load_config(struct gmnisrv_config *conf, const char *path)
return validate_config(conf);
}
+
+void
+config_finish(struct gmnisrv_config *conf)
+{
+ free(conf->tls.store);
+ free(conf->tls.organization);
+ free(conf->tls.email);
+ struct gmnisrv_bind *bind = conf->binds;
+ while (bind) {
+ struct gmnisrv_bind *next = bind->next;
+ free(bind->name);
+ free(bind);
+ bind = next;
+ }
+ struct gmnisrv_host *host = conf->hosts;
+ while (host) {
+ struct gmnisrv_host *next = host->next;
+ free(host->hostname);
+ free(host->root);
+ free(host);
+ host = next;
+ }
+}
diff --git a/src/main.c b/src/main.c
index b865b01..6e64965 100644
--- a/src/main.c
+++ b/src/main.c
@@ -1,6 +1,7 @@
#include <getopt.h>
#include <stdio.h>
#include "config.h"
+#include "server.h"
static void
usage(const char *argv_0)
@@ -36,8 +37,19 @@ main(int argc, char **argv)
int r = load_config(&conf, confpath);
if (r != 0) {
- return r;
+ goto exit_conf;
}
+ struct gmnisrv_server server = {0};
+ r = server_init(&server, &conf);
+ if (r != 0) {
+ goto exit;
+ }
+ server_run(&server);
+
+exit:
+ server_finish(&server);
+exit_conf:
+ config_finish(&conf);
return 0;
}
diff --git a/src/server.c b/src/server.c
new file mode 100644
index 0000000..39c2c07
--- /dev/null
+++ b/src/server.c
@@ -0,0 +1,92 @@
+#include <arpa/inet.h>
+#include <assert.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/socket.h>
+#include "config.h"
+#include "server.h"
+
+int
+server_init(struct gmnisrv_server *server, struct gmnisrv_config *conf)
+{
+ server->conf = conf;
+ for (struct gmnisrv_bind *b = conf->binds; b; b = b->next) {
+ ++server->nlisten;
+ }
+
+ assert(server->nlisten < 1024);
+ server->nfds = server->nlisten;
+ server->fds = calloc(server->nfds, sizeof(struct pollfd));
+ assert(server->fds);
+
+ server->clientsz = 1024 - server->nlisten;
+ server->clients = calloc(server->clientsz, sizeof(struct gmnisrv_client));
+
+ size_t i = 0;
+ for (struct gmnisrv_bind *b = conf->binds; b; b = b->next) {
+ int sockfd = socket(b->family, SOCK_STREAM, 0);
+ if (sockfd < 0) {
+ fprintf(stderr,
+ "Failed to establish socket %s: %s\n",
+ b->name, strerror(errno));
+ return 1;
+ }
+
+ struct sockaddr *addr;
+ size_t addrsz;
+ if (b->family == AF_INET) {
+ struct sockaddr_in in = {0};
+ in.sin_family = AF_INET;
+ memcpy(&in.sin_addr, b->addr, sizeof(b->addr));
+ in.sin_port = htons(b->port);
+ addr = (struct sockaddr *)&in;
+ addrsz = sizeof(in);
+ } else if (b->family == AF_INET6) {
+ struct sockaddr_in6 in = {0};
+ in.sin6_family = AF_INET6;
+ memcpy(&in.sin6_addr, b->addr, sizeof(b->addr));
+ in.sin6_port = htons(b->port);
+ addr = (struct sockaddr *)&in;
+ addrsz = sizeof(in);
+#ifdef LINUX
+ static int t = 1;
+ setsockopt(sockfd, IPPROTO_IPV6,
+ IPV6_V6ONLY, &t, sizeof(t));
+#endif
+ } else {
+ assert(0);
+ }
+
+ int r = bind(sockfd, addr, addrsz);
+ if (r == -1) {
+ fprintf(stderr,
+ "Failed to bind socket %s: %s\n",
+ b->name, strerror(errno));
+ return 1;
+ }
+
+ r = listen(sockfd, 16);
+
+ server->fds[i].fd = sockfd;
+ server->fds[i].events = POLLIN;
+ ++i;
+ }
+
+ return 0;
+}
+
+void
+server_run(struct gmnisrv_server *server)
+{
+ // TODO
+ (void)server;
+}
+
+void
+server_finish(struct gmnisrv_server *server)
+{
+ // TODO
+ (void)server;
+}