From 8d96868945f3d52b44de02e2c468766c46693aef Mon Sep 17 00:00:00 2001 From: Simon Rettberg Date: Thu, 7 Sep 2017 15:50:50 +0200 Subject: [SERVER] Refactor: Move client list to net.* and isolate --- src/server/helper.c | 1 + src/server/image.c | 1 + src/server/image.h | 5 +- src/server/net.c | 316 ++++++++++++++++++++++++++++++++++++++++++---------- src/server/net.h | 12 +- src/server/rpc.c | 50 +-------- src/server/server.c | 140 +++-------------------- src/server/server.h | 12 -- 8 files changed, 290 insertions(+), 247 deletions(-) (limited to 'src/server') 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 #include #include +#include #ifdef HAVE_THREAD_NAMES #include // 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 #include #include +#include #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 + +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 #include #endif +#include + +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 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 -#include - -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 -- cgit v1.2.3-55-g7522