diff options
-rw-r--r-- | src/server/altservers.c | 51 | ||||
-rw-r--r-- | src/server/altservers.h | 4 | ||||
-rw-r--r-- | src/server/globals.h | 8 | ||||
-rw-r--r-- | src/server/image.c | 2 | ||||
-rw-r--r-- | src/server/net.c | 2 |
5 files changed, 49 insertions, 18 deletions
diff --git a/src/server/altservers.c b/src/server/altservers.c index 952af4f..943345c 100644 --- a/src/server/altservers.c +++ b/src/server/altservers.c @@ -23,7 +23,7 @@ static atomic_int numAltServers = 0; static pthread_mutex_t altServersLock; static void *altservers_runCheck(void *data); -static int altservers_getListForUplink(dnbd3_uplink_t *uplink, int *servers, int size, int current); +static int altservers_getListForUplink(dnbd3_uplink_t *uplink, const char *image, int *servers, int size, int current); static void altservers_findUplinkInternal(dnbd3_uplink_t *uplink); static uint32_t altservers_updateRtt(dnbd3_uplink_t *uplink, int index, uint32_t rtt); static void altservers_imageFailed(dnbd3_uplink_t *uplink, int server); @@ -86,6 +86,13 @@ static int addAltFromIni(void *countptr, const char* section, const char* key, c } } else if ( strcmp( key, "comment" ) == 0 ) { snprintf( altServers[index].comment, COMMENT_LENGTH, "%s", value ); + } else if ( strcmp( key, "namespace" ) == 0 ) { + dnbd3_ns_t *elem = malloc( sizeof(*elem) ); + elem->name = strdup( value ); + elem->len = strlen( value ); + do { + elem->next = altServers[index].nameSpaces; + } while ( !atomic_compare_exchange_weak( &altServers[index].nameSpaces, &elem->next, elem ) ); } else { logadd( LOG_DEBUG1, "Unknown key in alt-servers section: '%s'", key ); } @@ -139,6 +146,7 @@ bool altservers_add(dnbd3_host_t *host, const char *comment, const int isPrivate altServers[freeSlot].host = *host; altServers[freeSlot].isPrivate = isPrivate; altServers[freeSlot].isClientOnly = isClientOnly; + altServers[freeSlot].nameSpaces = NULL; if ( comment != NULL ) snprintf( altServers[freeSlot].comment, COMMENT_LENGTH, "%s", comment ); mutex_unlock( &altServersLock ); *index = freeSlot; @@ -171,15 +179,28 @@ void altservers_findUplinkAsync(dnbd3_uplink_t *uplink) } } +static bool isImageAllowed(dnbd3_alt_server_t *alt, const char *image) +{ + if ( alt->nameSpaces == NULL ) + return true; + for ( dnbd3_ns_t *it = alt->nameSpaces; it != NULL; it = it->next ) { + if ( strncmp( it->name, image, it->len ) == 0 ) + return true; + } + return false; +} + /** * Get <size> known (working) alt servers, ordered by network closeness * (by finding the smallest possible subnet) * Private servers are excluded, so this is what you want to call to * get a list of servers you can tell a client about */ -int altservers_getListForClient(dnbd3_host_t *host, dnbd3_server_entry_t *output, int size) +int altservers_getListForClient(dnbd3_client_t *client, dnbd3_server_entry_t *output, int size) { - if ( host == NULL || host->type == 0 || numAltServers == 0 || output == NULL || size <= 0 ) return 0; + dnbd3_host_t *host = &client->host; + if ( host->type == 0 || numAltServers == 0 || output == NULL || size <= 0 ) + return 0; int i, j; int count = 0; uint16_t scores[SERVER_MAX_ALTS] = { 0 }; @@ -188,11 +209,9 @@ int altservers_getListForClient(dnbd3_host_t *host, dnbd3_server_entry_t *output for ( i = 0; i < numAltServers; ++i ) { if ( altServers[i].host.type == 0 || altServers[i].isPrivate ) continue; // Slot is empty or uplink is for replication only - if ( host->type == altServers[i].host.type ) { - scores[i] = (uint16_t)( 10 + altservers_netCloseness( host, &altServers[i].host ) ); - } else { - scores[i] = 1; // Wrong address family - } + if ( !isImageAllowed( &altServers[i], client->image->name ) ) + continue; + scores[i] = (uint16_t)( 10 + altservers_netCloseness( host, &altServers[i].host ) ); } while ( count < size ) { i = -1; @@ -244,10 +263,10 @@ static bool isUsableForUplink( dnbd3_uplink_t *uplink, int server, ticks *now ) return fails < SERVER_BAD_UPLINK_MIN || ( rand() % fails ) < SERVER_BAD_UPLINK_MIN; } -int altservers_getHostListForReplication(dnbd3_host_t *servers, int size) +int altservers_getHostListForReplication(const char *image, dnbd3_host_t *servers, int size) { int idx[size]; - int num = altservers_getListForUplink( NULL, idx, size, -1 ); + int num = altservers_getListForUplink( NULL, image, idx, size, -1 ); for ( int i = 0; i < num; ++i ) { servers[i] = altServers[i].host; } @@ -261,7 +280,7 @@ int altservers_getHostListForReplication(dnbd3_host_t *servers, int size) * it includes private servers and ignores any "client only" servers * @param current index of server for current connection, or -1 in panic mode */ -static int altservers_getListForUplink(dnbd3_uplink_t *uplink, int *servers, int size, int current) +static int altservers_getListForUplink(dnbd3_uplink_t *uplink, const char *image, int *servers, int size, int current) { if ( size <= 0 ) return 0; @@ -272,7 +291,9 @@ static int altservers_getListForUplink(dnbd3_uplink_t *uplink, int *servers, int if ( numAltServers <= size ) { for ( int i = 0; i < numAltServers; ++i ) { if ( current == -1 || i == current || isUsableForUplink( uplink, i, &now ) ) { - servers[count++] = i; + if ( isImageAllowed( &altServers[i], image ) ) { + servers[count++] = i; + } } } } else { @@ -286,7 +307,9 @@ static int altservers_getListForUplink(dnbd3_uplink_t *uplink, int *servers, int int idx = rand() % numAltServers; if ( state[idx] != 0 ) continue; - if ( isUsableForUplink( uplink, idx, &now ) ) { + if ( !isImageAllowed( &altServers[idx], image ) ) { + state[idx] = 2; // Mark as used without adding, so it will be ignored in panic loop + } else if ( isUsableForUplink( uplink, idx, &now ) ) { servers[count++] = idx; state[idx] = 2; // Used } else { @@ -469,7 +492,7 @@ static void altservers_findUplinkInternal(dnbd3_uplink_t *uplink) current = uplink->current.index; // Current server index (or last one in panic mode) mutex_unlock( &uplink->rttLock ); // First, get 4 alt servers - numAlts = altservers_getListForUplink( uplink, servers, ALTS, panic ? -1 : current ); + numAlts = altservers_getListForUplink( uplink, uplink->image->name, servers, ALTS, panic ? -1 : current ); // If we're already connected and only got one server anyways, there isn't much to do if ( numAlts == 0 || ( numAlts == 1 && !panic ) ) { uplink->rttTestResult = RTT_DONTCHANGE; diff --git a/src/server/altservers.h b/src/server/altservers.h index 1e1f119..8e29aaa 100644 --- a/src/server/altservers.h +++ b/src/server/altservers.h @@ -15,9 +15,9 @@ void altservers_findUplinkAsync(dnbd3_uplink_t *uplink); void altservers_findUplink(dnbd3_uplink_t *uplink); -int altservers_getListForClient(dnbd3_host_t *host, dnbd3_server_entry_t *output, int size); +int altservers_getListForClient(dnbd3_client_t *client, dnbd3_server_entry_t *output, int size); -int altservers_getHostListForReplication(dnbd3_host_t *servers, int size); +int altservers_getHostListForReplication(const char *image, dnbd3_host_t *servers, int size); bool altservers_toString(int server, char *buffer, size_t len); diff --git a/src/server/globals.h b/src/server/globals.h index 221af78..ebdc1c7 100644 --- a/src/server/globals.h +++ b/src/server/globals.h @@ -31,6 +31,13 @@ typedef struct uint8_t hopCount; // How many hops this request has already taken across proxies } dnbd3_queued_request_t; +typedef struct _ns +{ + struct _ns *next; + char *name; + size_t len; +} dnbd3_ns_t; + typedef struct { int fails; // Hard fail: Connection failed @@ -41,6 +48,7 @@ typedef struct ticks lastFail; // Last hard fail dnbd3_host_t host; char comment[COMMENT_LENGTH]; + _Atomic(dnbd3_ns_t *) nameSpaces; // Linked list of name spaces } dnbd3_alt_server_t; typedef struct diff --git a/src/server/image.c b/src/server/image.c index bdb910d..86e6b87 100644 --- a/src/server/image.c +++ b/src/server/image.c @@ -1204,7 +1204,7 @@ static dnbd3_image_t *loadImageProxy(char * const name, const uint16_t revision, dnbd3_host_t servers[REP_NUM_SRV]; int uplinkSock = -1; dnbd3_host_t uplinkServer; - const int count = altservers_getHostListForReplication( servers, REP_NUM_SRV ); + const int count = altservers_getHostListForReplication( name, servers, REP_NUM_SRV ); uint16_t remoteProtocolVersion; uint16_t remoteRid = revision; uint64_t remoteImageSize; diff --git a/src/server/net.c b/src/server/net.c index 00c9a8d..aba4e7d 100644 --- a/src/server/net.c +++ b/src/server/net.c @@ -477,7 +477,7 @@ void* net_handleNewConnection(void *clientPtr) case CMD_GET_SERVERS: // Build list of known working alt servers - num = altservers_getListForClient( &client->host, server_list, NUMBER_SERVERS ); + num = altservers_getListForClient( client, server_list, NUMBER_SERVERS ); reply.cmd = CMD_GET_SERVERS; reply.size = (uint32_t)( num * sizeof(dnbd3_server_entry_t) ); mutex_lock( &client->sendMutex ); |