From 8df182e6d1eaa9a0fd6323b9b6c22f118b28acd4 Mon Sep 17 00:00:00 2001 From: root Date: Tue, 5 Feb 2019 03:22:39 +0000 Subject: initial --- server.c | 189 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 189 insertions(+) create mode 100644 server.c (limited to 'server.c') diff --git a/server.c b/server.c new file mode 100644 index 0000000..4da1cc1 --- /dev/null +++ b/server.c @@ -0,0 +1,189 @@ +/* + qotdserver +Copyright (C) 2019 Richard Knight + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . + + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "qotdserver.h" +#include "logger.h" + +const char *port = "17"; + +struct workerArgs +{ + int socket; +}; + +void *accept_clients(void *args); +void *service_single_client(void *args); + +int serve() +{ + pthread_t server_thread; + sigset_t new; + sigemptyset (&new); + sigaddset(&new, SIGPIPE); + if (pthread_sigmask(SIG_BLOCK, &new, NULL) != 0) + { + write_log("Unable to mask SIGPIPE"); + raise(SIGTERM); + } + + if (pthread_create(&server_thread, NULL, accept_clients, NULL) < 0) + { + write_log("Could not create server thread"); + raise(SIGTERM); + } + + pthread_join(server_thread, NULL); + pthread_exit(NULL); +} + + +void *accept_clients(void *args) +{ + int serverSocket; + int clientSocket; + pthread_t worker_thread; + struct addrinfo hints, *res, *p; + struct sockaddr_storage *clientAddr; + socklen_t sinSize = sizeof(struct sockaddr_storage); + struct workerArgs *wa; + int yes = 1; + + memset(&hints, 0, sizeof hints); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = AI_PASSIVE; + + if (getaddrinfo(NULL, port, &hints, &res) != 0) + { + write_log("getaddrinfo() failed"); + pthread_exit(NULL); + } + + for(p = res;p != NULL; p = p->ai_next) + { + if ((serverSocket = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) + { + write_log("Could not open socket"); + continue; + } + + if (setsockopt(serverSocket, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) + { + write_log("Socket setsockopt() failed"); + close(serverSocket); + continue; + } + + if (bind(serverSocket, p->ai_addr, p->ai_addrlen) == -1) + { + write_log("Socket bind() failed"); + close(serverSocket); + continue; + } + + if (listen(serverSocket, 5) == -1) + { + write_log("Socket listen() failed"); + close(serverSocket); + continue; + } + + break; + } + + freeaddrinfo(res); + + if (p == NULL) + { + write_log("Could not find a socket to bind to"); + pthread_exit(NULL); + } + + /* Loop and wait for connections */ + while (1) + { + clientAddr = malloc(sinSize); + if ((clientSocket = accept(serverSocket, (struct sockaddr *) clientAddr, &sinSize)) == -1) + { + + free(clientAddr); + write_log("Could not accept() connection"); + continue; + } + + + + wa = malloc(sizeof(struct workerArgs)); + wa->socket = clientSocket; + + if (pthread_create(&worker_thread, NULL, service_single_client, wa) != 0) + { + write_log("Could not create a worker thread"); + free(clientAddr); + free(wa); + close(clientSocket); + close(serverSocket); + pthread_exit(NULL); + } + } + + pthread_exit(NULL); +} + + +void *service_single_client(void *args) { + struct workerArgs *wa; + int socket, nbytes; + + wa = (struct workerArgs*) args; + socket = wa->socket; + + pthread_detach(pthread_self()); + + // log connection + struct sockaddr_in addr; + socklen_t addr_size = sizeof(struct sockaddr_in); + int res = getpeername(socket, (struct sockaddr *)&addr, &addr_size); + char log_string[20 + INET_ADDRSTRLEN] = "Connection from "; + strcat(log_string, inet_ntoa(addr.sin_addr)); + + + // send + char *tosend = get_quote(&config); + nbytes = send(socket, tosend, strlen(tosend), 0); + close(socket); + free(wa); + + // write log + write_log(log_string); + pthread_exit(NULL); + +} + -- cgit v1.2.3