diff options
| author | Syndamia <kamen@syndamia.com> | 2023-12-08 17:55:57 +0200 |
|---|---|---|
| committer | Syndamia <kamen@syndamia.com> | 2023-12-08 17:55:57 +0200 |
| commit | 7ad507e3ec8efb0cdbc32474ea7c1ccbf031b960 (patch) | |
| tree | 712dd3f5acf72ba621bd3eeed282467e2e258636 | |
| parent | de1e66d00a5469f02eb7323553b3b087e6255980 (diff) | |
| download | pico-web-7ad507e3ec8efb0cdbc32474ea7c1ccbf031b960.tar pico-web-7ad507e3ec8efb0cdbc32474ea7c1ccbf031b960.tar.gz pico-web-7ad507e3ec8efb0cdbc32474ea7c1ccbf031b960.zip | |
[server] Moved server-cli to it's own file and reorganized server and server-cli
| -rw-r--r-- | Makefile | 2 | ||||
| -rw-r--r-- | server-cli.c | 46 | ||||
| -rw-r--r-- | server-cli.h | 8 | ||||
| -rw-r--r-- | server.c | 220 | ||||
| -rw-r--r-- | util.c | 4 | ||||
| -rw-r--r-- | util.h | 3 |
6 files changed, 159 insertions, 124 deletions
@@ -3,7 +3,7 @@ all: server browser .PHONY: server server: - gcc -g -o server -I. sds/sds.c util.c server.c server-connection.c + gcc -g -o server -I. sds/sds.c util.c server.c server-connection.c server-cli.c .PHONY: browser browser: diff --git a/server-cli.c b/server-cli.c new file mode 100644 index 0000000..82c9501 --- /dev/null +++ b/server-cli.c @@ -0,0 +1,46 @@ +#include <util.h> +#include <server-connection.h> +#include <stdio.h> +#include <signal.h> +#include <unistd.h> + +#define MAX_LEN_COMMAND 16 +#define COMMAND_FORMAT ": %16s" + +void handleCLI(sds **vhosts, int vhostsc) { + // Get a line + char line[256]; + fgets(line, 256, stdin); + + // Get command name and it's arguments + // Currently no command takes arguments + char name[MAX_LEN_COMMAND+1]; + int argsAssigned = sscanf(line, COMMAND_FORMAT, name); + + while (name[0] != 'q' && name[0] != 'e' && !streq(name, "quit") && !streq(name, "exit")) { + if (argsAssigned < 1) { + printf("Bad command syntax!\n"); + } + else if (streq(name, "vhosts")) { + for (int i = 0; i < vhostsc; i++) { + printf("Name: \"%s\" Root dir: \"%s\" Error file: \"%s\"\n", + vhosts[i][vh_user], + vhosts[i][vh_path], + vhosts[i][vh_error]); + } + } + else if (streq(name, "help")) { + printf("help\tPrints this message\nvhosts\tPrints all registered virtual hosts\n"); + } + else { + printf("Unknown command %s!\n", name); + } + + // Get line and divided it into command name and arguments + fgets(line, 256, stdin); + argsAssigned = sscanf(line, COMMAND_FORMAT, name); + } + + printf("Exiting...\n"); + kill(getppid(), SIGTERM); +} diff --git a/server-cli.h b/server-cli.h new file mode 100644 index 0000000..b5b5875 --- /dev/null +++ b/server-cli.h @@ -0,0 +1,8 @@ +#ifndef H_SERVER_CLI +#define H_SERVER_CLI + +#include <sds/sds.h> + +void handleCLI(sds **vhosts, int vhostsc); + +#endif @@ -1,7 +1,5 @@ /* The server recieves connections and passes files to the clients */ -#include <server-connection.h> - #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> @@ -19,18 +17,39 @@ #include <sds/sds.h> #include <util.h> -#define MAX_LEN_COMMAND 16 -#define COMMAND_FORMAT ": %16s" +#include <server-connection.h> +#include <server-cli.h> -void freeVhosts(sds **vhosts, int argc) { - for (int i = 1; i < argc; i++) { - sdsfreesplitres(vhosts[i-1], 3); - } - free(vhosts); +int createCommunicationSocket(const char* ip, const char* port) { + int fd_socket = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0); + herr(fd_socket, "socket"); + + int aton_status = 0; + struct sockaddr_in sa_socket = { + .sin_family = AF_INET, + .sin_port = atop(port), + .sin_addr = aton(ip, &aton_status), + }; + herr(aton_status, "inet_aton"); + + // Reuse address when in TIME_WAIT state, after listening socket was closed + // https://stackoverflow.com/a/10651048/12036073 + // https://superuser.com/questions/173535/what-are-close-wait-and-time-wait-states#comment951880_173543 + int true = 1; + herr(setsockopt(fd_socket, SOL_SOCKET, SO_REUSEADDR, &true, sizeof(int)), "setsockopt"); + + herr(bind(fd_socket, (struct sockaddr*)&sa_socket, sizeof(struct sockaddr_in)), "bind"); + + herr(listen(fd_socket, 50), "listen"); + + return fd_socket; } -int streq(const char* first, const char* second) { - return strcmp(first, second) == 0; +void freeVhosts(sds **vhosts, int vhostsc) { + for (int i = 1; i < vhostsc; i++) { + sdsfreesplitres(vhosts[i], 3); + } + free(vhosts); } int acceptConnections = 1; @@ -52,135 +71,92 @@ int main(int argc, char* argv[]) { /* * Create socket for accepting connections */ - int fd_socket; - herr(fd_socket = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0), "socket"); - - struct sockaddr_in sa_socket = { - .sin_family = AF_INET, - .sin_port = inet_atop("8080"), - }; - herr(inet_aton("127.0.0.1", &sa_socket.sin_addr.s_addr), "inet_aton"); - - // Reuse address when in TIME_WAIT state, after listening socket was closed - // https://stackoverflow.com/a/10651048/12036073 - // https://superuser.com/questions/173535/what-are-close-wait-and-time-wait-states#comment951880_173543 - int true = 1; - herr(setsockopt(fd_socket, SOL_SOCKET, SO_REUSEADDR, &true, sizeof(int)), "setsockopt"); - - herr(bind(fd_socket, (struct sockaddr*)&sa_socket, sizeof(struct sockaddr_in)), "bind"); - - herr(listen(fd_socket, 50), "listen"); + int fd_socket = createCommunicationSocket("127.0.0.1", "8080"); printf("Listening on %s:%s\n", "127.0.0.1", "8080"); /* - * Accept connection on the socket + * Server command-line interface */ - int pid_connections = fork(); - if (pid_connections == 0) { - // Client address - struct sockaddr_in sa_client = { - .sin_family = AF_INET, - .sin_port = 0, - .sin_addr.s_addr = 0, - }; - socklen_t sa_client_size = sizeof(struct sockaddr_in); - - // Data for pselect - fd_set rfds; - struct timespec tv = { - .tv_sec = 0, - .tv_nsec = 100000, - }; - - int fd_client; - int count = 0; - int pselectStat = 0; - - // Effecitvely stops the cycle on SIGTERM - signal(SIGTERM, handler_refuseConnections); - - while (acceptConnections) { - /* Check if fd_socket has something we can read */ - FD_ZERO(&rfds); - FD_SET(fd_socket, &rfds); - - herrc(pselect(fd_socket + 1, &rfds, NULL, NULL, &tv, NULL), "pselect"); - if (!FD_ISSET(fd_socket, &rfds)) continue; - - /* If so, accept the connection and pass execution to the "main" logic */ - fd_client = accept(fd_socket, (struct sockaddr*)&sa_client, &sa_client_size); - herrc(fd_client, "accept"); - if (fd_client < 0) continue; - - char* strAddr = inet_ntoa(sa_client.sin_addr); - count++; - - int fp = fork(); - if (fp == 0) { - close(fd_socket); - on_connection(strAddr, fd_client, vhosts, argc - 1); - close(fd_client); - freeVhosts(vhosts, argc); - return 0; - } - close(fd_client); - } - - while(wait(NULL) > 0); - freeVhosts(vhosts, argc); + int pid_cli = fork(); + if (pid_cli == 0) { close(fd_socket); - + handleCLI(vhosts, argc-1); + freeVhosts(vhosts, argc); + //while(wait(NULL) > 0); return 0; } /* - * Server command-line interface + * Define variables */ - close(fd_socket); + // Client address + struct sockaddr_in sa_client = { + .sin_family = AF_INET, + .sin_port = 0, + .sin_addr.s_addr = 0, + }; + socklen_t sa_client_size = sizeof(struct sockaddr_in); - // Get a line - char line[256]; - fgets(line, 256, stdin); + int fd_client; + int count = 0; + int pselectStat = 0; - // Get command name and it's arguments - // Currently no command takes arguments - char name[MAX_LEN_COMMAND+1]; - int argsAssigned = sscanf(line, COMMAND_FORMAT, name); + /* + * Handle connection requests + */ - while (name[0] != 'q' && name[0] != 'e' && !streq(name, "quit") && !streq(name, "exit")) { - if (argsAssigned < 1) { - printf("Bad command syntax!\n"); - } - else if (streq(name, "vhosts")) { - for (int i = 1; i < argc; i++) { - printf("Name: \"%s\" Root dir: \"%s\" Error file: \"%s\"\n", - vhosts[i-1][vh_user], - vhosts[i-1][vh_path], - vhosts[i-1][vh_error]); - } - } - else if (streq(name, "help")) { - printf("help\tPrints this message\nvhosts\tPrints all registered virtual hosts\n"); - } - else { - printf("Unknown command %s!\n", name); - } + // Data for pselect + fd_set rfds; + struct timespec tv = { + /* How long should we block (wait) for fd_socket to have a request */ + .tv_sec = 0, + .tv_nsec = 100000, + }; - // Get line and divided it into command name and arguments - fgets(line, 256, stdin); - argsAssigned = sscanf(line, COMMAND_FORMAT, name); - } + // Stop accepting connections on SIGTERM + signal(SIGTERM, handler_refuseConnections); - /* - * Upon termination - */ + while (acceptConnections) { + /* + * Check if fd_socket has something we can read + */ - printf("Exiting...\n"); - kill(pid_connections, SIGTERM); - while(wait(NULL) > 0); + FD_ZERO(&rfds); + FD_SET(fd_socket, &rfds); + + herrc(pselect(fd_socket + 1, &rfds, NULL, NULL, &tv, NULL), "pselect"); + if (!FD_ISSET(fd_socket, &rfds)) continue; + + /* + * Accept the connection + */ + + fd_client = accept(fd_socket, (struct sockaddr*)&sa_client, &sa_client_size); + herrc(fd_client, "accept"); + if (fd_client < 0) continue; - freeVhosts(vhosts, argc); + char* strAddr = inet_ntoa(sa_client.sin_addr); + count++; + + /* + * Logic when connected with client + */ + + int fp = fork(); + if (fp == 0) { + close(fd_socket); + on_connection(strAddr, fd_client, vhosts, argc - 1); + close(fd_client); + freeVhosts(vhosts, argc); + return 0; + } + close(fd_client); + } + + while(wait(NULL) > 0); + freeVhosts(vhosts, argc - 1); + close(fd_socket); } @@ -147,3 +147,7 @@ int digits(int num) { // 2147483647 (2^31-1) is max value of int return 10; } + +int streq(const char* first, const char* second) { + return strcmp(first, second) == 0; +} @@ -19,7 +19,8 @@ sds gsub(sds str, const regex_t* regex, const char* repl); sds gsub_getm(sds str, const regex_t *regex, const char* repl, int* *matches, int *matchesCount); /* Other */ -int digits(int num); #define clear_arr(arr) memset(arr, 0, sizeof(arr)/sizeof(*arr)) +int digits(int num); +int streq(const char* first, const char* second); #endif |
