Improved abort signal printing and some reformats

This commit is contained in:
WolverinDEV 2021-01-14 22:16:56 +01:00
parent f2c5b5d750
commit 94c7eb2f39
14 changed files with 143 additions and 95 deletions

View File

@ -116,8 +116,9 @@ bool FileClient::enqueue_disk_buffer_bytes(const void *snd_buffer, size_t size)
size_t buffer_size;
{
std::lock_guard block{this->disk_buffer.mutex};
if(this->disk_buffer.write_disconnected)
if(this->disk_buffer.write_disconnected) {
goto write_disconnected;
}
*this->disk_buffer.buffer_tail = tbuffer;
this->disk_buffer.buffer_tail = &tbuffer->next;

View File

@ -133,8 +133,10 @@ bool FileClient::enqueue_network_buffer_bytes(const void *snd_buffer, size_t siz
size_t buffer_size;
{
std::lock_guard block{this->network_buffer.mutex};
if(this->network_buffer.write_disconnected)
if(this->network_buffer.write_disconnected) {
goto write_disconnected;
}
*this->network_buffer.buffer_tail = tbuffer;
this->network_buffer.buffer_tail = &tbuffer->next;
@ -898,8 +900,9 @@ size_t LocalFileTransfer::handle_transfer_read_raw(const std::shared_ptr<FileCli
client->transfer_key.provided_bytes += bytes_write;
}
if(client->transfer_key.provided_bytes < TRANSFER_KEY_LENGTH)
if(client->transfer_key.provided_bytes < TRANSFER_KEY_LENGTH) {
return 0; /* we need more data */
}
if(pipes::SSL::is_ssl((uint8_t*) client->transfer_key.key, client->transfer_key.provided_bytes)) {
client->networking.protocol = FileClient::PROTOCOL_HTTPS;
@ -911,12 +914,14 @@ size_t LocalFileTransfer::handle_transfer_read_raw(const std::shared_ptr<FileCli
memcpy(first_bytes, client->transfer_key.key, TRANSFER_KEY_LENGTH);
client->transfer_key.provided_bytes = 0;
if(!this->initialize_client_ssl(client))
if(!this->initialize_client_ssl(client)) {
return (size_t) -1;
}
client->networking.pipe_ssl.process_incoming_data(pipes::buffer_view{first_bytes, TRANSFER_KEY_LENGTH});
if(length > 0)
if(length > 0) {
client->networking.pipe_ssl.process_incoming_data(pipes::buffer_view{buffer, length});
}
return client->network_buffer.bytes;
} else {
client->networking.protocol = FileClient::PROTOCOL_TS_V1;
@ -1226,8 +1231,9 @@ TransferKeyApplyResult LocalFileTransfer::handle_transfer_key_provided(const std
}
}
if(!client->transfer)
if(!client->transfer) {
return TransferKeyApplyResult::UNKNOWN_KEY;
}
if(client->transfer->direction == Transfer::DIRECTION_UPLOAD) {
auto server = dynamic_pointer_cast<LocalVirtualFileServer>(client->transfer->server);
@ -1255,14 +1261,16 @@ TransferKeyApplyResult LocalFileTransfer::handle_transfer_key_provided(const std
{
std::unique_lock slock{client->state_mutex};
if(client->state != FileClient::STATE_AWAITING_KEY)
if(client->state != FileClient::STATE_AWAITING_KEY) {
return TransferKeyApplyResult::SUCCESS; /* something disconnected the client */
}
client->state = FileClient::STATE_TRANSFERRING;
}
if(auto callback{this->callback_transfer_started}; callback)
if(auto callback{this->callback_transfer_started}; callback) {
callback(client->transfer);
}
client->timings.key_received = std::chrono::system_clock::now();
return TransferKeyApplyResult::SUCCESS;
@ -1283,8 +1291,9 @@ TransferUploadRawResult LocalFileTransfer::handle_transfer_upload_raw(const std:
client->statistics.file_transferred.increase_bytes(write_length);
client->enqueue_disk_buffer_bytes(buffer, write_length);
this->enqueue_disk_io(client);
if(bytesWritten)
if(bytesWritten) {
*bytesWritten = write_length;
}
return result;
}

View File

@ -107,8 +107,9 @@ namespace ts::server::file::networking {
throttle |= this->right->should_throttle(right_timestamp);
if(!throttle) return false;
if(right_timestamp.tv_sec > next_timestamp.tv_sec || (right_timestamp.tv_sec == next_timestamp.tv_sec && right_timestamp.tv_usec > next_timestamp.tv_usec))
if(right_timestamp.tv_sec > next_timestamp.tv_sec || (right_timestamp.tv_sec == next_timestamp.tv_sec && right_timestamp.tv_usec > next_timestamp.tv_usec)) {
next_timestamp = right_timestamp;
}
return true;
}
@ -141,8 +142,10 @@ namespace ts::server::file::networking {
std::lock_guard slock{this->mutex};
this->total_bytes += bytes;
if(this->span_index != current_span)
if(this->span_index != current_span) {
this->history[this->span_index % kAverageTimeCount] = std::exchange(this->span_bytes, 0);
}
this->span_index = current_span;
this->span_bytes += bytes;
}

2
rtclib

@ -1 +1 @@
Subproject commit 2c08b8759268095b96f3904757300905db1ea61d
Subproject commit 449f4f3baab91ba488f83def70193d08f350f193

View File

@ -26,6 +26,18 @@ google_breakpad::ExceptionHandler* globalExceptionHandler = nullptr;
if(signal(s, c) != nullptr) logError(LOG_GENERAL, "Cant setup signal handler for " #s);
void print_current_exception() {
if(std::current_exception()) {
logCritical(LOG_GENERAL, "Exception reached stack root and cause the server to crash!");
logCritical(LOG_GENERAL, " Type: {}", std::current_exception().__cxa_exception_type()->name());
try {
std::rethrow_exception(std::current_exception());
} catch(std::exception& ex) {
logCritical(LOG_GENERAL, " Message: {}", ex.what());
} catch(...) {}
}
}
extern bool mainThreadDone;
#ifdef BREAKPAD_EXCEPTION_HANDLER
static bool dumpCallback(const google_breakpad::MinidumpDescriptor& descriptor, void* context, bool succeeded) {
@ -41,15 +53,7 @@ static bool dumpCallback(const google_breakpad::MinidumpDescriptor& descriptor,
} catch (...) {
logCritical(LOG_GENERAL, "Failed to write/move crash dump!");
}
if(std::current_exception()) {
logCritical(LOG_GENERAL, "Exception reached stack root and cause the server to crash!");
logCritical(LOG_GENERAL, " Type: {}", std::current_exception().__cxa_exception_type()->name());
try {
std::rethrow_exception(std::current_exception());
} catch(std::exception& ex) {
logCritical(LOG_GENERAL, " Message: {}", ex.what());
} catch(...) {}
}
print_current_exception();
logCritical(LOG_GENERAL, "Please report this crash to the TeaSpeak maintainer WolverinDEV");
logCritical(LOG_GENERAL, "Official issue and bug tracker url: https://github.com/TeaSpeak/TeaSpeak/issues");
@ -58,7 +62,9 @@ static bool dumpCallback(const google_breakpad::MinidumpDescriptor& descriptor,
terminal::finalize_pipe();
ts::server::shutdownInstance(ts::config::messages::applicationCrashed);
while(!mainThreadDone) threads::self::sleep_for(chrono::seconds(1));
while(!mainThreadDone) {
threads::self::sleep_for(chrono::seconds(1));
}
return succeeded;
}
#endif
@ -75,6 +81,8 @@ bool ts::syssignal::setup() {
//We cant listen for this signal if stdin ist a atty
SIG(SIGINT, &ts::syssignal::handleStopSignal);
}
SIG(SIGABRT, &ts::syssignal::handleAbortSignal);
std::set_terminate(ts::syssignal::handleTerminate);
return true;
}
@ -116,4 +124,10 @@ void ts::syssignal::handleStopSignal(int signal) {
raise(SIGKILL);
}
ts::server::shutdownInstance();
}
void ts::syssignal::handleTerminate() {
logCritical(0, "The server crashed (Received a terminate signal)!");
print_current_exception();
}

View File

@ -8,5 +8,7 @@ namespace ts {
extern bool setup();
extern bool setup_threads();
extern void handleStopSignal(int);
extern void handleAbortSignal(int);
extern void handleTerminate();
}
}

View File

@ -40,7 +40,6 @@ using namespace ts::token;
constexpr static auto kFileAPITimeout = std::chrono::milliseconds{500};
constexpr static auto kMaxClientTransfers = 10;
#define QUERY_PASSWORD_LENGTH 12
//ftgetfilelist cid=1 cpw path=\/ return_code=1:x
//Answer:
@ -90,8 +89,9 @@ command_result ConnectedClient::handleCommandFTGetFileList(Command &cmd) {
}
}
if(!query_result->wait_for(kFileAPITimeout))
if(!query_result->wait_for(kFileAPITimeout)) {
return command_result{error::file_api_timeout};
}
if(!query_result->succeeded()) {
debugMessage(this->getServerId(), "{} Failed to query directory: {} / {}", CLIENT_STR_LOG_PREFIX, file::filesystem::directory_query_error_messages[(int) query_result->error().error_type], query_result->error().error_message);
@ -118,8 +118,9 @@ command_result ConnectedClient::handleCommandFTGetFileList(Command &cmd) {
}
const auto& files = query_result->response();
if(files.empty())
if(files.empty()) {
return command_result{error::database_empty_result};
}
auto return_code = cmd["return_code"].size() > 0 ? cmd["return_code"].string() : "";
@ -131,8 +132,9 @@ command_result ConnectedClient::handleCommandFTGetFileList(Command &cmd) {
notify_file_list.reset();
notify_file_list.put_unchecked(0, "path", cmd["path"].string());
notify_file_list.put_unchecked(0, "cid", cmd["cid"].string());
if(!return_code.empty())
if(!return_code.empty()){
notify_file_list.put_unchecked(0, "return_code", return_code);
}
}
auto bulk = notify_file_list.bulk(bulk_index++);

View File

@ -663,8 +663,9 @@ command_result ConnectedClient::handleCommandBanList(Command &cmd) {
CMD_CHK_AND_INC_FLOOD_POINTS(25);
ServerId sid = this->getServerId();
if (cmd[0].has("sid"))
if (cmd[0].has("sid")) {
sid = cmd["sid"];
}
if (sid == 0) {
ACTION_REQUIRES_GLOBAL_PERMISSION(permission::b_client_ban_list_global, 1);
@ -672,8 +673,9 @@ command_result ConnectedClient::handleCommandBanList(Command &cmd) {
auto server = serverInstance->getVoiceServerManager()->findServerById(sid);
if (!server) return command_result{error::parameter_invalid};
if (!permission::v2::permission_granted(1, server->calculate_permission(permission::b_client_ban_list, this->getClientDatabaseId(), this->getType(), 0)))
if (!permission::v2::permission_granted(1, server->calculate_permission(permission::b_client_ban_list, this->getClientDatabaseId(), this->getType(), 0))) {
return command_result{permission::b_client_ban_list};
}
}
//When empty: return command_result{error::database_empty_result};

View File

@ -18,8 +18,6 @@ WhisperHandler::~WhisperHandler() {
}
bool WhisperHandler::validate_whisper_packet(const protocol::ClientPacketParser &packet, bool& match_last_header, void *&payload_ptr, size_t &payload_length) {
std::lock_guard process_lock{this->whisper_head_mutex};
size_t head_length;
if(packet.flags() & protocol::PacketFlag::NewProtocol) {
if(packet.payload_length() < 3 + 10) {
@ -45,19 +43,22 @@ bool WhisperHandler::validate_whisper_packet(const protocol::ClientPacketParser
}
auto head_ptr = packet.payload().data_ptr<uint8_t>() + 3;
match_last_header = this->whisper_head_length == head_length && memcmp(this->whisper_head_ptr, head_ptr, head_length) == 0;
if(!match_last_header) {
if(this->whisper_head_capacity < head_length) {
if(this->whisper_head_ptr) {
::free(this->whisper_head_ptr);
{
std::lock_guard process_lock{this->whisper_head_mutex};
match_last_header = this->whisper_head_length == head_length && memcmp(this->whisper_head_ptr, head_ptr, head_length) == 0;
if(!match_last_header) {
if(this->whisper_head_capacity < head_length) {
if(this->whisper_head_ptr) {
::free(this->whisper_head_ptr);
}
this->whisper_head_ptr = malloc(head_length);
this->whisper_head_capacity = head_length;
}
this->whisper_head_ptr = malloc(head_length);
this->whisper_head_capacity = head_length;
this->whisper_head_length = head_length;
memcpy(this->whisper_head_ptr, head_ptr, head_length);
}
this->whisper_head_length = head_length;
memcpy(this->whisper_head_ptr, head_ptr, head_length);
}
assert(packet.payload_length() >= head_length + 3);

View File

@ -221,10 +221,11 @@ CommandReassembleResult PacketDecoder::try_reassemble_ordered_packet(
ReassembledCommand *&assembled_command) {
assert(buffer_lock.owns_lock());
if(!buffer.front_set())
if(!buffer.front_set()) {
return CommandReassembleResult::NO_COMMANDS_PENDING;
}
uint8_t packet_flags{0};
uint8_t packet_flags;
std::unique_ptr<ReassembledCommand, void(*)(ReassembledCommand*)> rcommand{nullptr, ReassembledCommand::free};
@ -234,11 +235,13 @@ CommandReassembleResult PacketDecoder::try_reassemble_ordered_packet(
uint16_t sequence_length{1};
size_t total_payload_length{first_buffer.payload_length};
do {
if(sequence_length >= buffer.capacity())
if(sequence_length >= buffer.capacity()) {
return CommandReassembleResult::SEQUENCE_LENGTH_TOO_LONG;
}
if(!buffer.slot_set(sequence_length))
if(!buffer.slot_set(sequence_length)) {
return CommandReassembleResult::NO_COMMANDS_PENDING; /* we need more packets */
}
auto& packet = buffer.slot_value(sequence_length++);
total_payload_length += packet.payload_length;
@ -293,12 +296,14 @@ CommandReassembleResult PacketDecoder::try_reassemble_ordered_packet(
auto compressed_command = std::move(rcommand);
auto decompressed_size = compression::qlz_decompressed_size(compressed_command->command(), compressed_command->length());
if(decompressed_size > 64 * 1024 * 1024)
if(decompressed_size > 64 * 1024 * 1024) {
return CommandReassembleResult::COMMAND_TOO_LARGE;
}
rcommand.reset(ReassembledCommand::allocate(decompressed_size));
if(!compression::qlz_decompress_payload(compressed_command->command(), rcommand->command(), &decompressed_size))
if(!compression::qlz_decompress_payload(compressed_command->command(), rcommand->command(), &decompressed_size)) {
return CommandReassembleResult::COMMAND_DECOMPRESS_FAILED;
}
rcommand->set_length(decompressed_size);
}

View File

@ -5,7 +5,8 @@
#include <protocol/buffers.h>
#include <protocol/CompressionHandler.h>
#include <protocol/CryptHandler.cpp>
#include <protocol/CryptHandler.h>
#include <misc/endianness.h>
using namespace ts;
using namespace ts::server::server::udp;
@ -15,7 +16,7 @@ PacketEncoder::PacketEncoder(ts::connection::CryptHandler *crypt_handler, client
this->acknowledge_manager_.callback_data = this;
this->acknowledge_manager_.destroy_packet = [](void* packet) {
reinterpret_cast<OutgoingServerPacket*>(packet)->unref();
reinterpret_cast<protocol::OutgoingServerPacket*>(packet)->unref();
};
this->acknowledge_manager_.callback_resend_failed = [](void* this_ptr, const auto& entry) {
auto encoder = reinterpret_cast<PacketEncoder*>(this_ptr);
@ -37,7 +38,7 @@ void PacketEncoder::reset() {
rhead = std::exchange(this->resend_queue_head, nullptr);
this->encrypt_queue_tail = &this->encrypt_queue_head;
this->resend_queue_tail = &this->resend_queue_head;
this->send_queue_tail = &this->resend_queue_head;
}
while(whead) {
@ -87,8 +88,8 @@ void PacketEncoder::send_packet_acknowledge(uint16_t pid, bool low) {
char buffer[2];
le2be16(pid, buffer);
auto pflags = PacketFlag::Unencrypted | PacketFlag::NewProtocol;
this->send_packet(low ? protocol::PacketType::ACK_LOW : protocol::PacketType::ACK, (PacketFlag::PacketFlag) pflags, buffer, 2);
auto pflags = protocol::PacketFlag::Unencrypted | protocol::PacketFlag::NewProtocol;
this->send_packet(low ? protocol::PacketType::ACK_LOW : protocol::PacketType::ACK, (protocol::PacketFlag::PacketFlag) pflags, buffer, 2);
}
@ -101,7 +102,7 @@ void PacketEncoder::send_command(const std::string_view &command, bool low, std:
size_t data_length{command.length()};
uint8_t head_pflags{0};
PacketType ptype{low ? PacketType::COMMAND_LOW : PacketType::COMMAND};
protocol::PacketType ptype{low ? protocol::PacketType::COMMAND_LOW : protocol::PacketType::COMMAND};
protocol::OutgoingServerPacket *packets_head{nullptr};
protocol::OutgoingServerPacket **packets_tail{&packets_head};
@ -123,19 +124,19 @@ void PacketEncoder::send_command(const std::string_view &command, bool low, std:
data_buffer = (char*) compressed_buffer;
own_data_buffer_ptr = compressed_buffer;
data_length = compressed_size;
head_pflags |= PacketFlag::Compressed;
head_pflags |= protocol::PacketFlag::Compressed;
} else {
::free(compressed_buffer);
}
}
uint8_t ptype_and_flags{(uint8_t) ((uint8_t) ptype | (uint8_t) PacketFlag::NewProtocol)};
uint8_t ptype_and_flags{(uint8_t) ((uint8_t) ptype | (uint8_t) protocol::PacketFlag::NewProtocol)};
if(data_length > MAX_COMMAND_PACKET_PAYLOAD_LENGTH) {
auto chunk_count = (size_t) ceil((float) data_length / (float) MAX_COMMAND_PACKET_PAYLOAD_LENGTH);
auto chunk_size = (size_t) ceil((float) data_length / (float) chunk_count);
while(true) {
auto bytes = min(chunk_size, data_length);
auto bytes = std::min(chunk_size, data_length);
auto packet = protocol::allocate_outgoing_packet(bytes);
packet->type_and_flags = ptype_and_flags;
memcpy(packet->payload, data_buffer, bytes);
@ -145,12 +146,12 @@ void PacketEncoder::send_command(const std::string_view &command, bool low, std:
data_length -= bytes;
if(data_length == 0) {
packet->type_and_flags |= PacketFlag::Fragmented;
packet->type_and_flags |= protocol::PacketFlag::Fragmented;
break;
}
data_buffer += bytes;
}
packets_head->type_and_flags |= PacketFlag::Fragmented;
packets_head->type_and_flags |= protocol::PacketFlag::Fragmented;
} else {
auto packet = protocol::allocate_outgoing_packet(data_length);
packet->type_and_flags = ptype_and_flags;
@ -163,20 +164,19 @@ void PacketEncoder::send_command(const std::string_view &command, bool low, std:
{
std::lock_guard id_lock{this->packet_id_mutex};
{
uint32_t full_id;
auto head = packets_head;
while(head) {
full_id = this->packet_id_manager.generate_full_id(ptype);
head->set_packet_id(full_id & 0xFFFFU);
head->generation = full_id >> 16U;
uint32_t full_id;
auto head = packets_head;
while(head) {
full_id = this->packet_id_manager.generate_full_id(ptype);
/* loss stats (In order required so we're using the this->packet_id_mutex) */
this->packet_statistics_->send_command(head->packet_type(), full_id);
head->set_packet_id(full_id & 0xFFFFU);
head->generation = full_id >> 16U;
head = head->next;
}
/* loss stats (In order required so we're using the this->packet_id_mutex) */
this->packet_statistics_->send_command(head->packet_type(), full_id);
head = head->next;
}
}
packets_head->type_and_flags |= head_pflags;
@ -200,10 +200,11 @@ void PacketEncoder::send_command(const std::string_view &command, bool low, std:
head->ref();
/* Even thou the packet is yet unencrypted, it will be encrypted with the next write. The next write will be before the next resend because the next ptr must be null in order to resend a packet */
if(&head->next == packets_tail)
if(&head->next == packets_tail) {
this->acknowledge_manager_.process_packet(ptype, full_packet_id, head, std::move(ack_listener));
else
} else {
this->acknowledge_manager_.process_packet(ptype, full_packet_id, head, nullptr);
}
head = head->next;
}
@ -222,7 +223,7 @@ void PacketEncoder::send_command(const std::string_view &command, bool low, std:
}
void PacketEncoder::encrypt_pending_packets() {
OutgoingServerPacket* packets_head;
protocol::OutgoingServerPacket* packets_head;
{
std::lock_guard wlock{this->write_queue_mutex};
packets_head = this->encrypt_queue_head;
@ -230,36 +231,39 @@ void PacketEncoder::encrypt_pending_packets() {
this->encrypt_queue_tail = &this->encrypt_queue_head;
}
if(!packets_head)
if(!packets_head) {
return;
}
auto packet = packets_head;
auto packet_tail = packet;
while(packet) {
this->prepare_outgoing_packet(packet);
packet = packet->next;
if(packet)
if(packet) {
packet_tail = packet;
}
}
{
std::lock_guard wlock{this->write_queue_mutex};
*this->resend_queue_tail = packets_head;
this->resend_queue_tail = &packet_tail->next;
*this->send_queue_tail = packets_head;
this->send_queue_tail = &packet_tail->next;
}
}
bool PacketEncoder::prepare_outgoing_packet(ts::protocol::OutgoingServerPacket *packet) {
if(packet->type_and_flags & PacketFlag::Unencrypted) {
if(packet->type_and_flags & protocol::PacketFlag::Unencrypted) {
this->crypt_handler_->write_default_mac(packet->mac);
} else {
CryptHandler::key_t crypt_key{};
CryptHandler::nonce_t crypt_nonce{};
connection::CryptHandler::key_t crypt_key{};
connection::CryptHandler::nonce_t crypt_nonce{};
std::string error{};
if(!this->crypt_handler_->encryption_initialized()) {
crypt_key = CryptHandler::kDefaultKey;
crypt_nonce = CryptHandler::kDefaultNonce;
crypt_key = connection::CryptHandler::kDefaultKey;
crypt_nonce = connection::CryptHandler::kDefaultNonce;
} else {
if(!this->crypt_handler_->generate_key_nonce(false, (uint8_t) packet->packet_type(), packet->packet_id(), packet->generation, crypt_key, crypt_nonce)) {
this->callback_crypt_error(this->callback_data, CryptError::KEY_GENERATION_FAILED, "");
@ -267,7 +271,7 @@ bool PacketEncoder::prepare_outgoing_packet(ts::protocol::OutgoingServerPacket *
}
}
auto crypt_result = this->crypt_handler_->encrypt((char*) packet->packet_data() + ServerPacketP::kHeaderOffset, ServerPacketP::kHeaderLength,
auto crypt_result = this->crypt_handler_->encrypt((char*) packet->packet_data() + protocol::ServerPacketP::kHeaderOffset, protocol::ServerPacketP::kHeaderLength,
packet->payload, packet->payload_size,
packet->mac,
crypt_key, crypt_nonce, error);
@ -286,12 +290,12 @@ PacketEncoder::BufferPopResult PacketEncoder::pop_write_buffer(protocol::Outgoin
if(this->resend_queue_head) {
result = this->resend_queue_head;
if(result->next) {
assert(this->resend_queue_tail != &result->next);
assert(this->send_queue_tail != &result->next);
this->resend_queue_head = result->next;
} else {
assert(this->resend_queue_tail == &result->next);
assert(this->send_queue_tail == &result->next);
this->resend_queue_head = nullptr;
this->resend_queue_tail = &this->resend_queue_head;
this->send_queue_tail = &this->resend_queue_head;
}
} else if(this->encrypt_queue_head) {
result = this->encrypt_queue_head;
@ -311,8 +315,10 @@ PacketEncoder::BufferPopResult PacketEncoder::pop_write_buffer(protocol::Outgoin
more_packets = this->resend_queue_head != nullptr || this->encrypt_queue_head != nullptr;
}
if(need_prepare_packet)
if(need_prepare_packet) {
this->prepare_outgoing_packet(result);
}
return more_packets ? BufferPopResult::MORE_AVAILABLE : BufferPopResult::DRAINED;
}
@ -325,20 +331,22 @@ void PacketEncoder::execute_resend(const std::chrono::system_clock::time_point &
if(!buffers.empty()) {
size_t send_count{0};
{
lock_guard wlock{this->write_queue_mutex};
std::lock_guard wlock{this->write_queue_mutex};
for(auto& buffer : buffers) {
auto packet = (protocol::OutgoingServerPacket*) buffer->packet_ptr;
/* Test if the packet is still in the write/enqueue queue */
if(packet->next)
if(packet->next) {
continue;
}
if(&packet->next == this->encrypt_queue_tail || &packet->next == this->resend_queue_tail)
if(&packet->next == this->encrypt_queue_tail || &packet->next == this->send_queue_tail) {
continue;
}
packet->ref(); /* for the write queue again */
*this->resend_queue_tail = packet;
this->resend_queue_tail = &packet->next;
*this->send_queue_tail = packet;
this->send_queue_tail = &packet->next;
send_count++;
buffer->resend_count++;
@ -352,7 +360,7 @@ void PacketEncoder::execute_resend(const std::chrono::system_clock::time_point &
}
}
bool PacketEncoder::wait_empty_write_and_prepare_queue(chrono::time_point<chrono::system_clock> until) {
bool PacketEncoder::wait_empty_write_and_prepare_queue(std::chrono::time_point<std::chrono::system_clock> until) {
while(true) {
{
std::lock_guard wlock{this->write_queue_mutex};

View File

@ -75,7 +75,7 @@ namespace ts::server::server::udp {
spin_mutex write_queue_mutex{};
protocol::OutgoingServerPacket* resend_queue_head{nullptr};
protocol::OutgoingServerPacket** resend_queue_tail{&resend_queue_head};
protocol::OutgoingServerPacket** send_queue_tail{&resend_queue_head};
protocol::OutgoingServerPacket* encrypt_queue_head{nullptr};
protocol::OutgoingServerPacket** encrypt_queue_tail{&encrypt_queue_head};

View File

@ -47,8 +47,9 @@ void ServerCommandExecutor::enqueue_command_execution(ReassembledCommand *comman
if(!command_handling_scheduled) {
auto voice_server = this->client->getVoiceServer();
if(voice_server)
if(voice_server) {
voice_server->schedule_command_handling(&*client);
}
}
}

View File

@ -18,7 +18,7 @@ void WebClient::handleMessageWrite(int fd, short, void *) {
auto buffer = this->queue_write[0];
this->queue_write.pop_front();
auto written = send(fd, buffer.data_ptr(), buffer.length(), MSG_NOSIGNAL);
auto written = send(fd, buffer.data_ptr(), buffer.length(), MSG_NOSIGNAL | MSG_DONTWAIT);
if(written == -1) {
buffer_lock.unlock();
@ -66,7 +66,7 @@ void WebClient::handleMessageRead(int fd, short, void *) {
size_t buffer_length = 1024 * 4;
uint8_t buffer[buffer_length];
auto length = read(fd, buffer, buffer_length);
auto length = recv(fd, buffer, buffer_length, MSG_NOSIGNAL | MSG_DONTWAIT);
if(length <= 0){
if(errno == EINTR || errno == EAGAIN)
;