diff options
Diffstat (limited to 'src/server/server.c')
-rw-r--r-- | src/server/server.c | 407 |
1 files changed, 202 insertions, 205 deletions
diff --git a/src/server/server.c b/src/server/server.c index ffeb0af..0b327e3 100644 --- a/src/server/server.c +++ b/src/server/server.c @@ -48,237 +48,234 @@ char *config_file_name = DEFAULT_CONFIG_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 Configuration file (default /etc/dnbd3-server.conf)\n"); - printf("-n or --nodaemon \t\t Start server in foreground\n"); - printf("-r or --reload \t\t Reload configuration file\n"); - printf("-s or --stop \t\t Stop running dnbd3-server\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); + printf("Usage: %s [OPTIONS]...\n", argv_0); + printf("Start the DNBD3 server\n"); + printf("-f or --file \t\t Configuration file (default /etc/dnbd3-server.conf)\n"); + printf("-n or --nodaemon \t\t Start server in foreground\n"); + printf("-r or --reload \t\t Reload configuration file\n"); + printf("-s or --stop \t\t Stop running dnbd3-server\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); + printf("Version: %s\n", VERSION_STRING); + exit(0); } void cleanup() { - close(_sock); - dnbd3_delete_pid_file(); - exit(EXIT_SUCCESS); + close(_sock); + dnbd3_delete_pid_file(); + exit(EXIT_SUCCESS); } void handle_sigpipe(int signum) { - printf("ERROR: Received signal SIGPIPE, Broken pipe (errno: %i)\n", errno); - return; + printf("ERROR: Received signal SIGPIPE, Broken pipe (errno: %i)\n", errno); + return; } void handle_sighup(int signum) { - printf("INFO: SIGHUP received!\n"); - printf("INFO: Reloading configuration...\n"); - pthread_spin_lock(&spinlock); - dnbd3_reload_config(config_file_name); - pthread_spin_unlock(&spinlock); + printf("INFO: SIGHUP received!\n"); + printf("INFO: Reloading configuration...\n"); + pthread_spin_lock(&spinlock); + dnbd3_reload_config(config_file_name); + pthread_spin_unlock(&spinlock); } void handle_sigterm(int signum) { - printf("INFO: SIGTERM or SIGINT received!\n"); - cleanup(); + printf("INFO: SIGTERM or SIGINT received!\n"); + cleanup(); } void *handle_query(void *client_socket) { - int image_file = -1; - off_t filesize = 0; - int sock = (int)(uintptr_t) client_socket; - struct dnbd3_request request; - struct dnbd3_reply reply; - uint16_t cmd; - - while (recv(sock, &request, sizeof(struct dnbd3_request), MSG_WAITALL) > 0) - { - cmd = request.cmd; - switch (cmd) - { - case CMD_PING: - reply.cmd = request.cmd; - memcpy(reply.handle, request.handle, sizeof(request.handle)); - send(sock, (char *) &reply, sizeof(struct dnbd3_reply), 0); - break; - - case CMD_GET_SIZE: - pthread_spin_lock(&spinlock); // because of reloading config - image_file = open(dnbd3_ht_search(request.image_id), O_RDONLY); - pthread_spin_unlock(&spinlock); - if (image_file < 0) - { - printf("ERROR: Client requested an unknown image id.\n"); - filesize = 0; - } - else - { - struct stat st; - fstat(image_file, &st); - filesize = st.st_size; - } - - reply.cmd = request.cmd; - reply.filesize = filesize; - send(sock, (char *) &reply, sizeof(struct dnbd3_reply), 0); - break; - - case CMD_GET_BLOCK: - if (image_file < 0) - break; - - reply.cmd = request.cmd; - memcpy(reply.handle, request.handle, sizeof(request.handle)); - send(sock, (char *) &reply, sizeof(struct dnbd3_reply), 0); - - if (sendfile(sock, image_file, (off_t *) &request.offset, - request.size) < 0) - printf("ERROR: sendfile returned -1\n"); - - break; - - default: - printf("ERROR: Unknown command\n"); - break; - } - - } - close(sock); - printf("INFO: Client exit.\n"); - pthread_exit((void *) 0); + int image_file = -1; + off_t filesize = 0; + int sock = (int) (uintptr_t) client_socket; + struct dnbd3_request request; + struct dnbd3_reply reply; + uint16_t cmd; + + while (recv(sock, &request, sizeof(struct dnbd3_request), MSG_WAITALL) > 0) + { + cmd = request.cmd; + switch (cmd) + { + case CMD_PING: + reply.cmd = request.cmd; + memcpy(reply.handle, request.handle, sizeof(request.handle)); + send(sock, (char *) &reply, sizeof(struct dnbd3_reply), 0); + break; + + case CMD_GET_SIZE: + pthread_spin_lock(&spinlock); // because of reloading config + image_file = open(dnbd3_ht_search(request.image_id), O_RDONLY); + pthread_spin_unlock(&spinlock); + if (image_file < 0) + { + printf("ERROR: Client requested an unknown image id.\n"); + filesize = 0; + } + else + { + struct stat st; + fstat(image_file, &st); + filesize = st.st_size; + } + reply.cmd = request.cmd; + reply.filesize = filesize; + send(sock, (char *) &reply, sizeof(struct dnbd3_reply), 0); + break; + + case CMD_GET_BLOCK: + if (image_file < 0) + break; + + reply.cmd = request.cmd; + memcpy(reply.handle, request.handle, sizeof(request.handle)); + send(sock, (char *) &reply, sizeof(struct dnbd3_reply), 0); + + if (sendfile(sock, image_file, (off_t *) &request.offset, request.size) < 0) + printf("ERROR: sendfile returned -1\n"); + + break; + + default: + printf("ERROR: Unknown command\n"); + break; + } + + } + close(sock); + printf("INFO: Client exit.\n"); + pthread_exit((void *) 0); } int main(int argc, char* argv[]) { - int demonize = 1; - int opt = 0; - int longIndex = 0; - static const char *optString = "f:nrshv?"; - static const struct option longOpts[] = - { - { "file", required_argument, NULL, 'f' }, - { "nodaemon", no_argument, NULL, 'n' }, - { "reload", no_argument, NULL, 'r' }, - { "stop", no_argument, NULL, 's' }, - { "help", no_argument, NULL, 'h' }, - { "version", no_argument, NULL, 'v' } }; - - opt = getopt_long(argc, argv, optString, longOpts, &longIndex); - - while (opt != -1) - { - switch (opt) - { - case 'f': - config_file_name = optarg; - break; - case 'n': - demonize = 0; - break; - case 'r': - printf("INFO: Reloading configuration file...\n"); - dnbd3_send_signal(SIGHUP); - return EXIT_SUCCESS; - case 's': - printf("INFO: Stopping running server...\n"); - dnbd3_send_signal(SIGTERM); - return EXIT_SUCCESS; - case 'h': - print_help(argv[0]); - break; - case 'v': - print_version(); - break; - case '?': - exit(1); - } - opt = getopt_long(argc, argv, optString, longOpts, &longIndex); - } - - if (demonize) - daemon(1,0); - - pthread_spin_init(&spinlock, PTHREAD_PROCESS_PRIVATE); - dnbd3_load_config(config_file_name); - - // setup signal handler - signal(SIGPIPE, handle_sigpipe); - signal(SIGHUP, handle_sighup); - signal(SIGTERM, handle_sigterm); - signal(SIGINT, handle_sigterm); - - // setup network - struct sockaddr_in server; - struct sockaddr_in client; - int fd; - unsigned int len; - - // 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); - } - - dnbd3_write_pid_file(getpid()); - printf("INFO: Server is ready...\n"); - - struct timeval timeout; - timeout.tv_sec = SERVER_SOCKET_TIMEOUT; - timeout.tv_usec = 0; - - - while (1) - { - len = sizeof(client); - fd = accept(_sock, (struct sockaddr*) &client, &len); - if (fd < 0) - { - printf("ERROR: Accept failure\n"); - exit(EXIT_FAILURE); - } - printf("INFO: Client: %s connected\n", inet_ntoa(client.sin_addr)); - - setsockopt (fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(timeout)); - setsockopt (fd, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout, sizeof(timeout)); - - // FIXME: catch SIGKILL/SIGTERM and close all socket before exit - pthread_t thread; - pthread_create(&(thread), NULL, handle_query, (void *)(uintptr_t) fd); - pthread_detach(thread); - } - - cleanup(); + int demonize = 1; + int opt = 0; + int longIndex = 0; + static const char *optString = "f:nrshv?"; + static const struct option longOpts[] = + { + { "file", required_argument, NULL, 'f' }, + { "nodaemon", no_argument, NULL, 'n' }, + { "reload", no_argument, NULL, 'r' }, + { "stop", no_argument, NULL, 's' }, + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, 'v' } }; + + opt = getopt_long(argc, argv, optString, longOpts, &longIndex); + + while (opt != -1) + { + switch (opt) + { + case 'f': + config_file_name = optarg; + break; + case 'n': + demonize = 0; + break; + case 'r': + printf("INFO: Reloading configuration file...\n"); + dnbd3_send_signal(SIGHUP); + return EXIT_SUCCESS; + case 's': + printf("INFO: Stopping running server...\n"); + dnbd3_send_signal(SIGTERM); + return EXIT_SUCCESS; + case 'h': + print_help(argv[0]); + break; + case 'v': + print_version(); + break; + case '?': + exit(1); + } + opt = getopt_long(argc, argv, optString, longOpts, &longIndex); + } + + if (demonize) + daemon(1, 0); + + // load config file + pthread_spin_init(&spinlock, PTHREAD_PROCESS_PRIVATE); + dnbd3_load_config(config_file_name); + + // setup signal handler + signal(SIGPIPE, handle_sigpipe); + signal(SIGHUP, handle_sighup); + signal(SIGTERM, handle_sigterm); + signal(SIGINT, handle_sigterm); + + // setup network + struct sockaddr_in server; + struct sockaddr_in client; + int fd; + unsigned int len; + + // 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); + } + + dnbd3_write_pid_file(getpid()); + printf("INFO: Server is ready...\n"); + + struct timeval timeout; + timeout.tv_sec = SERVER_SOCKET_TIMEOUT; + timeout.tv_usec = 0; + + while (1) + { + len = sizeof(client); + fd = accept(_sock, (struct sockaddr*) &client, &len); + if (fd < 0) + { + printf("ERROR: Accept failure\n"); + exit(EXIT_FAILURE); + } + printf("INFO: Client: %s connected\n", inet_ntoa(client.sin_addr)); + + setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, (char *) &timeout, sizeof(timeout)); + setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, (char *) &timeout, sizeof(timeout)); + + // FIXME: catch SIGKILL/SIGTERM and close all socket before exit + pthread_t thread; + pthread_create(&(thread), NULL, handle_query, (void *) (uintptr_t) fd); + pthread_detach(thread); + } + + cleanup(); } |