Adding a basic skillet to the new voice server - fixed some connection issues
This commit is contained in:
parent
c3188cd9e5
commit
59ec412fea
@ -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
23
src/lookup/ip.cpp
Normal 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
134
src/lookup/ip.h
Normal 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
46
src/lookup/ipv4.h
Normal 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
53
src/lookup/ipv6.h
Normal 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
|
||||
>;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user