99 lines
3.6 KiB
C++
99 lines
3.6 KiB
C++
//
|
|
// Created by WolverinDEV on 29/07/2020.
|
|
//
|
|
|
|
#include "./ServerCommandExecutor.h"
|
|
#include "./PacketDecoder.h"
|
|
#include "./VoiceClientConnection.h"
|
|
|
|
using namespace ts;
|
|
using namespace ts::server::server::udp;
|
|
|
|
ServerCommandExecutor::ServerCommandExecutor(VoiceClient *client) : client{client} {}
|
|
ServerCommandExecutor::~ServerCommandExecutor() {
|
|
this->reset();
|
|
}
|
|
|
|
void ServerCommandExecutor::reset() {
|
|
std::unique_lock pc_lock{this->pending_commands_lock};
|
|
auto head = std::exchange(this->pending_commands_head, nullptr);
|
|
this->pending_commands_tail = &this->pending_commands_head;
|
|
pc_lock.unlock();
|
|
|
|
while(head) {
|
|
auto cmd = head->next_command;
|
|
ReassembledCommand::free(head);
|
|
head = cmd;
|
|
}
|
|
}
|
|
|
|
void ServerCommandExecutor::force_insert_command(const pipes::buffer_view &buffer) {
|
|
auto command = ReassembledCommand::allocate(buffer.length());
|
|
memcpy(command->command(), buffer.data_ptr(), command->length());
|
|
this->enqueue_command_execution(command);
|
|
}
|
|
|
|
void ServerCommandExecutor::enqueue_command_execution(ReassembledCommand *command) {
|
|
assert(!command->next_command);
|
|
|
|
bool command_handling_scheduled;
|
|
{
|
|
std::lock_guard pc_lock{this->pending_commands_lock};
|
|
*this->pending_commands_tail = command;
|
|
this->pending_commands_tail = &command->next_command;
|
|
|
|
command_handling_scheduled = std::exchange(this->has_command_handling_scheduled, true);
|
|
}
|
|
|
|
if(!command_handling_scheduled) {
|
|
auto voice_server = this->client->getVoiceServer();
|
|
if(voice_server)
|
|
voice_server->schedule_command_handling(&*client);
|
|
}
|
|
}
|
|
|
|
void ServerCommandExecutor::execute_handle_command_packets(const std::chrono::system_clock::time_point& /* scheduled */) {
|
|
if(!this->client->getServer() || this->client->connectionState() >= ConnectionState::DISCONNECTING) {
|
|
return;
|
|
}
|
|
|
|
std::unique_ptr<ReassembledCommand, void(*)(ReassembledCommand*)> pending_command{nullptr, ReassembledCommand::free};
|
|
while(true) {
|
|
{
|
|
std::lock_guard pc_lock{this->pending_commands_lock};
|
|
pending_command.reset(this->pending_commands_head);
|
|
if(!pending_command) {
|
|
this->has_command_handling_scheduled = false;
|
|
return;
|
|
} else if(pending_command->next_command) {
|
|
this->pending_commands_head = pending_command->next_command;
|
|
} else {
|
|
this->pending_commands_head = nullptr;
|
|
this->pending_commands_tail = &this->pending_commands_head;
|
|
}
|
|
}
|
|
|
|
auto startTime = std::chrono::system_clock::now();
|
|
try {
|
|
this->client->handlePacketCommand(pipes::buffer_view{pending_command->command(), pending_command->length()});
|
|
} catch (std::exception& ex) {
|
|
logCritical(this->client->getServerId(), "{} Exception reached root tree! {}", CLIENT_STR_LOG_PREFIX_(this->client), ex.what());
|
|
}
|
|
|
|
auto end = std::chrono::system_clock::now();
|
|
if(end - startTime > std::chrono::milliseconds(10)) {
|
|
logError(this->client->getServerId(),
|
|
"{} Handling of command packet needs more than 10ms ({}ms)",
|
|
CLIENT_STR_LOG_PREFIX_(this->client),
|
|
duration_cast<std::chrono::milliseconds>(end - startTime).count()
|
|
);
|
|
}
|
|
|
|
break; /* Maybe handle more than one command? Maybe some kind of time limit? */
|
|
}
|
|
|
|
auto voice_server = this->client->getVoiceServer();
|
|
if(voice_server) {
|
|
voice_server->schedule_command_handling(client);
|
|
}
|
|
} |