summaryrefslogtreecommitdiffstats
path: root/src/server/net.c
diff options
context:
space:
mode:
authorsr2012-09-03 15:27:36 +0200
committersr2012-09-03 15:27:36 +0200
commita55be46ec7a281f5c3d41d48edf32e57ef5e4ba1 (patch)
treed375eaf63e03a6e1b5e199712735a68b448c6d97 /src/server/net.c
parent[SERVER] Add list of trusted servers and namespaces (load, display) (diff)
downloaddnbd3-a55be46ec7a281f5c3d41d48edf32e57ef5e4ba1.tar.gz
dnbd3-a55be46ec7a281f5c3d41d48edf32e57ef5e4ba1.tar.xz
dnbd3-a55be46ec7a281f5c3d41d48edf32e57ef5e4ba1.zip
[*] Fixed and unified formatting
Diffstat (limited to 'src/server/net.c')
-rw-r--r--src/server/net.c535
1 files changed, 269 insertions, 266 deletions
diff --git a/src/server/net.c b/src/server/net.c
index bcbf056..afb7077 100644
--- a/src/server/net.c
+++ b/src/server/net.c
@@ -43,29 +43,29 @@ static inline char recv_request_header(int sock, dnbd3_request_t *request)
{
int ret;
// Read request header from socket
- if ((ret = recv(sock, request, sizeof(*request), MSG_WAITALL)) != sizeof(*request))
- {
- if (ret == 0) return 0;
- printf("[DEBUG] Error receiving request: Could not read message header (%d/%d)\n", ret, (int)sizeof(*request));
- return 0;
- }
- // Make sure all bytes are in the right order (endianness)
- fixup_request(*request);
- if (request->magic != dnbd3_packet_magic)
- {
- printf("[DEBUG] Magic in client request incorrect (cmd: %d, len: %d)\n", (int)request->cmd, (int)request->size);
- return 0;
- }
- // Payload sanity check
- if (request->cmd != CMD_GET_BLOCK && request->size > MAX_PAYLOAD)
- {
- memlogf("[WARNING] Client tries to send a packet of type %d with %d bytes payload. Dropping client.", (int)request->cmd, (int)request->size);
- return 0;
- }
+ if ((ret = recv(sock, request, sizeof(*request), MSG_WAITALL)) != sizeof(*request))
+ {
+ if (ret == 0) return 0;
+ printf("[DEBUG] Error receiving request: Could not read message header (%d/%d)\n", ret, (int)sizeof(*request));
+ return 0;
+ }
+ // Make sure all bytes are in the right order (endianness)
+ fixup_request(*request);
+ if (request->magic != dnbd3_packet_magic)
+ {
+ printf("[DEBUG] Magic in client request incorrect (cmd: %d, len: %d)\n", (int)request->cmd, (int)request->size);
+ return 0;
+ }
+ // Payload sanity check
+ if (request->cmd != CMD_GET_BLOCK && request->size > MAX_PAYLOAD)
+ {
+ memlogf("[WARNING] Client tries to send a packet of type %d with %d bytes payload. Dropping client.", (int)request->cmd, (int)request->size);
+ return 0;
+ }
#ifdef _DEBUG
- if (_fake_delay) usleep(_fake_delay);
+ if (_fake_delay) usleep(_fake_delay);
#endif
- return 1;
+ return 1;
}
static inline char recv_request_payload(int sock, uint32_t size, serialized_buffer_t *payload)
@@ -120,44 +120,44 @@ static inline char send_reply(int sock, dnbd3_reply_t *reply, void *payload)
void *dnbd3_handle_query(void *dnbd3_client)
{
- dnbd3_client_t *client = (dnbd3_client_t *) (uintptr_t) dnbd3_client;
- dnbd3_request_t request;
- dnbd3_reply_t reply;
-
- dnbd3_image_t *image = NULL;
- int image_file = -1, image_cache = -1;
-
- int i, num;
-
- uint64_t map_y;
- char map_x, bit_mask;
- serialized_buffer_t payload;
- char *image_name;
- uint16_t rid, client_version;
-
- uint64_t todo_size = 0;
- uint64_t todo_offset = 0;
- uint64_t cur_offset = 0;
- uint64_t last_offset = 0;
-
- dnbd3_server_entry_t server_list[NUMBER_SERVERS];
-
- int dirty = 0;
-
- reply.magic = dnbd3_packet_magic;
-
- // Receive first packet. This must be CMD_GET_SIZE by protocol specification
- if (recv_request_header(client->sock, &request))
- {
- if (request.cmd != CMD_GET_SIZE)
- {
- printf("[DEBUG] Client sent invalid handshake (%d). Dropping Client\n", (int)request.cmd);
- }
- else
- {
- if (recv_request_payload(client->sock, request.size, &payload))
- {
- client_version = serializer_get_uint16(&payload);
+ dnbd3_client_t *client = (dnbd3_client_t *) (uintptr_t) dnbd3_client;
+ dnbd3_request_t request;
+ dnbd3_reply_t reply;
+
+ dnbd3_image_t *image = NULL;
+ int image_file = -1, image_cache = -1;
+
+ int i, num;
+
+ uint64_t map_y;
+ char map_x, bit_mask;
+ serialized_buffer_t payload;
+ char *image_name;
+ uint16_t rid, client_version;
+
+ uint64_t todo_size = 0;
+ uint64_t todo_offset = 0;
+ uint64_t cur_offset = 0;
+ uint64_t last_offset = 0;
+
+ dnbd3_server_entry_t server_list[NUMBER_SERVERS];
+
+ int dirty = 0;
+
+ reply.magic = dnbd3_packet_magic;
+
+ // Receive first packet. This must be CMD_GET_SIZE by protocol specification
+ if (recv_request_header(client->sock, &request))
+ {
+ if (request.cmd != CMD_GET_SIZE)
+ {
+ printf("[DEBUG] Client sent invalid handshake (%d). Dropping Client\n", (int)request.cmd);
+ }
+ else
+ {
+ if (recv_request_payload(client->sock, request.size, &payload))
+ {
+ client_version = serializer_get_uint16(&payload);
image_name = serializer_get_string(&payload);
rid = serializer_get_uint16(&payload);
client->is_server = serializer_get_uint8(&payload);
@@ -182,7 +182,7 @@ void *dnbd3_handle_query(void *dnbd3_client)
printf("[DEBUG] Client requested non-existent image '%s' (rid:%d)\n", image_name, (int)rid);
}
else if ((image->delete_soft != 0 && image->delete_soft < now)
- || (image->delete_hard != 0 && image->delete_hard < now))
+ || (image->delete_hard != 0 && image->delete_hard < now))
{
printf("[DEBUG] Client requested end-of-life image '%s' (rid:%d)\n", image_name, (int)rid);
}
@@ -220,221 +220,224 @@ void *dnbd3_handle_query(void *dnbd3_client)
pthread_spin_unlock(&_spinlock);
}
}
- }
+ }
}
- if (image) while (recv_request_header(client->sock, &request))
- {
- switch (request.cmd)
- {
-
- case CMD_GET_BLOCK:
- if (request.offset >= image->filesize)
- { // Sanity check
- memlogf("[WARNING] Client requested non-existent block");
- reply.size = 0;
- reply.cmd = CMD_ERROR;
- send_reply(client->sock, &reply, NULL);
- break;
- }
- if (request.offset + request.size > image->filesize)
- { // Sanity check
- memlogf("[WARNING] Client requested data block that extends beyond image size");
- reply.size = 0;
- reply.cmd = CMD_ERROR;
- send_reply(client->sock, &reply, NULL);
- break;
- }
- if (request.size > image->filesize)
- { // Sanity check
- memlogf("[WARNING] Client requested data block that is bigger than the image size");
- reply.size = 0;
- reply.cmd = CMD_ERROR;
- send_reply(client->sock, &reply, NULL);
- break;
- }
-
- reply.cmd = CMD_GET_BLOCK;
- reply.size = request.size;
- reply.handle = request.handle;
-
- fixup_reply(reply);
- if (send(client->sock, &reply, sizeof(dnbd3_reply_t), MSG_MORE) != sizeof(dnbd3_reply_t))
+ if (image) while (recv_request_header(client->sock, &request))
+ {
+ switch (request.cmd)
{
- printf("[DEBUG] Sending CMD_GET_BLOCK header failed\n");
- return 0;
+
+ case CMD_GET_BLOCK:
+ if (request.offset >= image->filesize)
+ {
+ // Sanity check
+ memlogf("[WARNING] Client requested non-existent block");
+ reply.size = 0;
+ reply.cmd = CMD_ERROR;
+ send_reply(client->sock, &reply, NULL);
+ break;
+ }
+ if (request.offset + request.size > image->filesize)
+ {
+ // Sanity check
+ memlogf("[WARNING] Client requested data block that extends beyond image size");
+ reply.size = 0;
+ reply.cmd = CMD_ERROR;
+ send_reply(client->sock, &reply, NULL);
+ break;
+ }
+ if (request.size > image->filesize)
+ {
+ // Sanity check
+ memlogf("[WARNING] Client requested data block that is bigger than the image size");
+ reply.size = 0;
+ reply.cmd = CMD_ERROR;
+ send_reply(client->sock, &reply, NULL);
+ break;
+ }
+
+ reply.cmd = CMD_GET_BLOCK;
+ reply.size = request.size;
+ reply.handle = request.handle;
+
+ fixup_reply(reply);
+ if (send(client->sock, &reply, sizeof(dnbd3_reply_t), MSG_MORE) != sizeof(dnbd3_reply_t))
+ {
+ printf("[DEBUG] Sending CMD_GET_BLOCK header failed\n");
+ return 0;
+ }
+
+ if (request.size == 0) // Request for 0 bytes, done after sending header
+ break;
+
+ // caching is off
+ if (image_cache == -1)
+ {
+ if (sendfile(client->sock, image_file, (off_t *)&request.offset, request.size) != request.size)
+ {
+ printf("[ERROR] sendfile failed (image to net)\n");
+ close(client->sock);
+ client->sock = -1;
+ }
+ break;
+ }
+
+ // caching is on
+ dirty = 0;
+ todo_size = 0;
+ todo_offset = request.offset;
+ cur_offset = request.offset;
+ last_offset = request.offset + request.size;
+
+ // first make sure the whole requested part is in the local cache file
+ while(cur_offset < last_offset)
+ {
+ map_y = cur_offset >> 15; // div 32768
+ map_x = (cur_offset >> 12) & 7; // (X div 4096) mod 8
+ bit_mask = 0b00000001 << (map_x);
+
+ cur_offset += 4096;
+
+ if ((image->cache_map[map_y] & bit_mask) != 0) // cache hit
+ {
+ if (todo_size != 0) // fetch missing chunks
+ {
+ lseek(image_cache, todo_offset, SEEK_SET);
+ if (sendfile(image_cache, image_file, (off_t *) &todo_offset, todo_size) != todo_size)
+ {
+ printf("[ERROR] sendfile failed (copy to cache 1)\n");
+ close(client->sock);
+ client->sock = -1;
+ // Reset these so we don't update the cache map with false information
+ dirty = 0;
+ todo_size = 0;
+ break;
+ }
+ todo_size = 0;
+ dirty = 1;
+ }
+ todo_offset = cur_offset;
+ }
+ else
+ {
+ todo_size += 4096;
+ }
+ }
+
+ // whole request was missing
+ if (todo_size != 0)
+ {
+ lseek(image_cache, todo_offset, SEEK_SET);
+ if (sendfile(image_cache, image_file, (off_t *) &todo_offset, todo_size) != todo_size)
+ {
+ printf("[ERROR] sendfile failed (copy to cache 2)\n");
+ close(client->sock);
+ client->sock = -1;
+ break;
+ }
+ dirty = 1;
+ }
+
+ if (dirty) // cache map needs to be updated as something was missing locally
+ {
+ // set 1 in cache map for whole request
+ cur_offset = request.offset;
+ while(cur_offset < last_offset)
+ {
+ map_y = cur_offset >> 15;
+ map_x = (cur_offset >> 12) & 7; // mod 8
+ bit_mask = 0b00000001 << (map_x);
+ image->cache_map[map_y] |= bit_mask;
+ cur_offset += 4096;
+ }
+ }
+
+ // send data to client
+ if (sendfile(client->sock, image_cache, (off_t *) &request.offset, request.size) != request.size)
+ {
+ memlogf("[ERROR] sendfile failed (cache to net)\n");
+ close(client->sock);
+ client->sock = -1;
+ }
+ break;
+
+
+ case CMD_GET_SERVERS:
+ client->is_server = FALSE; // Only clients request list of servers
+ // Build list of known working alt servers
+ num = 0;
+ for (i = 0; i < NUMBER_SERVERS; i++)
+ {
+ if (image->servers[i].hostaddrtype == 0 || image->servers[i].failures > 200) continue;
+ memcpy(server_list + num++, image->servers + i, sizeof(dnbd3_server_entry_t));
+ }
+ reply.cmd = CMD_GET_SERVERS;
+ reply.size = num * sizeof(dnbd3_server_entry_t);
+ send_reply(client->sock, &reply, server_list);
+ break;
+
+ case CMD_KEEPALIVE:
+ reply.cmd = CMD_KEEPALIVE;
+ reply.size = 0;
+ send_reply(client->sock, &reply, NULL);
+ break;
+
+ case CMD_SET_CLIENT_MODE:
+ client->is_server = FALSE;
+ break;
+
+ default:
+ memlogf("ERROR: Unknown command\n");
+ break;
+
}
- if (request.size == 0) // Request for 0 bytes, done after sending header
- break;
-
- // caching is off
- if (image_cache == -1)
- {
- if (sendfile(client->sock, image_file, (off_t *)&request.offset, request.size) != request.size)
- {
- printf("[ERROR] sendfile failed (image to net)\n");
- close(client->sock);
- client->sock = -1;
- }
- break;
- }
-
- // caching is on
- dirty = 0;
- todo_size = 0;
- todo_offset = request.offset;
- cur_offset = request.offset;
- last_offset = request.offset + request.size;
-
- // first make sure the whole requested part is in the local cache file
- while(cur_offset < last_offset)
- {
- map_y = cur_offset >> 15; // div 32768
- map_x = (cur_offset >> 12) & 7; // (X div 4096) mod 8
- bit_mask = 0b00000001 << (map_x);
-
- cur_offset += 4096;
-
- if ((image->cache_map[map_y] & bit_mask) != 0) // cache hit
- {
- if (todo_size != 0) // fetch missing chunks
- {
- lseek(image_cache, todo_offset, SEEK_SET);
- if (sendfile(image_cache, image_file, (off_t *) &todo_offset, todo_size) != todo_size)
- {
- printf("[ERROR] sendfile failed (copy to cache 1)\n");
- close(client->sock);
- client->sock = -1;
- // Reset these so we don't update the cache map with false information
- dirty = 0;
- todo_size = 0;
- break;
- }
- todo_size = 0;
- dirty = 1;
- }
- todo_offset = cur_offset;
- }
- else
- {
- todo_size += 4096;
- }
- }
-
- // whole request was missing
- if (todo_size != 0)
- {
- lseek(image_cache, todo_offset, SEEK_SET);
- if (sendfile(image_cache, image_file, (off_t *) &todo_offset, todo_size) != todo_size)
- {
- printf("[ERROR] sendfile failed (copy to cache 2)\n");
- close(client->sock);
- client->sock = -1;
- break;
- }
- dirty = 1;
- }
-
- if (dirty) // cache map needs to be updated as something was missing locally
- {
- // set 1 in cache map for whole request
- cur_offset = request.offset;
- while(cur_offset < last_offset)
- {
- map_y = cur_offset >> 15;
- map_x = (cur_offset >> 12) & 7; // mod 8
- bit_mask = 0b00000001 << (map_x);
- image->cache_map[map_y] |= bit_mask;
- cur_offset += 4096;
- }
- }
-
- // send data to client
- if (sendfile(client->sock, image_cache, (off_t *) &request.offset, request.size) != request.size)
- {
- memlogf("[ERROR] sendfile failed (cache to net)\n");
- close(client->sock);
- client->sock = -1;
- }
- break;
-
-
- case CMD_GET_SERVERS:
- client->is_server = FALSE; // Only clients request list of servers
- // Build list of known working alt servers
- num = 0;
- for (i = 0; i < NUMBER_SERVERS; i++)
- {
- if (image->servers[i].hostaddrtype == 0 || image->servers[i].failures > 200) continue;
- memcpy(server_list + num++, image->servers + i, sizeof(dnbd3_server_entry_t));
- }
- reply.cmd = CMD_GET_SERVERS;
- reply.size = num * sizeof(dnbd3_server_entry_t);
- send_reply(client->sock, &reply, server_list);
- break;
-
- case CMD_KEEPALIVE:
- reply.cmd = CMD_KEEPALIVE;
- reply.size = 0;
- send_reply(client->sock, &reply, NULL);
- break;
-
- case CMD_SET_CLIENT_MODE:
- client->is_server = FALSE;
- break;
-
- default:
- memlogf("ERROR: Unknown command\n");
- break;
-
- }
-
- }
- pthread_spin_lock(&_spinlock);
- _dnbd3_clients = g_slist_remove(_dnbd3_clients, client);
- pthread_spin_unlock(&_spinlock);
- if (client->sock != -1)
- close(client->sock);
- if (image_file != -1) close(image_file);
- if (image_cache != -1) close(image_cache);
- g_free(client);
- pthread_exit((void *) 0);
+ }
+ pthread_spin_lock(&_spinlock);
+ _dnbd3_clients = g_slist_remove(_dnbd3_clients, client);
+ pthread_spin_unlock(&_spinlock);
+ if (client->sock != -1)
+ close(client->sock);
+ if (image_file != -1) close(image_file);
+ if (image_cache != -1) close(image_cache);
+ g_free(client);
+ 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)
- {
- memlogf("ERROR: Socket setup failure\n");
- return -1;
- }
- const int opt = 1;
+ int sock;
+ struct sockaddr_in server;
+
+ // Create socket
+ sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
+ if (sock < 0)
+ {
+ memlogf("ERROR: Socket setup failure\n");
+ return -1;
+ }
+ const int opt = 1;
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
- 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)
- {
- memlogf("ERROR: Bind failure\n");
- return -1;
- }
-
- // Listen on socket
- if (listen(sock, 100) == -1)
- {
- memlogf("ERROR: Listen failure\n");
- return -1;
- }
-
- return sock;
+ 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)
+ {
+ memlogf("ERROR: Bind failure\n");
+ return -1;
+ }
+
+ // Listen on socket
+ if (listen(sock, 100) == -1)
+ {
+ memlogf("ERROR: Listen failure\n");
+ return -1;
+ }
+
+ return sock;
}