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

This commit is contained in:
WolverinDEV 2020-08-03 13:51:47 +02:00
parent e49b091b92
commit fa7a390fe3
16 changed files with 190 additions and 107 deletions

View File

@ -157,7 +157,10 @@ set(SERVER_SOURCE_FILES
src/terminal/PipedTerminal.cpp src/terminal/PipedTerminal.cpp
src/server/voice/UDPVoiceServer.cpp
src/server/voice/DatagramPacket.cpp
) )
if (COMPILE_WEB_CLIENT) if (COMPILE_WEB_CLIENT)
add_definitions(-DCOMPILE_WEB_CLIENT) add_definitions(-DCOMPILE_WEB_CLIENT)

View File

@ -583,8 +583,10 @@ command_result ConnectedClient::handleCommandServerGroupClientList(Command &cmd)
notify[index]["client_unique_identifier"] = clientEntry.uid; notify[index]["client_unique_identifier"] = clientEntry.uid;
index++; index++;
} }
if(index == 0)
if(index == 0 && this->getType() != ClientType::CLIENT_TEAMSPEAK) {
return ts::command_result{error::database_empty_result}; return ts::command_result{error::database_empty_result};
}
this->sendCommand(notify); this->sendCommand(notify);
return command_result{error::ok}; return command_result{error::ok};

View File

@ -107,7 +107,7 @@ CryptSetupHandler::CommandResult CryptSetupHandler::handleCommandClientInitIv(co
client->state = ConnectionState::INIT_HIGH; client->state = ConnectionState::INIT_HIGH;
} else if(client->state == ConnectionState::INIT_HIGH) { } else if(client->state == ConnectionState::INIT_HIGH) {
logTrace(client->getServerId(), "{} Received a duplicated initiv. It seems like our initivexpand2 hasn't yet reached the client. The acknowledge handler should handle this issue for us.", CLIENT_STR_LOG_PREFIX_(client)); logTrace(client->getServerId(), "{} Received a duplicated initiv. It seems like our initivexpand2 hasn't yet reached the client. The acknowledge handler should handle this issue for us.", CLIENT_STR_LOG_PREFIX_(client));
return command_result{error::ok}; return CommandHandleResult::CONSUME_COMMAND; /* we don't want to send an error id=0 msg=ok */
} else { } else {
client->state = ConnectionState::INIT_HIGH; client->state = ConnectionState::INIT_HIGH;
} }

View File

@ -91,7 +91,7 @@ namespace ts {
int socket_id_{0}; int socket_id_{0};
sockaddr_storage remote_address_{}; sockaddr_storage remote_address_{};
io::pktinfo_storage remote_address_info_{}; server::udp::pktinfo_storage remote_address_info_{};
CryptHandler crypt_handler; /* access to CryptHandler is thread save */ CryptHandler crypt_handler; /* access to CryptHandler is thread save */
server::client::PacketStatistics packet_statistics_{}; server::client::PacketStatistics packet_statistics_{};

View File

@ -47,19 +47,19 @@ void MusicBotManager::cleanup_client_bots(ts::ClientDbId clientid) {
this->deleteBot(bot); this->deleteBot(bot);
} }
std::deque<std::shared_ptr<server::MusicClient>> MusicBotManager::available_bots() { std::deque<std::shared_ptr<ts::server::MusicClient>> MusicBotManager::available_bots() {
lock_guard lock(music_bots_lock); lock_guard lock(music_bots_lock);
return this->music_bots; return this->music_bots;
} }
std::shared_ptr<server::MusicClient> MusicBotManager::find_bot_by_playlist(const std::shared_ptr<ts::music::PlayablePlaylist> &playlist) { std::shared_ptr<ts::server::MusicClient> MusicBotManager::find_bot_by_playlist(const std::shared_ptr<ts::music::PlayablePlaylist> &playlist) {
for(const auto& bot : this->available_bots()) for(const auto& bot : this->available_bots())
if(bot->playlist() == playlist) if(bot->playlist() == playlist)
return bot; return bot;
return nullptr; return nullptr;
} }
std::deque<std::shared_ptr<server::MusicClient>> MusicBotManager::listBots(ClientDbId clid) { std::deque<std::shared_ptr<ts::server::MusicClient>> MusicBotManager::listBots(ClientDbId clid) {
lock_guard lock(music_bots_lock); lock_guard lock(music_bots_lock);
std::deque<std::shared_ptr<server::MusicClient>> res; std::deque<std::shared_ptr<server::MusicClient>> res;
for(const auto& bot : this->music_bots) for(const auto& bot : this->music_bots)

View File

@ -72,7 +72,7 @@ void POWHandler::handle_datagram(int socket, const sockaddr_storage &address,msg
client->socket = socket; client->socket = socket;
client->client_version = be2le32(&buffer[MAC_SIZE + CLIENT_HEADER_SIZE]); client->client_version = be2le32(&buffer[MAC_SIZE + CLIENT_HEADER_SIZE]);
memcpy(&client->address, &address, sizeof(client->address)); memcpy(&client->address, &address, sizeof(client->address));
io::DatagramPacket::extract_info(info, client->address_info); udp::DatagramPacket::extract_info(info, client->address_info);
client->state = LowHandshakeState::COOKIE_GET; client->state = LowHandshakeState::COOKIE_GET;
} }
@ -126,7 +126,7 @@ void POWHandler::handle_datagram(int socket, const sockaddr_storage &address,msg
} }
void POWHandler::send_data(const std::shared_ptr<ts::server::POWHandler::Client> &client, const pipes::buffer_view &buffer) { void POWHandler::send_data(const std::shared_ptr<ts::server::POWHandler::Client> &client, const pipes::buffer_view &buffer) {
auto datagram = io::DatagramPacket::create(client->address, client->address_info, buffer.length() + MAC_SIZE + SERVER_HEADER_SIZE, nullptr); auto datagram = udp::DatagramPacket::create(client->address, client->address_info, buffer.length() + MAC_SIZE + SERVER_HEADER_SIZE, nullptr);
if(!datagram) return; //Should never happen if(!datagram) return; //Should never happen
/* first 8 bytes mac */ /* first 8 bytes mac */

View File

@ -27,7 +27,7 @@ namespace ts::server {
struct Client { struct Client {
int socket; int socket;
sockaddr_storage address; sockaddr_storage address;
io::pktinfo_storage address_info; udp::pktinfo_storage address_info;
std::timed_mutex handle_lock; std::timed_mutex handle_lock;
std::chrono::system_clock::time_point last_packet; std::chrono::system_clock::time_point last_packet;

View File

@ -242,7 +242,7 @@ void IOServerHandler::invoke_write(const std::shared_ptr<ts::server::VoiceClient
event_add(event->event_write, nullptr); event_add(event->event_write, nullptr);
} }
void IOServerHandler::send_datagram(ts::io::datagram_packet_t datagram, int socket) { void IOServerHandler::send_datagram(server::udp::DatagramPacket* datagram, int socket) {
if(this->event_loop_events.empty()) if(this->event_loop_events.empty())
return; /* TODO any kind of error or warning? */ return; /* TODO any kind of error or warning? */
@ -330,30 +330,4 @@ void VoiceIOManager::dispatchBase(shared_ptr<IOEventLoop> self) {
this->ioExecutorNotify.notify_all(); /* let everybody know we're done */ this->ioExecutorNotify.notify_all(); /* let everybody know we're done */
} }
}
DatagramPacket* DatagramPacket::create(const sockaddr_storage &address, const pktinfo_storage& address_info, size_t length, const uint8_t *data) {
auto membuf = buffer::allocate_buffer(sizeof(DatagramPacket) + length);
auto instance = membuf.data_ptr<DatagramPacket>();
new (&instance->self_buffer) pipes::buffer;
instance->next_packet = nullptr;
instance->self_buffer = membuf;
memcpy(&instance->address, &address, sizeof(address));
if(address.ss_family == AF_INET6) {
memcpy(&instance->address_info, &address_info, sizeof(in6_pktinfo));
} else {
memcpy(&instance->address_info, &address_info, sizeof(in_pktinfo));
}
instance->data_length = length;
if(data)
memcpy(&instance->data, data, length);
return instance;
}
void DatagramPacket::destory(ts::io::datagram_packet_t packet) {
packet->self_buffer.~buffer();
} }

View File

@ -7,6 +7,7 @@
#include <pipes/buffer.h> #include <pipes/buffer.h>
#include <misc/spin_mutex.h> #include <misc/spin_mutex.h>
#include <ThreadPool/Mutex.h> #include <ThreadPool/Mutex.h>
#include <src/server/voice/DatagramPacket.h>
namespace ts { namespace ts {
namespace server { namespace server {
@ -15,38 +16,6 @@ namespace ts {
class VoiceClient; class VoiceClient;
} }
namespace io { namespace io {
union pktinfo_storage {
in_pktinfo v4;
in6_pktinfo v6;
};
struct DatagramPacket;
typedef DatagramPacket* datagram_packet_t;
struct DatagramPacket {
private:
pipes::buffer self_buffer;
public:
datagram_packet_t next_packet;
sockaddr_storage address;
pktinfo_storage address_info;
size_t data_length;
uint8_t data[0];
static void destory(datagram_packet_t);
static datagram_packet_t create(const sockaddr_storage& address, const pktinfo_storage& address_info, size_t length, const uint8_t* data);
static int extract_info(msghdr& /* header */, pktinfo_storage& /* info */);
DatagramPacket() = delete;
DatagramPacket(const DatagramPacket&) = delete;
DatagramPacket(DatagramPacket&&) = delete;
~DatagramPacket() = delete;
};
class VoiceIOManager; class VoiceIOManager;
class IOServerHandler; class IOServerHandler;
struct IOEventLoopEntry; struct IOEventLoopEntry;
@ -81,12 +50,12 @@ namespace ts {
::event* event_write = nullptr; ::event* event_write = nullptr;
spin_mutex write_queue_lock; spin_mutex write_queue_lock;
datagram_packet_t dg_write_queue_head = nullptr; server::udp::DatagramPacket* dg_write_queue_head = nullptr;
datagram_packet_t dg_write_queue_tail = nullptr; server::udp::DatagramPacket* dg_write_queue_tail = nullptr;
std::deque<std::weak_ptr<server::VoiceClient>> voice_write_queue; std::deque<std::weak_ptr<server::VoiceClient>> voice_write_queue;
inline datagram_packet_t pop_dg_write_queue() { inline server::udp::DatagramPacket* pop_dg_write_queue() {
std::lock_guard lock(this->write_queue_lock); std::lock_guard lock(this->write_queue_lock);
if(!this->dg_write_queue_head) if(!this->dg_write_queue_head)
return nullptr; return nullptr;
@ -102,7 +71,7 @@ namespace ts {
return packet; return packet;
} }
inline void push_dg_write_queue(datagram_packet_t packet) { inline void push_dg_write_queue(server::udp::DatagramPacket* packet) {
std::lock_guard lock(this->write_queue_lock); std::lock_guard lock(this->write_queue_lock);
if(this->dg_write_queue_tail) { if(this->dg_write_queue_tail) {
this->dg_write_queue_tail->next_packet = packet; this->dg_write_queue_tail->next_packet = packet;
@ -193,7 +162,7 @@ namespace ts {
void invoke_write(const std::shared_ptr<server::VoiceClient>& /* client */); void invoke_write(const std::shared_ptr<server::VoiceClient>& /* client */);
int resolve_file_descriptor(const std::shared_ptr<server::VoiceClient>& /* client */); int resolve_file_descriptor(const std::shared_ptr<server::VoiceClient>& /* client */);
void send_datagram(datagram_packet_t /* packet */, int /* socket */); void send_datagram(server::udp::DatagramPacket* /* packet */, int /* socket */);
private: private:
std::shared_ptr<IOEventLoopEvents> create_event_loop_events(const std::shared_ptr<IOEventLoop> &); std::shared_ptr<IOEventLoopEvents> create_event_loop_events(const std::shared_ptr<IOEventLoop> &);

View File

@ -239,21 +239,6 @@ static union {
uint64_t integral; uint64_t integral;
} TS3INIT; } TS3INIT;
int io::DatagramPacket::extract_info(msghdr &message, pktinfo_storage &info) {
for (cmsghdr* cmsg = CMSG_FIRSTHDR(&message); cmsg != nullptr; cmsg = CMSG_NXTHDR(&message, cmsg)) { // iterate through all the control headers
if(cmsg->cmsg_type != IP_PKTINFO && cmsg->cmsg_type != IPV6_PKTINFO) continue;
if(cmsg->cmsg_level == IPPROTO_IP) {
memcpy(&info, (void*) CMSG_DATA(cmsg), sizeof(in_pktinfo));
return 4;
} else if(cmsg->cmsg_level == IPPROTO_IPV6) {
memcpy(&info, (void*) CMSG_DATA(cmsg), sizeof(in6_pktinfo));
return 6;
}
}
return 0;
}
void VoiceServer::handleMessageRead(int fd, short events, void *_event_handle) { void VoiceServer::handleMessageRead(int fd, short events, void *_event_handle) {
auto event_handle = (io::IOEventLoopEntry*) _event_handle; auto event_handle = (io::IOEventLoopEntry*) _event_handle;
auto voice_server = event_handle->voice_server; auto voice_server = event_handle->voice_server;
@ -332,7 +317,7 @@ void VoiceServer::handleMessageRead(int fd, short events, void *_event_handle) {
auto command = "dummy_ipchange old_ip=" + old_address + " new_ip=" + new_address; auto command = "dummy_ipchange old_ip=" + old_address + " new_ip=" + new_address;
client->server_command_executor().force_insert_command(pipes::buffer_view{command.data(), command.length()}); client->server_command_executor().force_insert_command(pipes::buffer_view{command.data(), command.length()});
memcpy(&client->remote_address, &remote_address, sizeof(remote_address)); memcpy(&client->remote_address, &remote_address, sizeof(remote_address));
io::DatagramPacket::extract_info(message, client->connection->remote_address_info_); udp::DatagramPacket::extract_info(message, client->connection->remote_address_info_);
} }
} else { } else {
continue; /* we've no clue */ continue; /* we've no clue */
@ -382,7 +367,7 @@ struct IOData {
}; };
template <int MHS> template <int MHS>
inline ssize_t write_datagram(IOData<MHS>& io, const sockaddr_storage& address, io::pktinfo_storage* info, size_t length, const void* buffer) { inline ssize_t write_datagram(IOData<MHS>& io, const sockaddr_storage& address, udp::pktinfo_storage* info, size_t length, const void* buffer) {
io.message.msg_flags = 0; io.message.msg_flags = 0;
io.message.msg_name = (void*) &address; io.message.msg_name = (void*) &address;
io.message.msg_namelen = address.ss_family == AF_INET ? sizeof(sockaddr_in) : sizeof(sockaddr_in6); io.message.msg_namelen = address.ss_family == AF_INET ? sizeof(sockaddr_in) : sizeof(sockaddr_in6);
@ -514,21 +499,21 @@ void VoiceServer::handleMessageWrite(int fd, short events, void *_event_handle)
/* write all manually specified datagram packets */ /* write all manually specified datagram packets */
{ {
auto write_timeout = system_clock::now() + microseconds(2500); /* read 2.5ms long at a time or 'till nothing more is there */ auto write_timeout = system_clock::now() + microseconds(2500); /* read 2.5ms long at a time or 'till nothing more is there */
io::datagram_packet_t packet; udp::DatagramPacket* packet;
while(system_clock::now() <= write_timeout && (packet = event_handle->pop_dg_write_queue())) { while(system_clock::now() <= write_timeout && (packet = event_handle->pop_dg_write_queue())) {
ssize_t res = write_datagram(io, packet->address, &packet->address_info, packet->data_length, packet->data); ssize_t res = write_datagram(io, packet->address, &packet->pktinfo, packet->data_length, packet->data);
if(res != packet->data_length) { if(res != packet->data_length) {
if(errno == EAGAIN) { if(errno == EAGAIN) {
event_handle->push_dg_write_queue(packet); event_handle->push_dg_write_queue(packet);
} else } else
io::DatagramPacket::destory(packet); udp::DatagramPacket::destroy(packet);
logError(voice_server->server->getServerId(), "Failed to send datagram. Wrote {} out of {}. {}/{}", res, packet->data_length, errno, strerror(errno)); logError(voice_server->server->getServerId(), "Failed to send datagram. Wrote {} out of {}. {}/{}", res, packet->data_length, errno, strerror(errno));
retrigger = false; retrigger = false;
break; break;
} }
io::DatagramPacket::destory(packet); udp::DatagramPacket::destroy(packet);
} }
retrigger |= packet != nullptr; /* memory stored at packet is not accessible anymore. But anyways pop_dg_write_queue returns 0 if there is nothing more */ retrigger |= packet != nullptr; /* memory stored at packet is not accessible anymore. But anyways pop_dg_write_queue returns 0 if there is nothing more */
@ -537,6 +522,6 @@ void VoiceServer::handleMessageWrite(int fd, short events, void *_event_handle)
event_add(event_handle->event_write, nullptr); event_add(event_handle->event_write, nullptr);
} }
void VoiceServer::send_datagram(int socket, io::datagram_packet_t packet) { void VoiceServer::send_datagram(int socket, udp::DatagramPacket* packet) {
this->io->send_datagram(packet, socket); this->io->send_datagram(packet, socket);
} }

View File

@ -9,6 +9,7 @@
#include <misc/net.h> #include <misc/net.h>
#include <protocol/ringbuffer.h> #include <protocol/ringbuffer.h>
#include "VoiceIOManager.h" #include "VoiceIOManager.h"
#include "./voice/DatagramPacket.h"
namespace ts { namespace ts {
namespace protocol { namespace protocol {
@ -25,8 +26,8 @@ namespace ts {
sockaddr_storage address{}; sockaddr_storage address{};
int file_descriptor = 0; int file_descriptor = 0;
inline std::string address_string() { return net::to_string(address); } [[nodiscard]] inline std::string address_string() const { return net::to_string(address); }
inline uint16_t address_port() { return net::port(address); } [[nodiscard]] inline uint16_t address_port() const { return net::port(address); }
}; };
class VoiceServer { class VoiceServer {
@ -70,25 +71,18 @@ namespace ts {
std::recursive_mutex connectionLock; std::recursive_mutex connectionLock;
std::deque<std::shared_ptr<VoiceClient>> activeConnections; std::deque<std::shared_ptr<VoiceClient>> activeConnections;
public: //lib event public:
void triggerWrite(const std::shared_ptr<VoiceClient> &); void triggerWrite(const std::shared_ptr<VoiceClient> &);
void schedule_command_handling(VoiceClient const *client); void schedule_command_handling(VoiceClient const *client);
void tickHandshakingClients(); void tickHandshakingClients();
void execute_resend(const std::chrono::system_clock::time_point& /* now */, std::chrono::system_clock::time_point& /* next resend */); void execute_resend(const std::chrono::system_clock::time_point& /* now */, std::chrono::system_clock::time_point& /* next resend */);
void send_datagram(int /* socket */, io::datagram_packet_t /* packet */); void send_datagram(int /* socket */, udp::DatagramPacket* /* packet */);
std::shared_ptr<io::IOServerHandler> io; std::shared_ptr<io::IOServerHandler> io;
private: private:
static void handleMessageRead(int, short, void *); static void handleMessageRead(int, short, void *);
static void handleMessageWrite(int, short, void *); static void handleMessageWrite(int, short, void *);
/* execute loop */
/* TODO
std::mutex execute_list_lock;
protocol::RingBuffer<ClientId, 128, uint8_t> execute_list;
void run_execute_clients();
*/
}; };
} }
} }

View File

@ -0,0 +1,48 @@
//
// Created by WolverinDEV on 02/08/2020.
//
#include <malloc.h>
#include <cstring>
#include "DatagramPacket.h"
using namespace ts::server::udp;
DatagramPacket* DatagramPacket::create(const sockaddr_storage &address, const pktinfo_storage& address_info, size_t length, const uint8_t *data) {
auto membuf = malloc(sizeof(DatagramPacket) + length);
auto instance = (DatagramPacket*) membuf;
instance->next_packet = nullptr;
memcpy(&instance->address, &address, sizeof(address));
if(address.ss_family == AF_INET6) {
memcpy(&instance->pktinfo, &address_info, sizeof(in6_pktinfo));
} else {
memcpy(&instance->pktinfo, &address_info, sizeof(in_pktinfo));
}
instance->data_length = length;
if(data) {
memcpy(&instance->data, data, length);
}
return instance;
}
void DatagramPacket::destroy(DatagramPacket *packet) {
free(packet);
}
int DatagramPacket::extract_info(msghdr &message, pktinfo_storage &info) {
for (cmsghdr* cmsg = CMSG_FIRSTHDR(&message); cmsg != nullptr; cmsg = CMSG_NXTHDR(&message, cmsg)) { // iterate through all the control headers
if(cmsg->cmsg_type != IP_PKTINFO && cmsg->cmsg_type != IPV6_PKTINFO) continue;
if(cmsg->cmsg_level == IPPROTO_IP) {
memcpy(&info, (void*) CMSG_DATA(cmsg), sizeof(in_pktinfo));
return 4;
} else if(cmsg->cmsg_level == IPPROTO_IPV6) {
memcpy(&info, (void*) CMSG_DATA(cmsg), sizeof(in6_pktinfo));
return 6;
}
}
return 0;
}

View File

@ -0,0 +1,32 @@
#pragma once
#include <netinet/in.h>
namespace ts::server::udp {
union pktinfo_storage {
in_pktinfo v4;
in6_pktinfo v6;
};
struct DatagramPacket {
public:
DatagramPacket* next_packet;
sockaddr_storage address;
pktinfo_storage pktinfo;
size_t data_length;
uint8_t data[0];
static void destroy(DatagramPacket*);
static DatagramPacket* create(const sockaddr_storage& address, const pktinfo_storage& address_info, size_t length, const uint8_t* data);
static int extract_info(msghdr& /* header */, pktinfo_storage& /* info */);
DatagramPacket() = delete;
DatagramPacket(const DatagramPacket&) = delete;
DatagramPacket(DatagramPacket&&) = delete;
~DatagramPacket() = delete;
};
}

View File

@ -0,0 +1,5 @@
//
// Created by WolverinDEV on 02/08/2020.
//
#include "UDPVoiceServer.h"

View File

@ -0,0 +1,71 @@
#pragma once
#include <string>
#include <netinet/in.h>
#include <misc/net.h>
#include <mutex>
#include <event.h>
#include <Definitions.h>
#include <lookup/ipv4.h>
namespace ts::connection {
class VoiceClientConnection;
}
namespace ts::server::server::udp {
class Server;
class Socket {
public:
Socket(Server* /* server handle */, ServerId /* server id */, const sockaddr_storage& /* address */);
void start();
void stop();
[[nodiscard]] inline bool is_active() const { return this->file_descriptor > 0; }
[[nodiscard]] inline std::string address_string() const { return net::to_string(address); }
[[nodiscard]] inline uint16_t address_port() const { return net::port(address); }
private:
struct EVLoopEntry {
Socket* socket;
event* event_read{nullptr};
event* event_write{nullptr};
};
Server* server;
ServerId server_id;
sockaddr_storage address;
int file_descriptor{0};
std::deque<EVLoopEntry*> event_loop_entries{};
std::mutex clients_lock{};
std::deque<std::shared_ptr<connection::VoiceClientConnection>> clients{};
std::vector<std::shared_ptr<connection::VoiceClientConnection>> client_map_by_id{};
lookup::ip_v4<connection::VoiceClientConnection> clients_by_ipv4{};
lookup::ip_v4<connection::VoiceClientConnection> clients_by_ipv6{};
spin_mutex client_write_lock{};
connection::VoiceClientConnection* client_write_head{nullptr};
connection::VoiceClientConnection** client_write_tail{&client_write_head};
static void callback_event_read(int, short, void*);
static void callback_event_write(int, short, void*);
};
struct ServerEventLoops {
event_base* event_base{nullptr};
std::thread dispatch_thread{};
};
class Server {
public:
private:
};
}

2
shared

@ -1 +1 @@
Subproject commit c3188cd9e5f499f4b5813953d2bc62f56800222f Subproject commit 59ec412fea21d6342311135a697696624fc0e628