uint64_t group = CBAddressManagerGetGroup(self, addr);
CBRandomSeed(self->rndGenForBucketIndexes, group + self->secret); // Add the group with the secure secret generated during initialisation.
return CBSecureRandomInteger(self->rndGenForBucketIndexes) % CB_BUCKET_NUM;
}
uint64_t CBAddressManagerGetGroup(CBAddressManager * self,CBNetworkAddress * addr){
uint8_t start = 0;
int8_t bits = 16;
uint64_t group;
switch (addr->type) {
case CB_IP_I2P:
case CB_IP_TOR:
group = addr->type;
start = 6;
bits = 4;
break;
case CB_IP_SITT:
case CB_IP_RFC6052:
group = CB_IP_IPv4;
start = 12;
break;
case CB_IP_6TO4:
group = CB_IP_IPv4;
start = 2;
break;
case CB_IP_TEREDO:
return CB_IP_IPv4 | ((CBByteArrayGetByte(addr->ip, 12) ^ 0xFF) << 8) | ((CBByteArrayGetByte(addr->ip, 13) ^ 0xFF) << 16);
case CB_IP_HENET:
group = CB_IP_IPv6;
bits = 36;
break;
case CB_IP_IPv6:
group = CB_IP_IPv6;
bits = 32;
break;
case CB_IP_IPv4:
group = CB_IP_IPv4;
start = 12;
break;
default:
group = addr->type;
bits = 0;
break;
}
uint8_t x = 8;
for (; bits >= 8; bits -= 8, x += 8, start++)
group |= CBByteArrayGetByte(addr->ip, start) << x;
if (bits > 0)
group |= (CBByteArrayGetByte(addr->ip, start) | ((1 << bits) - 1)) << x;
return group;
}
bool CBAddressManagerSetup(CBAddressManager * self){
// Allocate buckets
self->buckets = malloc(sizeof(*self->buckets) * CB_BUCKET_NUM);
// Create mutexes
if(CBNewMutex(&self->addressMutex)){
if(CBNewMutex(&self->nodesMutex)){
// Create random number generators.
self->rndGen = CBNewSecureRandomGenerator();
if (self->rndGen) {
CBSecureRandomSeed(self->rndGen); // Cryptographically secure.
self->secret = CBSecureRandomInteger(self->rndGen);
self->rndGenForBucketIndexes = CBNewSecureRandomGenerator();
if (self->rndGenForBucketIndexes) {
return true;
}
CBFreeSecureRandomGenerator(self->rndGen);
}
CBFreeMutex(self->addressMutex);
CBFreeMutex(self->nodesMutex);
}else{
CBGetMessage(self)->events->onErrorReceived(CB_ERROR_NETWORK_COMMUNICATOR_MUTEX_CREATE_FAIL,"The CBAddressManager 'nodesMutex' could not be created.");
}
CBFreeMutex(self->addressMutex);
}else{
CBGetMessage(self)->events->onErrorReceived(CB_ERROR_NETWORK_COMMUNICATOR_MUTEX_CREATE_FAIL,"The CBAddressManager 'addressMutex' could not be created.");
}
return false;
}
void CBAddressManagerTakeAddress(CBAddressManager * self,CBNetworkAddress * addr){
// Find the bucket for this address.
CBBucket * bucket = self->buckets + CBAddressManagerGetBucketIndex(self, addr);
CBMutexLock(self->addressMutex); // Use mutex lock when modifying the addresses
// Find insersion point for address
uint16_t insert = 0;
for (; insert < bucket->addrNum; insert++) {
if (bucket->addresses[insert]->score > addr->score)
// Insert here
break;
}
if (bucket->addrNum == self->maxAddressesInBucket) {
// A lot of addresses stored, remove random address but with bias to a low scoring address.
uint16_t remove = (CBSecureRandomInteger(self->rndGen) % bucket->addrNum);
remove *= remove;
remove /= bucket->addrNum;
// Release address
CBReleaseObject(&bucket->addresses[remove]);
if (insert < remove)
// Insersion happens below removal. Move memory up to overwrite removed address and make space to insert.
memmove(bucket->addresses + insert + 1, bucket->addresses + insert, remove-insert);
else if (insert > remove){
// Insersion happens above removal. Move memory down to overwrite removed address and make space to insert.
memmove(bucket->addresses + remove, bucket->addresses + remove + 1, insert-remove);
insert--; // Move insert down since we moved memory down.
}
}else{
bucket->addrNum++;
// Move memory up to allow insertion of address.
memmove(bucket->addresses + insert + 1, bucket->addresses + insert, bucket->addrNum - insert - 1);
}
bucket->addresses[insert] = addr;
CBMutexUnlock(self->addressMutex); // Now other threads can access the addresses.
}