summaryrefslogtreecommitdiffstats
path: root/src/server
diff options
context:
space:
mode:
authorSimon Rettberg2017-09-07 15:50:50 +0200
committerSimon Rettberg2017-09-07 15:50:50 +0200
commit8d96868945f3d52b44de02e2c468766c46693aef (patch)
tree09b012052d5bd67b855b36bd47cdb3956d55e0a8 /src/server
parent[SERVER] Implement closeUnusedFd config option (diff)
downloaddnbd3-8d96868945f3d52b44de02e2c468766c46693aef.tar.gz
dnbd3-8d96868945f3d52b44de02e2c468766c46693aef.tar.xz
dnbd3-8d96868945f3d52b44de02e2c468766c46693aef.zip
[SERVER] Refactor: Move client list to net.* and isolate
Diffstat (limited to 'src/server')
-rw-r--r--src/server/helper.c1
-rw-r--r--src/server/image.c1
-rw-r--r--src/server/image.h5
-rw-r--r--src/server/net.c316
-rw-r--r--src/server/net.h12
-rw-r--r--src/server/rpc.c50
-rw-r--r--src/server/server.c140
-rw-r--r--src/server/server.h12
8 files changed, 290 insertions, 247 deletions
diff --git a/src/server/helper.c b/src/server/helper.c
index fd29e9f..46a5ba8 100644
--- a/src/server/helper.c
+++ b/src/server/helper.c
@@ -2,6 +2,7 @@
#include <arpa/inet.h>
#include <stdlib.h>
#include <signal.h>
+#include <stdio.h>
#ifdef HAVE_THREAD_NAMES
#include <sys/prctl.h> // For thread names
diff --git a/src/server/image.c b/src/server/image.c
index cc5915d..4061e1a 100644
--- a/src/server/image.c
+++ b/src/server/image.c
@@ -14,6 +14,7 @@
#include <zlib.h>
#include <inttypes.h>
#include <glob.h>
+#include <jansson.h>
#define PATHLEN (2000)
#define NONWORKING_RECHECK_INTERVAL_SECONDS (60)
diff --git a/src/server/image.h b/src/server/image.h
index 40a6375..a3c4ceb 100644
--- a/src/server/image.h
+++ b/src/server/image.h
@@ -2,7 +2,8 @@
#define _IMAGE_H_
#include "globals.h"
-#include <jansson.h>
+
+struct json_t;
extern dnbd3_image_t *_images[];
extern int _num_images;
@@ -39,7 +40,7 @@ bool image_create(char *image, int revision, uint64_t size);
bool image_generateCrcFile(char *image);
-json_t* image_getListAsJson();
+struct json_t* image_getListAsJson();
int image_getCompletenessEstimate(dnbd3_image_t * const image);
diff --git a/src/server/net.c b/src/server/net.c
index 3092c7e..f7a866b 100644
--- a/src/server/net.c
+++ b/src/server/net.c
@@ -38,12 +38,22 @@
#include <sys/socket.h>
#include <sys/uio.h>
#endif
+#include <jansson.h>
+
+static dnbd3_client_t *_clients[SERVER_MAX_CLIENTS];
+static int _num_clients = 0;
+static pthread_spinlock_t _clients_lock;
static char nullbytes[500];
static uint64_t totalBytesSent = 0;
static pthread_spinlock_t statisticsSentLock;
+// Adding and removing clients -- list management
+static void dnbd3_removeClient(dnbd3_client_t *client);
+static dnbd3_client_t* dnbd3_freeClient(dnbd3_client_t *client);
+static bool dnbd3_addClient(dnbd3_client_t *client);
+
/**
* Update global sent stats. Hold client's statsLock when calling.
*/
@@ -146,13 +156,51 @@ uint64_t net_getTotalBytesSent()
void net_init()
{
+ spin_init( &_clients_lock, PTHREAD_PROCESS_PRIVATE );
spin_init( &statisticsSentLock, PTHREAD_PROCESS_PRIVATE );
}
-void *net_client_handler(void *dnbd3_client)
+void* net_handleNewConnection(void *clientPtr)
{
- dnbd3_client_t * const client = (dnbd3_client_t *)dnbd3_client;
+ dnbd3_client_t * const client = (dnbd3_client_t *)clientPtr;
dnbd3_request_t request;
+ int ret;
+
+ // Await data from client. Since this is a fresh connection, we expect data right away
+ sock_setTimeout( client->sock, _clientTimeout );
+ ret = recv( client->sock, &request, sizeof(request), MSG_WAITALL );
+ // Let's see if this looks like an HTTP request
+ if ( ret > 5 && request.magic != dnbd3_packet_magic
+ && ( strncmp( (char*)&request, "GET ", 4 ) == 0 || strncmp( (char*)&request, "POST ", 5 ) == 0 ) ) {
+ rpc_sendStatsJson( client->sock );
+ goto fail_preadd;
+ }
+
+ // It's expected to be a real dnbd3 client
+ // Check request for validity
+ if ( ret != sizeof(request) ) {
+ logadd( LOG_DEBUG1, "Error receiving request: Could not read message header (%d/%d, e=%d)", ret, (int)sizeof(request), errno );
+ goto fail_preadd;
+ }
+ if ( request.magic != dnbd3_packet_magic ) {
+ logadd( LOG_DEBUG1, "Magic in client handshake incorrect" );
+ goto fail_preadd;
+ }
+ fixup_request( *request );
+ if ( request.cmd != CMD_SELECT_IMAGE ) {
+ logadd( LOG_WARNING, "Client sent != CMD_SELECT_IMAGE in handshake (got cmd=%d, size=%d), dropping client.", (int)request.cmd, (int)request.size );
+ goto fail_preadd;
+ }
+ // Fully init client struct
+ spin_init( &client->lock, PTHREAD_PROCESS_PRIVATE );
+ spin_init( &client->statsLock, PTHREAD_PROCESS_PRIVATE );
+ pthread_mutex_init( &client->sendMutex, NULL );
+ if ( !dnbd3_addClient( client ) ) {
+ dnbd3_freeClient( client );
+ logadd( LOG_WARNING, "Could not add new client to list when connecting" );
+ return NULL;
+ }
+
dnbd3_reply_t reply;
dnbd3_image_t *image = NULL;
@@ -173,75 +221,62 @@ void *net_client_handler(void *dnbd3_client)
memset( &payload, 0, sizeof(payload) );
reply.magic = dnbd3_packet_magic;
- sock_setTimeout( client->sock, _clientTimeout );
spin_lock( &client->lock );
host_to_string( &client->host, client->hostName, HOSTNAMELEN );
client->hostName[HOSTNAMELEN-1] = '\0';
spin_unlock( &client->lock );
- // Receive first packet. This must be CMD_SELECT_IMAGE by protocol specification
- if ( recv_request_header( client->sock, &request ) ) {
- if ( request.cmd != CMD_SELECT_IMAGE ) {
- logadd( LOG_DEBUG1, "Client %s sent invalid handshake (%d). Dropping Client\n", client->hostName, (int)request.cmd );
- } else if ( recv_request_payload( client->sock, request.size, &payload ) ) {
- char *image_name;
- client_version = serializer_get_uint16( &payload );
- image_name = serializer_get_string( &payload );
- rid = serializer_get_uint16( &payload );
- client->isServer = serializer_get_uint8( &payload );
- if ( request.size < 3 || !image_name || client_version < MIN_SUPPORTED_CLIENT ) {
- if ( client_version < MIN_SUPPORTED_CLIENT ) {
- logadd( LOG_DEBUG1, "Client %s too old", client->hostName );
- } else {
- logadd( LOG_DEBUG1, "Incomplete handshake received from %s", client->hostName );
- }
+ // Receive first packet's payload
+ if ( recv_request_payload( client->sock, request.size, &payload ) ) {
+ char *image_name;
+ client_version = serializer_get_uint16( &payload );
+ image_name = serializer_get_string( &payload );
+ rid = serializer_get_uint16( &payload );
+ client->isServer = serializer_get_uint8( &payload );
+ if ( request.size < 3 || !image_name || client_version < MIN_SUPPORTED_CLIENT ) {
+ if ( client_version < MIN_SUPPORTED_CLIENT ) {
+ logadd( LOG_DEBUG1, "Client %s too old", client->hostName );
} else {
- image = image_getOrLoad( image_name, rid );
- spin_lock( &client->lock );
- client->image = image;
- spin_unlock( &client->lock );
- if ( image == NULL ) {
- //logadd( LOG_DEBUG1, "Client requested non-existent image '%s' (rid:%d), rejected\n", image_name, (int)rid );
- } else if ( !image->working ) {
- logadd( LOG_DEBUG1, "Client %s requested non-working image '%s' (rid:%d), rejected\n",
- client->hostName, image_name, (int)rid );
- } else {
- // Image is fine so far, but occasionally drop a client if the uplink for the image is clogged or unavailable
- bOk = true;
- if ( image->cache_map != NULL ) {
- spin_lock( &image->lock );
- if ( image->uplink == NULL || image->uplink->queueLen > SERVER_UPLINK_QUEUELEN_THRES ) {
- bOk = ( rand() % 4 ) == 1;
- }
- spin_unlock( &image->lock );
- if ( image->cacheFd == -1 ) { // Wait 100ms if local caching is not working so this
- usleep( 100000 ); // server gets a penalty and is less likely to be selected
- }
+ logadd( LOG_DEBUG1, "Incomplete handshake received from %s", client->hostName );
+ }
+ } else {
+ image = image_getOrLoad( image_name, rid );
+ spin_lock( &client->lock );
+ client->image = image;
+ spin_unlock( &client->lock );
+ if ( image == NULL ) {
+ //logadd( LOG_DEBUG1, "Client requested non-existent image '%s' (rid:%d), rejected\n", image_name, (int)rid );
+ } else if ( !image->working ) {
+ logadd( LOG_DEBUG1, "Client %s requested non-working image '%s' (rid:%d), rejected\n",
+ client->hostName, image_name, (int)rid );
+ } else {
+ // Image is fine so far, but occasionally drop a client if the uplink for the image is clogged or unavailable
+ bOk = true;
+ if ( image->cache_map != NULL ) {
+ spin_lock( &image->lock );
+ if ( image->uplink == NULL || image->uplink->queueLen > SERVER_UPLINK_QUEUELEN_THRES ) {
+ bOk = ( rand() % 4 ) == 1;
}
- if ( bOk ) {
- image_file = image->readFd;
- serializer_reset_write( &payload );
- serializer_put_uint16( &payload, PROTOCOL_VERSION );
- serializer_put_string( &payload, image->name );
- serializer_put_uint16( &payload, (uint16_t)image->rid );
- serializer_put_uint64( &payload, image->virtualFilesize );
- reply.cmd = CMD_SELECT_IMAGE;
- reply.size = serializer_get_written_length( &payload );
- if ( !send_reply( client->sock, &reply, &payload ) ) {
- bOk = false;
- }
+ spin_unlock( &image->lock );
+ if ( image->cacheFd == -1 ) { // Wait 100ms if local caching is not working so this
+ usleep( 100000 ); // server gets a penalty and is less likely to be selected
+ }
+ }
+ if ( bOk ) {
+ image_file = image->readFd;
+ serializer_reset_write( &payload );
+ serializer_put_uint16( &payload, PROTOCOL_VERSION );
+ serializer_put_string( &payload, image->name );
+ serializer_put_uint16( &payload, (uint16_t)image->rid );
+ serializer_put_uint64( &payload, image->virtualFilesize );
+ reply.cmd = CMD_SELECT_IMAGE;
+ reply.size = serializer_get_written_length( &payload );
+ if ( !send_reply( client->sock, &reply, &payload ) ) {
+ bOk = false;
}
}
}
}
- } else {
- fixup_request( request );
- if ( strncmp( (char*)&request, "GET ", 4 ) == 0 || strncmp( (char*)&request, "POST ", 5 ) == 0 ) {
- rpc_sendStatsJson( client->sock );
- } else {
- // Unknown request
- logadd( LOG_DEBUG1, "Client %s sent invalid handshake", client->hostName );
- }
}
if ( bOk ) {
@@ -486,5 +521,166 @@ exit_client_cleanup: ;
net_updateGlobalSentStatsFromClient( client ); // Don't need client's lock here as it's not active anymore
dnbd3_freeClient( client ); // This will also call image_release on client->image
return NULL ;
+fail_preadd: ;
+ close( client->sock );
+ free( client );
+ return NULL;
+}
+
+json_t* net_clientsToJson()
+{
+ json_t *jsonClients = json_array();
+ json_t *clientStats;
+ int i;
+ int imgId;
+ uint64_t bytesSent;
+ char host[HOSTNAMELEN];
+ host[HOSTNAMELEN-1] = '\0';
+
+ spin_lock( &_clients_lock );
+ for ( i = 0; i < _num_clients; ++i ) {
+ if ( _clients[i] == NULL ) {
+ continue;
+ }
+ dnbd3_client_t * const client = _clients[i];
+ spin_lock( &client->lock );
+ spin_unlock( &_clients_lock );
+ // Unlock so we give other threads a chance to access the client list.
+ // We might not get an atomic snapshot of the currently connected clients,
+ // but that doesn't really make a difference anyways.
+ if ( client->image == NULL ) {
+ spin_unlock( &client->lock );
+ imgId = -1;
+ } else {
+ strncpy( host, client->hostName, HOSTNAMELEN - 1 );
+ imgId = client->image->id;
+ spin_lock( &client->statsLock );
+ spin_unlock( &client->lock );
+ bytesSent = client->bytesSent;
+ net_updateGlobalSentStatsFromClient( client ); // Do this since we read the totalBytesSent counter later
+ spin_unlock( &client->statsLock );
+ }
+ if ( imgId != -1 ) {
+ clientStats = json_pack( "{sssisI}",
+ "address", host,
+ "imageId", imgId,
+ "bytesSent", (json_int_t)bytesSent );
+ json_array_append_new( jsonClients, clientStats );
+ }
+ spin_lock( &_clients_lock );
+ }
+ spin_unlock( &_clients_lock );
+ return jsonClients;
+}
+
+void net_disconnectAll()
+{
+ int i;
+ spin_lock( &_clients_lock );
+ for (i = 0; i < _num_clients; ++i) {
+ if ( _clients[i] == NULL ) continue;
+ dnbd3_client_t * const client = _clients[i];
+ spin_lock( &client->lock );
+ if ( client->sock >= 0 ) shutdown( client->sock, SHUT_RDWR );
+ spin_unlock( &client->lock );
+ }
+ spin_unlock( &_clients_lock );
+}
+
+void net_waitForAllDisconnected()
+{
+ int retries = 10, count, i;
+ do {
+ count = 0;
+ spin_lock( &_clients_lock );
+ for (i = 0; i < _num_clients; ++i) {
+ if ( _clients[i] == NULL ) continue;
+ count++;
+ }
+ spin_unlock( &_clients_lock );
+ if ( count != 0 ) {
+ logadd( LOG_INFO, "%d clients still active...\n", count );
+ sleep( 1 );
+ }
+ } while ( count != 0 && --retries > 0 );
+ _num_clients = 0;
+}
+
+/* +++
+ * Client list.
+ *
+ * Adding and removing clients.
+ */
+
+/**
+ * Remove a client from the clients array
+ * Locks on: _clients_lock
+ */
+static void dnbd3_removeClient(dnbd3_client_t *client)
+{
+ int i;
+ spin_lock( &_clients_lock );
+ for ( i = _num_clients - 1; i >= 0; --i ) {
+ if ( _clients[i] == client ) {
+ _clients[i] = NULL;
+ }
+ if ( _clients[i] == NULL && i + 1 == _num_clients ) --_num_clients;
+ }
+ spin_unlock( &_clients_lock );
+}
+
+/**
+ * Free the client struct recursively.
+ * !! Make sure to call this function after removing the client from _dnbd3_clients !!
+ * Locks on: _clients[].lock, _images[].lock
+ * might call functions that lock on _images, _image[], uplink.queueLock, client.sendMutex
+ */
+static dnbd3_client_t* dnbd3_freeClient(dnbd3_client_t *client)
+{
+ spin_lock( &client->lock );
+ pthread_mutex_lock( &client->sendMutex );
+ if ( client->sock != -1 ) close( client->sock );
+ client->sock = -1;
+ pthread_mutex_unlock( &client->sendMutex );
+ spin_lock( &client->statsLock );
+ spin_unlock( &client->statsLock );
+ if ( client->image != NULL ) {
+ spin_lock( &client->image->lock );
+ if ( client->image->uplink != NULL ) uplink_removeClient( client->image->uplink, client );
+ spin_unlock( &client->image->lock );
+ client->image = image_release( client->image );
+ }
+ spin_unlock( &client->lock );
+ spin_destroy( &client->lock );
+ spin_destroy( &client->statsLock );
+ pthread_mutex_destroy( &client->sendMutex );
+ free( client );
+ return NULL ;
+}
+
+//###//
+
+/**
+ * Add client to the clients array.
+ * Locks on: _clients_lock
+ */
+static bool dnbd3_addClient(dnbd3_client_t *client)
+{
+ int i;
+ spin_lock( &_clients_lock );
+ for (i = 0; i < _num_clients; ++i) {
+ if ( _clients[i] != NULL ) continue;
+ _clients[i] = client;
+ spin_unlock( &_clients_lock );
+ return true;
+ }
+ if ( _num_clients >= SERVER_MAX_CLIENTS ) {
+ spin_unlock( &_clients_lock );
+ logadd( LOG_ERROR, "Maximum number of clients reached!" );
+ return false;
+ }
+ _clients[_num_clients++] = client;
+ spin_unlock( &_clients_lock );
+ return true;
}
diff --git a/src/server/net.h b/src/server/net.h
index b8c850d..51f4db8 100644
--- a/src/server/net.h
+++ b/src/server/net.h
@@ -23,12 +23,22 @@
#include "globals.h"
+struct json_t;
+
void net_init();
+void* net_handleNewConnection(void *clientPtr);
+
void net_updateGlobalSentStatsFromClient(dnbd3_client_t * const client);
uint64_t net_getTotalBytesSent();
-void *net_client_handler(void *client_socket);
+void* net_client_handler(void *client_socket);
+
+struct json_t* net_clientsToJson();
+
+void net_disconnectAll();
+
+void net_waitForAllDisconnected();
#endif /* NET_H_ */
diff --git a/src/server/rpc.c b/src/server/rpc.c
index 0bef7ca..5c295f4 100644
--- a/src/server/rpc.c
+++ b/src/server/rpc.c
@@ -6,12 +6,12 @@
#include "image.h"
#include "../shared/sockhelper.h"
-static void clientsToJson(json_t *jsonClients);
+#include <jansson.h>
void rpc_sendStatsJson(int sock)
{
- json_t *jsonClients = json_array();
- clientsToJson( jsonClients );
+ // Call this first because it will update the total bytes sent counter
+ json_t *jsonClients = net_clientsToJson();
const uint64_t bytesReceived = uplink_getTotalBytesReceived();
const uint64_t bytesSent = net_getTotalBytesSent();
const int uptime = dnbd3_serverUptime();
@@ -40,47 +40,3 @@ void rpc_sendStatsJson(int sock)
free( jsonString );
}
-static void clientsToJson(json_t *jsonClients)
-{
- json_t *clientStats;
- int i;
- int imgId;
- uint64_t bytesSent;
- char host[HOSTNAMELEN];
- host[HOSTNAMELEN-1] = '\0';
-
- spin_lock( &_clients_lock );
- for ( i = 0; i < _num_clients; ++i ) {
- if ( _clients[i] == NULL ) {
- continue;
- }
- dnbd3_client_t * const client = _clients[i];
- spin_lock( &client->lock );
- spin_unlock( &_clients_lock );
- // Unlock so we give other threads a chance to access the client list.
- // We might not get an atomic snapshot of the currently connected clients,
- // but that doesn't really make a difference anyways.
- if ( client->image == NULL ) {
- spin_unlock( &client->lock );
- imgId = -1;
- } else {
- strncpy( host, client->hostName, HOSTNAMELEN - 1 );
- imgId = client->image->id;
- spin_lock( &client->statsLock );
- spin_unlock( &client->lock );
- bytesSent = client->bytesSent;
- net_updateGlobalSentStatsFromClient( client ); // Do this since we read the totalBytesSent counter later
- spin_unlock( &client->statsLock );
- }
- if ( imgId != -1 ) {
- clientStats = json_pack( "{sssisI}",
- "address", host,
- "imageId", imgId,
- "bytesSent", (json_int_t)bytesSent );
- json_array_append_new( jsonClients, clientStats );
- }
- spin_lock( &_clients_lock );
- }
- spin_unlock( &_clients_lock );
-}
-
diff --git a/src/server/server.c b/src/server/server.c
index 4fa4be8..bfff659 100644
--- a/src/server/server.c
+++ b/src/server/server.c
@@ -44,17 +44,14 @@
poll_list_t *listeners = NULL;
-dnbd3_client_t *_clients[SERVER_MAX_CLIENTS];
-int _num_clients = 0;
-pthread_spinlock_t _clients_lock;
-
/**
* Time the server was started
*/
static time_t startupTime = 0;
static bool sigReload = false, sigLogCycle = false;
-static bool dnbd3_addClient(dnbd3_client_t *client);
+static dnbd3_client_t* dnbd3_prepareClient(struct sockaddr_storage *client, int fd);
+
static void dnbd3_handleSignal(int signum);
static void* server_asyncImageListLoad(void *data);
@@ -97,7 +94,7 @@ void dnbd3_printVersion()
*/
void dnbd3_cleanup()
{
- int i, count, retries;
+ int retries;
_shutdown = true;
debug_locks_stop_watchdog();
@@ -107,15 +104,7 @@ void dnbd3_cleanup()
listeners = NULL;
// Kill connection to all clients
- spin_lock( &_clients_lock );
- for (i = 0; i < _num_clients; ++i) {
- if ( _clients[i] == NULL ) continue;
- dnbd3_client_t * const client = _clients[i];
- spin_lock( &client->lock );
- if ( client->sock >= 0 ) shutdown( client->sock, SHUT_RDWR );
- spin_unlock( &client->lock );
- }
- spin_unlock( &_clients_lock );
+ net_disconnectAll();
// Disable threadpool
threadpool_close();
@@ -130,21 +119,7 @@ void dnbd3_cleanup()
integrity_shutdown();
// Wait for clients to disconnect
- retries = 10;
- do {
- count = 0;
- spin_lock( &_clients_lock );
- for (i = 0; i < _num_clients; ++i) {
- if ( _clients[i] == NULL ) continue;
- count++;
- }
- spin_unlock( &_clients_lock );
- if ( count != 0 ) {
- logadd( LOG_INFO, "%d clients still active...\n", count );
- sleep( 1 );
- }
- } while ( count != 0 && --retries > 0 );
- _num_clients = 0;
+ net_waitForAllDisconnected();
// Clean up images
retries = 5;
@@ -258,7 +233,6 @@ int main(int argc, char *argv[])
// No one-shot detected, normal server operation
if ( demonize ) daemon( 1, 0 );
- spin_init( &_clients_lock, PTHREAD_PROCESS_PRIVATE );
image_serverStartup();
altservers_init();
integrity_init();
@@ -344,23 +318,15 @@ int main(int argc, char *argv[])
continue;
}
- dnbd3_client_t *dnbd3_client = dnbd3_initClient( &client, fd );
+ dnbd3_client_t *dnbd3_client = dnbd3_prepareClient( &client, fd );
if ( dnbd3_client == NULL ) {
close( fd );
continue;
}
- // This has to be done before creating the thread, otherwise a race condition might occur when the new thread
- // dies faster than this thread adds the client to the list after creating the thread
- if ( !dnbd3_addClient( dnbd3_client ) ) {
- dnbd3_client = dnbd3_freeClient( dnbd3_client );
- continue;
- }
-
- if ( !threadpool_run( &net_client_handler, (void *)dnbd3_client ) ) {
- logadd( LOG_ERROR, "Could not start thread for new client." );
- dnbd3_removeClient( dnbd3_client );
- dnbd3_client = dnbd3_freeClient( dnbd3_client );
+ if ( !threadpool_run( &net_handleNewConnection, (void *)dnbd3_client ) ) {
+ logadd( LOG_ERROR, "Could not start thread for new connection." );
+ free( dnbd3_client );
continue;
}
}
@@ -369,15 +335,16 @@ int main(int argc, char *argv[])
}
/**
- * Initialize and populate the client struct - called when an incoming
- * connection is accepted
+ * Initialize and partially populate the client struct - called when an incoming
+ * connection is accepted. As this might be an HTTP request we don't initialize the
+ * locks, that would happen later once we know.
*/
-dnbd3_client_t* dnbd3_initClient(struct sockaddr_storage *client, int fd)
+static dnbd3_client_t* dnbd3_prepareClient(struct sockaddr_storage *client, int fd)
{
dnbd3_client_t *dnbd3_client = calloc( 1, sizeof(dnbd3_client_t) );
if ( dnbd3_client == NULL ) { // This will never happen thanks to memory overcommit
logadd( LOG_ERROR, "Could not alloc dnbd3_client_t for new client." );
- return NULL ;
+ return NULL;
}
if ( client->ss_family == AF_INET ) {
@@ -393,89 +360,12 @@ dnbd3_client_t* dnbd3_initClient(struct sockaddr_storage *client, int fd)
} else {
logadd( LOG_ERROR, "New client has unknown address family %d, disconnecting...", (int)client->ss_family );
free( dnbd3_client );
- return NULL ;
+ return NULL;
}
dnbd3_client->sock = fd;
- dnbd3_client->bytesSent = 0;
- dnbd3_client->tmpBytesSent = 0;
- spin_init( &dnbd3_client->lock, PTHREAD_PROCESS_PRIVATE );
- spin_init( &dnbd3_client->statsLock, PTHREAD_PROCESS_PRIVATE );
- pthread_mutex_init( &dnbd3_client->sendMutex, NULL );
return dnbd3_client;
}
-/**
- * Remove a client from the clients array
- * Locks on: _clients_lock
- */
-void dnbd3_removeClient(dnbd3_client_t *client)
-{
- int i;
- spin_lock( &_clients_lock );
- for ( i = _num_clients - 1; i >= 0; --i ) {
- if ( _clients[i] == client ) {
- _clients[i] = NULL;
- }
- if ( _clients[i] == NULL && i + 1 == _num_clients ) --_num_clients;
- }
- spin_unlock( &_clients_lock );
-}
-
-/**
- * Free the client struct recursively.
- * !! Make sure to call this function after removing the client from _dnbd3_clients !!
- * Locks on: _clients[].lock, _images[].lock
- * might call functions that lock on _images, _image[], uplink.queueLock, client.sendMutex
- */
-dnbd3_client_t* dnbd3_freeClient(dnbd3_client_t *client)
-{
- spin_lock( &client->lock );
- pthread_mutex_lock( &client->sendMutex );
- if ( client->sock != -1 ) close( client->sock );
- client->sock = -1;
- pthread_mutex_unlock( &client->sendMutex );
- spin_lock( &client->statsLock );
- spin_unlock( &client->statsLock );
- if ( client->image != NULL ) {
- spin_lock( &client->image->lock );
- if ( client->image->uplink != NULL ) uplink_removeClient( client->image->uplink, client );
- spin_unlock( &client->image->lock );
- client->image = image_release( client->image );
- }
- spin_unlock( &client->lock );
- spin_destroy( &client->lock );
- spin_destroy( &client->statsLock );
- pthread_mutex_destroy( &client->sendMutex );
- free( client );
- return NULL ;
-}
-
-//###//
-
-/**
- * Add client to the clients array.
- * Locks on: _clients_lock
- */
-static bool dnbd3_addClient(dnbd3_client_t *client)
-{
- int i;
- spin_lock( &_clients_lock );
- for (i = 0; i < _num_clients; ++i) {
- if ( _clients[i] != NULL ) continue;
- _clients[i] = client;
- spin_unlock( &_clients_lock );
- return true;
- }
- if ( _num_clients >= SERVER_MAX_CLIENTS ) {
- spin_unlock( &_clients_lock );
- logadd( LOG_ERROR, "Maximum number of clients reached!" );
- return false;
- }
- _clients[_num_clients++] = client;
- spin_unlock( &_clients_lock );
- return true;
-}
-
static void dnbd3_handleSignal(int signum)
{
if ( signum == SIGINT || signum == SIGTERM ) {
diff --git a/src/server/server.h b/src/server/server.h
index 00aa43c..54e1a24 100644
--- a/src/server/server.h
+++ b/src/server/server.h
@@ -24,19 +24,7 @@
#include "globals.h"
#include "../types.h"
-#include <stdint.h>
-#include <stdio.h>
-
-struct sockaddr_storage;
-
-extern dnbd3_client_t *_clients[];
-extern int _num_clients;
-extern pthread_spinlock_t _clients_lock;
-
void dnbd3_cleanup();
-void dnbd3_removeClient(dnbd3_client_t *client);
-dnbd3_client_t* dnbd3_freeClient(dnbd3_client_t *client);
-dnbd3_client_t* dnbd3_initClient(struct sockaddr_storage *client, int fd);
int dnbd3_serverUptime();
#if !defined(_FILE_OFFSET_BITS) || _FILE_OFFSET_BITS != 64