Adding a basic skillet to the new voice server - fixed some connection issues

This commit is contained in:
WolverinDEV 2020-08-03 13:51:44 +02:00
parent c3188cd9e5
commit 59ec412fea
5 changed files with 258 additions and 0 deletions

View File

@ -137,6 +137,8 @@ set(SOURCE_FILES
src/protocol/ringbuffer.cpp
src/protocol/AcknowledgeManager.cpp
src/protocol/PacketLossCalculator.cpp
src/lookup/ip.cpp
)
set(HEADER_FILES

23
src/lookup/ip.cpp Normal file
View File

@ -0,0 +1,23 @@
//
// Created by WolverinDEV on 01/08/2020.
//
#include "ipv4.h"
#include "ipv6.h"
lookup::ip_v4<void> storage_4{};
lookup::ip_v6<void> loop6{};
int test() {
sockaddr_in addr_4{};
storage_4.insert(addr_4, nullptr);
(void) storage_4.lookup(addr_4);
storage_4.remove(addr_4);
sockaddr_in6 addr_6{};
loop6.insert(addr_6, nullptr);
(void) loop6.lookup(addr_6);
loop6.remove(addr_6);
return 0;
}

134
src/lookup/ip.h Normal file
View File

@ -0,0 +1,134 @@
#pragma once
#include <mutex>
#include "../misc/spin_mutex.h"
namespace lookup {
template <typename T, typename addr_t, typename addr_storage_t, typename addr_converter, typename addr_cmp, typename hash_fn>
struct ip_vx {
constexpr static auto kBukkitListSize{128}; /* must be a power of two */
constexpr static auto kBukkitSize{32};
struct bucket_entry {
addr_storage_t address{};
std::shared_ptr<T> entry{};
};
struct bucket_t {
std::array<bucket_entry, kBukkitSize> entries{};
uint8_t entry_count{0};
bucket_t* next{nullptr};
};
public:
inline void insert(const addr_t& address, const std::shared_ptr<T>& value) {
auto hash = (uint8_t) hash_fn{}(address);
hash &= (uint8_t) (kBukkitListSize - 1);
bucket_t* bucket = &this->buckets[hash];
std::lock_guard lock{this->bucket_locks[hash]};
while(bucket->entry_count == kBukkitSize && bucket->next)
bucket = bucket->next;
if(bucket->entry_count == kBukkitSize)
bucket = (bucket->next = new bucket_t{});
auto& entry = bucket->entries[bucket->entry_count++];
addr_converter{}(entry.address, address);
entry.entry = value;
}
inline std::shared_ptr<T> remove(const addr_t& address) {
auto hash = (uint8_t) hash_fn{}(address);
hash &= (uint8_t) (kBukkitListSize - 1);
bucket_t *bucket = &this->buckets[hash], *next_bucket;
addr_storage_t addr{};
addr_converter{}(addr, address);
addr_cmp cmp{};
std::lock_guard lock{this->bucket_locks[hash]};
size_t entry_index;
do {
for(entry_index = 0; entry_index < bucket->entry_count; entry_index++)
if(auto& entry{bucket->entries[entry_index]}; cmp(entry.address, addr))
goto entry_found;
} while((bucket = bucket->next));
/* entry hasn't been found */
return nullptr;
entry_found:
next_bucket = bucket;
while(next_bucket->next && next_bucket->next->entry_count > 0)
next_bucket = next_bucket->next;
/* swap the entry with the last entry and just remove the value */
next_bucket->entry_count--;
std::exchange(bucket->entries[entry_index], next_bucket->entries[next_bucket->entry_count]);
return std::exchange(next_bucket->entries[next_bucket->entry_count].entry, nullptr);
}
inline void cleanup() {
for(size_t bucket_index{0}; bucket_index < kBukkitListSize; bucket_index++)
cleanup_bucket(bucket_index);
}
inline void cleanup_bucket(size_t index) {
bucket_t* delete_head;
{
std::lock_guard lock{this->bucket_locks[index]};
auto& bucket = this->buckets[index];
bucket_t* prev{nullptr}, curr{&bucket};
while(curr.entry_count > 0 && curr.next)
prev = std::exchange(curr, curr.next);
if(curr.entry_count == 0) {
prev->next = nullptr;
delete_head = curr;
} else {
return;
}
}
while(delete_head) {
auto next = delete_head->next;
delete delete_head;
delete_head = next;
}
}
[[nodiscard]] inline std::shared_ptr<T> lookup(const addr_t& address) const {
auto hash = (uint8_t) hash_fn{}(address);
hash &= (uint8_t) (kBukkitListSize - 1);
const bucket_t* bucket = &this->buckets[hash], next_bucket;
addr_storage_t addr{};
addr_converter{}(addr, address);
addr_cmp cmp{};
{
std::lock_guard lock{this->bucket_locks[hash]};
do {
for(size_t index{0}; index < bucket->entry_count; index++)
if(auto& entry{bucket->entries[index]}; cmp(entry.address, addr))
return entry.entry;
} while((bucket = bucket->next));
}
return nullptr;
}
private:
mutable std::array<spin_mutex, kBukkitListSize> bucket_locks{};
std::array<bucket_t, kBukkitListSize> buckets{};
};
}

46
src/lookup/ipv4.h Normal file
View File

@ -0,0 +1,46 @@
#pragma once
#include <netinet/in.h>
#include "./ip.h"
namespace lookup {
namespace ipv4_impl {
union uaddress_t {
struct {
uint32_t address{0};
uint16_t port{0};
};
uint64_t value;
};
struct converter {
constexpr inline void operator()(uaddress_t& result, const sockaddr_in& addr) {
result.address = addr.sin_addr.s_addr;
result.port = addr.sin_port;
}
};
struct comparator {
constexpr inline bool operator()(const uaddress_t& a, const uaddress_t& b) {
return a.value == b.value;
}
};
struct hash {
constexpr inline uint8_t operator()(const sockaddr_in& address) {
return (address.sin_addr.s_addr & 0xFFU) ^ (address.sin_port);
}
};
}
template <typename T>
using ip_v4 = ip_vx<
T,
sockaddr_in,
ipv4_impl::uaddress_t,
ipv4_impl::converter,
ipv4_impl::comparator,
ipv4_impl::hash
>;
}

53
src/lookup/ipv6.h Normal file
View File

@ -0,0 +1,53 @@
#pragma once
#include <cstring>
#include <netinet/in.h>
#include "./ip.h"
namespace lookup {
namespace ipv6_impl {
struct address_t {
union {
uint64_t address_u64[ 2];
};
uint16_t port;
};
struct converter {
constexpr inline void operator()(address_t& result, const sockaddr_in6& addr) {
auto addr_ptr = (uint64_t*) &addr.sin6_addr;
result.address_u64[0] = addr_ptr[0];
result.address_u64[1] = addr_ptr[1];
result.port = addr.sin6_port;
}
};
struct comparator {
constexpr inline bool operator()(const address_t& a, const address_t& b) {
return a.address_u64[0] == b.address_u64[0] && a.address_u64[1] == b.address_u64[1] && a.port == b.port;
}
};
struct hash {
constexpr inline uint8_t operator()(const sockaddr_in6& address) {
auto addr_ptr = (uint8_t*) &address.sin6_addr;
return (uint8_t) (addr_ptr[8] ^ addr_ptr[9]) ^ (uint8_t) (addr_ptr[15] ^ address.sin6_port);
}
};
}
template <typename T>
using ip_v6 = ip_vx<
T,
sockaddr_in6,
ipv6_impl::address_t,
ipv6_impl::converter,
ipv6_impl::comparator,
ipv6_impl::hash
>;
}