From 42b8aee4bd081d4023f0da4545535c20702f0456 Mon Sep 17 00:00:00 2001 From: Lorenz Stechauner Date: Thu, 10 Dec 2020 20:55:33 +0100 Subject: [PATCH] Simple echo client --- src/client.c | 71 +++++++++++++++++++++++++++++++++---------- src/necronda-server.c | 41 ++++++++++++------------- src/necronda-server.h | 7 ++++- 3 files changed, 81 insertions(+), 38 deletions(-) diff --git a/src/client.c b/src/client.c index a8290f6..d14a3a3 100644 --- a/src/client.c +++ b/src/client.c @@ -7,12 +7,25 @@ #include #include +#include #include "necronda-server.h" #include "utils.h" #include "net/http.h" +#define out_1(fmt) fprintf(parent_stdout, "%s" fmt "\n", log_base_prefix) +#define out_2(fmt, args...) fprintf(parent_stdout, "%s" fmt "\n", log_base_prefix, args) + +#define out_x(x, arg1, arg2, arg3, arg4, arg5, arg6, arg7, FUNC, ...) FUNC + +#define print(...) out_x(, ##__VA_ARGS__, out_2(__VA_ARGS__), out_2(__VA_ARGS__), out_2(__VA_ARGS__), \ + out_2(__VA_ARGS__), out_2(__VA_ARGS__), out_2(__VA_ARGS__), out_1(__VA_ARGS__)) + + +char *client_addr_str, *client_addr_str_ptr, *server_addr_str, *server_addr_str_ptr, *log_base_prefix, *log_req_prefix; + + int client_websocket_handler() { // TODO implement client_websocket_handler return 0; @@ -23,32 +36,58 @@ int client_request_handler() { return 0; } -int client_connection_handler() { - // TODO implement client_connection_handler +int client_connection_handler(int client) { + char buf[256]; + print("Connection accepted from %s (%s) [%s]", client_addr_str, client_addr_str, "N/A"); + + sprintf(buf, "Hello World!\nYour address is: %s\n", client_addr_str); + send(client, buf, strlen(buf), 0); + close(client); + + print("Connection closed"); return 0; } -pid_t client_handler(int socket) { - struct sockaddr_in client_addr; +int client_handler(int socket, long client_num) { + struct sockaddr_in6 client_addr, *server_addr; + struct sockaddr_storage server_addr_storage; unsigned int client_addr_len = sizeof(client_addr); + char *color_table[] = {"\x1B[31m", "\x1B[32m", "\x1B[33m", "\x1B[34m", "\x1B[35m", "\x1B[36m"}; + 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)); + fprintf(parent_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; + client_addr_str_ptr = malloc(INET6_ADDRSTRLEN); + inet_ntop(client_addr.sin6_family, (void *) &client_addr.sin6_addr, client_addr_str_ptr, INET6_ADDRSTRLEN); + if (strncmp(client_addr_str_ptr, "::ffff:", 7) == 0) { + client_addr_str = client_addr_str_ptr + 7; } else { - // parent - close(client); - return pid; + client_addr_str = client_addr_str_ptr; } + + socklen_t len = sizeof(server_addr_storage); + getsockname(client, (struct sockaddr *) &server_addr_storage, &len); + server_addr = (struct sockaddr_in6 *) &server_addr_storage; + server_addr_str_ptr = malloc(INET6_ADDRSTRLEN); + inet_ntop(server_addr->sin6_family, (void *) &server_addr->sin6_addr, server_addr_str_ptr, INET6_ADDRSTRLEN); + if (strncmp(server_addr_str_ptr, "::ffff:", 7) == 0) { + server_addr_str = server_addr_str_ptr + 7; + } else { + server_addr_str = server_addr_str_ptr; + } + + log_base_prefix = malloc(256); + sprintf(log_base_prefix, "[%24s][%s%4i%s]%s[%*s][%5i]%s ", + server_addr_str, R_STR, ntohs(server_addr->sin6_port), CLR_STR, + color_table[client_num % 6], INET_ADDRSTRLEN, client_addr_str, ntohs(client_addr.sin6_port), CLR_STR); + + int ret = client_connection_handler(client); + free(client_addr_str_ptr); + free(server_addr_str_ptr); + free(log_base_prefix); + return ret; } diff --git a/src/necronda-server.c b/src/necronda-server.c index 020c1a9..4ce0ace 100644 --- a/src/necronda-server.c +++ b/src/necronda-server.c @@ -25,26 +25,22 @@ int main(int argc, const char *argv[]) { fd_set socket_fds, read_socket_fds; int max_socket_fd = 0; int ready_sockets_num = 0; + long client_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] = { + parent_stdout = stdout; + parent_stderr = stderr; + + const struct sockaddr_in6 addresses[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"); - SOCKETS[0] = socket(AF_INET, SOCK_STREAM, 0); + SOCKETS[0] = socket(AF_INET6, 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) { + SOCKETS[1] = socket(AF_INET6, SOCK_STREAM, 0); + if (SOCKETS[1] == -1) { socket_err: fprintf(stderr, ERR_STR "Unable to create socket: %s" CLR_STR "\n", strerror(errno)); return 1; @@ -58,9 +54,7 @@ int main(int argc, const char *argv[]) { } 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) { + if (bind(SOCKETS[1], (struct sockaddr *) &addresses[1], sizeof(addresses[1])) == -1) { bind_err: fprintf(stderr, ERR_STR "Unable to bind socket to address: %s" CLR_STR "\n", strerror(errno)); return 1; @@ -85,7 +79,7 @@ int main(int argc, const char *argv[]) { while (1) { read_socket_fds = socket_fds; - ready_sockets_num = select(max_socket_fd, &read_socket_fds, NULL, NULL, NULL); + ready_sockets_num = select(max_socket_fd + 1, &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; @@ -93,15 +87,20 @@ int main(int argc, const char *argv[]) { 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) { + pid_t pid = fork(); + if (pid == 0) { + // child + return client_handler(SOCKETS[i], client_num); + } else if (pid > 0) { + // parent + client_num++; for (int j = 0; j < MAX_CHILDREN; j++) { if (CHILDREN[j] == 0) { - CHILDREN[j] = child; + CHILDREN[j] = pid; } } + } else { + fprintf(stderr, ERR_STR "Unable to create child process: %s" CLR_STR "\n", strerror(errno)); } } } diff --git a/src/necronda-server.h b/src/necronda-server.h index ebec4e0..d6ccea8 100644 --- a/src/necronda-server.h +++ b/src/necronda-server.h @@ -9,17 +9,22 @@ #define NECRONDA_SERVER_NECRONDA_SERVER_H #include +#include -#define NUM_SOCKETS 4 +#define NUM_SOCKETS 2 #define MAX_CHILDREN 1024 #define LISTEN_BACKLOG 16 #define ERR_STR "\x1B[1;31m" #define CLR_STR "\x1B[0m" +#define R_STR "\x1B[31m" +#define G_STR "\x1B[32m" int SOCKETS[NUM_SOCKETS]; pid_t CHILDREN[MAX_CHILDREN]; +FILE *parent_stdout, *parent_stderr; + #endif //NECRONDA_SERVER_NECRONDA_SERVER_H