1
0
forked from aniani/gmnisrv

Initialize sockets

This commit is contained in:
Drew DeVault 2020-09-23 12:40:28 -04:00
parent 9adc6f34c7
commit 65c2a56c6d
7 changed files with 171 additions and 1 deletions

View File

@ -30,6 +30,12 @@ do
esac
done
case "$(uname)" in
Linux)
CFLAGS="$CFLAGS -DLINUX"
;;
esac
subdir() {
eval ". $srcdir/$1/configure"
}

1
configure vendored
View File

@ -8,6 +8,7 @@ gmnisrv() {
src/escape.c \
src/ini.c \
src/main.c \
src/server.c \
src/url.c
}

View File

@ -15,6 +15,7 @@ struct gmnisrv_host {
};
struct gmnisrv_bind {
char *name;
int family, port;
char addr[sizeof(struct in6_addr)];
struct gmnisrv_bind *next;
@ -27,6 +28,7 @@ struct gmnisrv_config {
};
int load_config(struct gmnisrv_config *conf, const char *path);
void config_finish(struct gmnisrv_config *conf);
struct gmnisrv_host *gmnisrv_config_get_host(
struct gmnisrv_config *conf, const char *hostname);

31
include/server.h Normal file
View File

@ -0,0 +1,31 @@
#ifndef GMNISRV_SERVER
#define GMNISRV_SERVER
#include <poll.h>
#define GEMINI_MAX_URL 1024
struct gmnisrv_client {
char buf[GEMINI_MAX_URL + 2];
size_t bufln;
int sockfd;
int respfd;
};
struct gmisrv_config;
struct gmnisrv_server {
struct gmnisrv_config *conf;
struct pollfd *fds;
nfds_t nfds, fdsz;
size_t nlisten;
struct gmnisrv_client *clients;
size_t nclients, clientsz;
};
int server_init(struct gmnisrv_server *server, struct gmnisrv_config *conf);
void server_run(struct gmnisrv_server *server);
void server_finish(struct gmnisrv_server *server);
#endif

View File

@ -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;
}
}

View File

@ -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;
}

92
src/server.c Normal file
View File

@ -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;
}