summaryrefslogtreecommitdiffstats
path: root/src/server/server.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/server/server.c')
-rw-r--r--src/server/server.c407
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();
}