Fixed the invalid packet splitting algorithm
This commit is contained in:
parent
40dfbd64fa
commit
ac89b3a423
@ -499,6 +499,7 @@ void VoiceClientConnection::execute_resend(const std::chrono::system_clock::time
|
||||
this->resend_queue_tail = &packet->next;
|
||||
|
||||
send_count++;
|
||||
buffer->resend_count++;
|
||||
this->packet_statistics().send_command((protocol::PacketType) buffer->packet_type, buffer->packet_full_id);
|
||||
}
|
||||
}
|
||||
@ -657,7 +658,8 @@ void VoiceClientConnection::send_command(const std::string_view &command, bool l
|
||||
uint8_t head_pflags{0};
|
||||
PacketType ptype{low ? PacketType::COMMAND_LOW : PacketType::COMMAND};
|
||||
protocol::OutgoingServerPacket *packets_head{nullptr};
|
||||
protocol::OutgoingServerPacket *packets_tail{nullptr};
|
||||
protocol::OutgoingServerPacket **packets_tail{&packets_head};
|
||||
|
||||
/* only compress "long" commands */
|
||||
if(command.size() > 100) {
|
||||
size_t max_compressed_payload_size = compression::qlz_compressed_size(command.data(), command.length());
|
||||
@ -671,7 +673,7 @@ void VoiceClientConnection::send_command(const std::string_view &command, bool l
|
||||
}
|
||||
|
||||
/* we don't need to make the command longer than it is */
|
||||
if(compressed_size < command.length()) {
|
||||
if(compressed_size < command.length() || this->client->getType() == ClientType::CLIENT_TEAMSPEAK) { /* TS3 requires each splituped packet to be compressed */
|
||||
own_data_buffer = true;
|
||||
data_buffer = (char*) compressed_buffer;
|
||||
own_data_buffer_ptr = compressed_buffer;
|
||||
@ -686,23 +688,24 @@ void VoiceClientConnection::send_command(const std::string_view &command, bool l
|
||||
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);
|
||||
auto packet = protocol::allocate_outgoing_packet(chunk_size);
|
||||
packets_head = packet;
|
||||
while(true) {
|
||||
packet->type_and_flags = ptype_and_flags;
|
||||
|
||||
while(true) {
|
||||
auto bytes = 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);
|
||||
|
||||
data_length -= bytes;
|
||||
if(data_length == 0)
|
||||
break;
|
||||
data_buffer += bytes;
|
||||
*packets_tail = packet;
|
||||
packets_tail = &packet->next;
|
||||
|
||||
packet->next = protocol::allocate_outgoing_packet(bytes);
|
||||
packet = packet->next;
|
||||
data_length -= bytes;
|
||||
if(data_length == 0) {
|
||||
packet->type_and_flags |= PacketFlag::Fragmented;
|
||||
break;
|
||||
}
|
||||
data_buffer += bytes;
|
||||
}
|
||||
packets_tail = packet;
|
||||
packets_head->type_and_flags |= PacketFlag::Fragmented;
|
||||
} else {
|
||||
auto packet = protocol::allocate_outgoing_packet(data_length);
|
||||
packet->type_and_flags = ptype_and_flags;
|
||||
@ -710,7 +713,7 @@ void VoiceClientConnection::send_command(const std::string_view &command, bool l
|
||||
memcpy(packet->payload, data_buffer, data_length);
|
||||
|
||||
packets_head = packet;
|
||||
packets_tail = packet;
|
||||
packets_tail = &packet->next;
|
||||
}
|
||||
|
||||
|
||||
@ -726,11 +729,7 @@ void VoiceClientConnection::send_command(const std::string_view &command, bool l
|
||||
head = head->next;
|
||||
}
|
||||
}
|
||||
|
||||
/* if head = tail, fragmented will not be enabled (2x xored) */
|
||||
packets_head->type_and_flags |= head_pflags;
|
||||
packets_head->type_and_flags ^= PacketFlag::Fragmented;
|
||||
packets_tail->type_and_flags ^= PacketFlag::Fragmented;
|
||||
|
||||
/* do this before the next ptr might get modified due to the write queue */
|
||||
auto statistics = this->client ? this->client->connectionStatistics : nullptr;
|
||||
@ -754,7 +753,7 @@ void VoiceClientConnection::send_command(const std::string_view &command, bool l
|
||||
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 == packets_tail)
|
||||
if(&head->next == packets_tail)
|
||||
this->acknowledge_handler.process_packet(ptype, full_packet_id, head, std::move(ack_listener));
|
||||
else
|
||||
this->acknowledge_handler.process_packet(ptype, full_packet_id, head, nullptr);
|
||||
@ -766,7 +765,7 @@ void VoiceClientConnection::send_command(const std::string_view &command, bool l
|
||||
{
|
||||
std::lock_guard qlock{this->write_queue_mutex};
|
||||
*this->write_queue_tail = packets_head;
|
||||
this->write_queue_tail = &packets_tail->next;
|
||||
this->write_queue_tail = packets_tail;
|
||||
}
|
||||
this->triggerWrite();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user