From 24ce5d8cd68537b04687b789500e3b6e9c4564a8 Mon Sep 17 00:00:00 2001 From: Lorenz Stechauner Date: Wed, 9 Dec 2020 22:45:35 +0100 Subject: [PATCH] Implemented Hello World --- run.sh | 7 ++-- src/client.c | 29 +++++++++++++ src/necronda-server.c | 95 ++++++++++++++++++++++++++++++++++++++++++- src/necronda-server.h | 25 ++++++++++++ 4 files changed, 150 insertions(+), 6 deletions(-) create mode 100644 src/necronda-server.h diff --git a/run.sh b/run.sh index a599718..84f5e37 100755 --- a/run.sh +++ b/run.sh @@ -1,7 +1,6 @@ #!/bin/bash echo "-- Building and starting Necronda Server..." make compile && \ - echo -e "-- Successfully finished compiling!\n" && \ - sleep 0.0625 && \ - echo -e "-- Starting Server...\n" && \ - authbind ./bin/necronda-server + echo "-- Successfully finished compiling!" && \ + echo "-- Starting Server..." && \ + ./bin/necronda-server diff --git a/src/client.c b/src/client.c index 720015a..a8290f6 100644 --- a/src/client.c +++ b/src/client.c @@ -5,6 +5,10 @@ * Lorenz Stechauner, 2020-12-03 */ +#include +#include + +#include "necronda-server.h" #include "utils.h" #include "net/http.h" @@ -23,3 +27,28 @@ int client_connection_handler() { // TODO implement client_connection_handler return 0; } + +pid_t client_handler(int socket) { + struct sockaddr_in client_addr; + unsigned int client_addr_len = sizeof(client_addr); + + int client = accept(socket, (struct sockaddr *) &client_addr, &client_addr_len); + if (client == -1) { + fprintf(stderr, ERR_STR "Unable to accept connection: %s" CLR_STR "\n", strerror(errno)); + return -1; + } + + pid_t pid = fork(); + if (pid == 0) { + // child + recv(client, NULL, 0, 0); + char buf[] = "Hello world!\n"; + send(client, buf, strlen(buf), 0); + close(client); + return 0; + } else { + // parent + close(client); + return pid; + } +} diff --git a/src/necronda-server.c b/src/necronda-server.c index af3efc8..020c1a9 100644 --- a/src/necronda-server.c +++ b/src/necronda-server.c @@ -5,14 +5,105 @@ * Lorenz Stechauner, 2020-12-03 */ +#include "necronda-server.h" + #include +#include +#include +#include +#include +#include +#include #include "utils.c" #include "net/http.c" #include "client.c" -int main(int argc, const char* argv[]) { +int main(int argc, const char *argv[]) { + const int YES = 1; + fd_set socket_fds, read_socket_fds; + int max_socket_fd = 0; + int ready_sockets_num = 0; + + const struct sockaddr_in addresses[2] = { + {.sin_family = AF_INET, .sin_addr.s_addr = INADDR_ANY, .sin_port = htons(8080)}, + {.sin_family = AF_INET, .sin_addr.s_addr = INADDR_ANY, .sin_port = htons(4443)} + }; + const struct sockaddr_in6 addresses6[2] = { + {.sin6_family = AF_INET6, .sin6_addr = IN6ADDR_ANY_INIT, .sin6_port = htons(8080)}, + {.sin6_family = AF_INET6, .sin6_addr = IN6ADDR_ANY_INIT, .sin6_port = htons(4443)} + }; + printf("Necronda Web Server\n"); - // TODO implement main + + SOCKETS[0] = socket(AF_INET, SOCK_STREAM, 0); + if (SOCKETS[0] == -1) goto socket_err; + SOCKETS[1] = socket(AF_INET, SOCK_STREAM, 0); + if (SOCKETS[1] == -1) goto socket_err; + SOCKETS[2] = socket(AF_INET6, SOCK_STREAM, 0); + if (SOCKETS[2] == -1) goto socket_err; + SOCKETS[3] = socket(AF_INET6, SOCK_STREAM, 0); + if (SOCKETS[3] == -1) { + socket_err: + fprintf(stderr, ERR_STR "Unable to create socket: %s" CLR_STR "\n", strerror(errno)); + return 1; + } + + for (int i = 0; i < NUM_SOCKETS; i++) { + if (setsockopt(SOCKETS[i], SOL_SOCKET, SO_REUSEADDR, &YES, sizeof(YES)) == -1) { + fprintf(stderr, ERR_STR "Unable to set options for socket %i: %s" CLR_STR "\n", i, strerror(errno)); + return 1; + } + } + + if (bind(SOCKETS[0], (struct sockaddr *) &addresses[0], sizeof(addresses[0])) == -1) goto bind_err; + if (bind(SOCKETS[1], (struct sockaddr *) &addresses[1], sizeof(addresses[1])) == -1) goto bind_err; + if (bind(SOCKETS[2], (struct sockaddr *) &addresses6[0], sizeof(addresses6[0])) == -1) goto bind_err; + if (bind(SOCKETS[3], (struct sockaddr *) &addresses6[1], sizeof(addresses6[1])) == -1) { + bind_err: + fprintf(stderr, ERR_STR "Unable to bind socket to address: %s" CLR_STR "\n", strerror(errno)); + return 1; + } + + // TODO implement TLS server side handshake + + for (int i = 0; i < NUM_SOCKETS; i++) { + if (listen(SOCKETS[i], LISTEN_BACKLOG) == -1) { + fprintf(stderr, ERR_STR "Unable to listen on socket %i: %s" CLR_STR "\n", i, strerror(errno)); + return 1; + } + } + + FD_ZERO(&socket_fds); + for (int i = 0; i < NUM_SOCKETS; i++) { + FD_SET(SOCKETS[i], &socket_fds); + if (SOCKETS[i] > max_socket_fd) { + max_socket_fd = SOCKETS[i]; + } + } + + while (1) { + read_socket_fds = socket_fds; + ready_sockets_num = select(max_socket_fd, &read_socket_fds, NULL, NULL, NULL); + if (ready_sockets_num == -1) { + fprintf(stderr, ERR_STR "Unable to select sockets: %s" CLR_STR "\n", strerror(errno)); + return 1; + } + + for (int i = 0; i < NUM_SOCKETS; i++) { + if (FD_ISSET(SOCKETS[i], &read_socket_fds)) { + pid_t child = client_handler(SOCKETS[i]); + if (child == 0) { + return 0; + } else if (child > 0) { + for (int j = 0; j < MAX_CHILDREN; j++) { + if (CHILDREN[j] == 0) { + CHILDREN[j] = child; + } + } + } + } + } + } } diff --git a/src/necronda-server.h b/src/necronda-server.h new file mode 100644 index 0000000..ebec4e0 --- /dev/null +++ b/src/necronda-server.h @@ -0,0 +1,25 @@ +/** + * Necronda Web Server + * Main executable (header file) + * src/necronda-server.c + * Lorenz Stechauner, 2020-12-03 + */ + +#ifndef NECRONDA_SERVER_NECRONDA_SERVER_H +#define NECRONDA_SERVER_NECRONDA_SERVER_H + +#include + + +#define NUM_SOCKETS 4 +#define MAX_CHILDREN 1024 +#define LISTEN_BACKLOG 16 + +#define ERR_STR "\x1B[1;31m" +#define CLR_STR "\x1B[0m" + +int SOCKETS[NUM_SOCKETS]; +pid_t CHILDREN[MAX_CHILDREN]; + + +#endif //NECRONDA_SERVER_NECRONDA_SERVER_H