diff options
Diffstat (limited to 'src/server')
-rw-r--r-- | src/server/net.c | 133 | ||||
-rw-r--r-- | src/server/net.h | 28 | ||||
-rw-r--r-- | src/server/server.c | 178 | ||||
-rw-r--r-- | src/server/server.h | 34 | ||||
-rw-r--r-- | src/server/signal.c | 45 | ||||
-rw-r--r-- | src/server/signal.h | 30 | ||||
-rw-r--r-- | src/server/utils.h | 2 |
7 files changed, 301 insertions, 149 deletions
diff --git a/src/server/net.c b/src/server/net.c new file mode 100644 index 0000000..87af60f --- /dev/null +++ b/src/server/net.c @@ -0,0 +1,133 @@ +/* + * This file is part of the Distributed Network Block Device 3 + * + * Copyright(c) 2011-2012 Johann Latocha <johann@latocha.de> + * + * This file may be licensed under the terms of of the + * GNU General Public License Version 2 (the ``GPL''). + * + * Software distributed under the License is distributed + * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See the GPL for the specific language + * governing rights and limitations. + * + * You should have received a copy of the GPL along with this + * program. If not, go to http://www.gnu.org/licenses/gpl.html + * or write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include <stdint.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> +#include <pthread.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <sys/socket.h> +#include <sys/sendfile.h> +#include <sys/types.h> +#include <netinet/in.h> + +#include "server.h" +#include "hashtable.h" + +void *dnbd3_handle_query(void *client_socket) +{ + int image_file = -1; + off_t filesize = 0; + int sock = (int) (uintptr_t) client_socket; + dnbd3_request_t request; + dnbd3_reply_t reply; + uint16_t cmd; + + while (recv(sock, &request, sizeof(dnbd3_request_t), 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(dnbd3_reply_t), 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(dnbd3_reply_t), 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(dnbd3_reply_t), 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 dnbd3_setup_socket() +{ + int sock; + struct sockaddr_in server; + + // Create socket + sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); + if (sock < 0) + { + printf("ERROR: Socket failure\n"); + return -1; + } + + 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"); + return -1; + } + + // Listen on socket + if (listen(sock, 50) == -1) + { + printf("ERROR: Listen failure\n"); + return -1; + } + + return sock; +} diff --git a/src/server/net.h b/src/server/net.h new file mode 100644 index 0000000..3e34c99 --- /dev/null +++ b/src/server/net.h @@ -0,0 +1,28 @@ +/* + * This file is part of the Distributed Network Block Device 3 + * + * Copyright(c) 2011-2012 Johann Latocha <johann@latocha.de> + * + * This file may be licensed under the terms of of the + * GNU General Public License Version 2 (the ``GPL''). + * + * Software distributed under the License is distributed + * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See the GPL for the specific language + * governing rights and limitations. + * + * You should have received a copy of the GPL along with this + * program. If not, go to http://www.gnu.org/licenses/gpl.html + * or write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef NET_H_ +#define NET_H_ + +void *dnbd3_handle_query(void *client_socket); + +int dnbd3_setup_socket(); + +#endif /* NET_H_ */ diff --git a/src/server/server.c b/src/server/server.c index 0b327e3..e15249b 100644 --- a/src/server/server.c +++ b/src/server/server.c @@ -20,33 +20,26 @@ #include <stdio.h> #include <stdlib.h> -#include <string.h> -#include <fcntl.h> -#include <errno.h> -#include <sys/types.h> -#include <sys/socket.h> -#include <netdb.h> #include <arpa/inet.h> -#include <unistd.h> #include <signal.h> #include <getopt.h> -#include <netinet/in.h> -#include <sys/sendfile.h> -#include <sys/stat.h> - #include <pthread.h> #include "../types.h" #include "../version.h" +#include "server.h" #include "utils.h" #include "hashtable.h" +#include "signal.h" +#include "net.h" int _sock; -pthread_spinlock_t spinlock; -char *config_file_name = DEFAULT_CONFIG_FILE; -void print_help(char* argv_0) +pthread_spinlock_t _spinlock; +char *_config_file_name = DEFAULT_CONFIG_FILE; + +void dnbd3_print_help(char* argv_0) { printf("Usage: %s [OPTIONS]...\n", argv_0); printf("Start the DNBD3 server\n"); @@ -59,104 +52,19 @@ void print_help(char* argv_0) exit(0); } -void print_version() +void dnbd3_print_version() { printf("Version: %s\n", VERSION_STRING); exit(0); } -void cleanup() +void dnbd3_cleanup() { 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; -} - -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); -} - -void handle_sigterm(int signum) -{ - 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 main(int argc, char* argv[]) { int demonize = 1; @@ -179,7 +87,7 @@ int main(int argc, char* argv[]) switch (opt) { case 'f': - config_file_name = optarg; + _config_file_name = optarg; break; case 'n': demonize = 0; @@ -193,13 +101,13 @@ int main(int argc, char* argv[]) dnbd3_send_signal(SIGTERM); return EXIT_SUCCESS; case 'h': - print_help(argv[0]); + dnbd3_print_help(argv[0]); break; case 'v': - print_version(); + dnbd3_print_version(); break; case '?': - exit(1); + dnbd3_print_help(argv[0]); } opt = getopt_long(argc, argv, optString, longOpts, &longIndex); } @@ -208,63 +116,37 @@ int main(int argc, char* argv[]) daemon(1, 0); // load config file - pthread_spin_init(&spinlock, PTHREAD_PROCESS_PRIVATE); - dnbd3_load_config(config_file_name); + 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); + signal(SIGPIPE, dnbd3_handle_sigpipe); + signal(SIGHUP, dnbd3_handle_sighup); + signal(SIGTERM, dnbd3_handle_sigterm); + signal(SIGINT, dnbd3_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); + _sock = dnbd3_setup_socket(); 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 sockaddr_in client; + unsigned int len = sizeof(client); + int fd; struct timeval timeout; timeout.tv_sec = SERVER_SOCKET_TIMEOUT; timeout.tv_usec = 0; + dnbd3_write_pid_file(getpid()); + printf("INFO: Server is ready...\n"); + + // main loop while (1) { - len = sizeof(client); fd = accept(_sock, (struct sockaddr*) &client, &len); if (fd < 0) { printf("ERROR: Accept failure\n"); - exit(EXIT_FAILURE); + continue; } printf("INFO: Client: %s connected\n", inet_ntoa(client.sin_addr)); @@ -273,9 +155,9 @@ int main(int argc, char* argv[]) // FIXME: catch SIGKILL/SIGTERM and close all socket before exit pthread_t thread; - pthread_create(&(thread), NULL, handle_query, (void *) (uintptr_t) fd); + pthread_create(&(thread), NULL, dnbd3_handle_query, (void *) (uintptr_t) fd); pthread_detach(thread); } - cleanup(); + dnbd3_cleanup(); } diff --git a/src/server/server.h b/src/server/server.h new file mode 100644 index 0000000..3918faf --- /dev/null +++ b/src/server/server.h @@ -0,0 +1,34 @@ +/* + * This file is part of the Distributed Network Block Device 3 + * + * Copyright(c) 2011-2012 Johann Latocha <johann@latocha.de> + * + * This file may be licensed under the terms of of the + * GNU General Public License Version 2 (the ``GPL''). + * + * Software distributed under the License is distributed + * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See the GPL for the specific language + * governing rights and limitations. + * + * You should have received a copy of the GPL along with this + * program. If not, go to http://www.gnu.org/licenses/gpl.html + * or write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef SERVER_H_ +#define SERVER_H_ + +#include <stdint.h> + +#include "config.h" +#include "../types.h" + +extern pthread_spinlock_t _spinlock; +extern char *_config_file_name; + +void dnbd3_cleanup(); + +#endif /* SERVER_H_ */ diff --git a/src/server/signal.c b/src/server/signal.c new file mode 100644 index 0000000..443742f --- /dev/null +++ b/src/server/signal.c @@ -0,0 +1,45 @@ +/* + * This file is part of the Distributed Network Block Device 3 + * + * Copyright(c) 2011-2012 Johann Latocha <johann@latocha.de> + * + * This file may be licensed under the terms of of the + * GNU General Public License Version 2 (the ``GPL''). + * + * Software distributed under the License is distributed + * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See the GPL for the specific language + * governing rights and limitations. + * + * You should have received a copy of the GPL along with this + * program. If not, go to http://www.gnu.org/licenses/gpl.html + * or write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include <stdio.h> +#include <pthread.h> + +#include "server.h" +#include "utils.h" + +void dnbd3_handle_sigpipe(int signum) +{ + printf("ERROR: SIGPIPE received!\n"); +} + +void dnbd3_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); +} + +void dnbd3_handle_sigterm(int signum) +{ + printf("INFO: SIGTERM or SIGINT received!\n"); + dnbd3_cleanup(); +} diff --git a/src/server/signal.h b/src/server/signal.h new file mode 100644 index 0000000..d91babf --- /dev/null +++ b/src/server/signal.h @@ -0,0 +1,30 @@ +/* + * This file is part of the Distributed Network Block Device 3 + * + * Copyright(c) 2011-2012 Johann Latocha <johann@latocha.de> + * + * This file may be licensed under the terms of of the + * GNU General Public License Version 2 (the ``GPL''). + * + * Software distributed under the License is distributed + * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See the GPL for the specific language + * governing rights and limitations. + * + * You should have received a copy of the GPL along with this + * program. If not, go to http://www.gnu.org/licenses/gpl.html + * or write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef SIGNAL_H_ +#define SIGNAL_H_ + +void dnbd3_handle_sigpipe(int signum); + +void dnbd3_handle_sighup(int signum); + +void dnbd3_handle_sigterm(int signum); + +#endif /* SIGNAL_H_ */ diff --git a/src/server/utils.h b/src/server/utils.h index 67a5444..ab8f839 100644 --- a/src/server/utils.h +++ b/src/server/utils.h @@ -26,8 +26,8 @@ #ifndef UTILS_H_ #define UTILS_H_ -void dnbd3_write_pid_file(pid_t pid); pid_t dnbd3_read_pid_file(); +void dnbd3_write_pid_file(pid_t pid); void dnbd3_delete_pid_file(); void dnbd3_load_config(char* config_file_name); |