From 9970fb00c79834703bc990d052439290338467be Mon Sep 17 00:00:00 2001 From: Johann Latocha Date: Tue, 29 Nov 2011 15:06:45 +0100 Subject: initial commit --- src/server/server.c | 173 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 173 insertions(+) create mode 100644 src/server/server.c (limited to 'src/server/server.c') diff --git a/src/server/server.c b/src/server/server.c new file mode 100644 index 0000000..e38a0e3 --- /dev/null +++ b/src/server/server.c @@ -0,0 +1,173 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "../include/types.h" +#include "../version.h" +#include "file.h" + +int file; + +void print_help(char* argv_0) +{ + + printf("Usage: %s [OPTIONS]...\n", argv_0); + printf("Start the DNBD3 server.\n"); + printf("-f or --file \t\t File to export.\n"); + printf("-h or --help \t\t Show this help text and quit.\n"); + printf("-v or --version \t Show version and quit.\n"); + exit(0); +} + +void print_version() +{ + printf("Version: %s\n", VERSION_STRING); + exit(0); +} + +void handle_sigpipe(int signum) +{ + printf("Program received signal SIGPIPE, Broken pipe (errno: %i)\n", errno); + return; +} + +void *echo(void *client_socket) +{ + int sock = (int) client_socket; + struct dnbd3_request request; + struct dnbd3_reply reply; + uint16_t cmd; + off_t filesize; + + while (recv(sock, &request, sizeof(struct dnbd3_request), MSG_WAITALL) > 0) + { + cmd = request.cmd; +// char buf[request.size]; + switch (cmd) + { + case CMD_GET_SIZE: + reply.cmd = request.cmd; + file_getsize(file, &filesize); + reply.filesize = filesize; + send(sock, (char *) &reply, sizeof(struct dnbd3_reply), 0); + break; + + case CMD_GET_BLOCK: +// printf("CMD: %i, Byte: %llu, Size: %llu\n",request.cmd, request.offset, request.size); +// file_read(file, buf, request.size, request.offset); +// send(sock, (char *) buf, request.size, 0); + sendfile(sock, file, (off_t *) &request.offset, request.size); + break; + + default: + ; + } + + } + close(sock); + printf("Client exit.\n"); + pthread_exit((void *)0); +} + +int main(int argc, char* argv[]) +{ + int opt = 0; + int longIndex = 0; + static const char *optString = "f:hv?"; + static const struct option longOpts[] = + { + { "file", required_argument, NULL, 'f' }, + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, 'v' } }; + + opt = getopt_long(argc, argv, optString, longOpts, &longIndex); + if (opt == -1) + print_help(argv[0]); + + while (opt != -1) + { + switch (opt) + { + case 'f': + file = file_open(optarg); + break; + case 'h': + print_help(argv[0]); + break; + case 'v': + print_version(); + break; + case '?': + exit(1); + } + opt = getopt_long(argc, argv, optString, longOpts, &longIndex); + } + + signal(SIGPIPE, handle_sigpipe); + + struct sockaddr_in server; + struct sockaddr_in client[50]; + int sock, fd; + unsigned int len; + pthread_t thread[50]; + int i=1; + + // Create socket + sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); + if (sock < 0) + { + printf("ERROR: Socket failure\n"); + exit(EXIT_FAILURE); + } + + memset(&server, 0, sizeof(server)); + server.sin_family = AF_INET; // IPv4 + server.sin_addr.s_addr = htonl(INADDR_ANY); // Take all IPs + server.sin_port = htons(PORT); // set port number + + // Bind to socket + if (bind(sock, (struct sockaddr*) &server, sizeof(server)) < 0) + { + printf("ERROR: Bind failure\n"); + exit(EXIT_FAILURE); + } + + // Listen on socket + if (listen(sock, 50) == -1) + { + printf("ERROR: Listen failure\n"); + exit(EXIT_FAILURE); + } + + printf("INFO: Server is ready...\n"); + + // TODO: dyn threads + while (1) + { + len = sizeof(client); + fd = accept(sock, (struct sockaddr*) &client[i], &len); + if (fd < 0) + { + printf("ERROR: Accept failure\n"); + exit(EXIT_FAILURE); + } + + printf("INFO: Client: %s connected\n", inet_ntoa(client[i].sin_addr)); + pthread_create(&(thread[i]), NULL, echo, (void *) fd); + pthread_detach(thread[i++]); + } + return EXIT_SUCCESS; +} -- cgit v1.2.3-55-g7522