Fix PACKET_SERVER_MAP_DONE prepending with packet encryption

Also fix logging of sent encrypted packets
This commit is contained in:
Jonathan G Rennison
2024-07-03 02:32:57 +01:00
parent 06718b632d
commit 7c569b2c83
5 changed files with 42 additions and 15 deletions

View File

@@ -54,12 +54,16 @@ Packet::Packet(NetworkSocketHandler *cs, PacketType type, size_t limit) : pos(0)
void Packet::ResetState(PacketType type)
{
this->buffer.clear();
this->tx_packet_type = type;
/* Allocate space for the the size so we can write that in just before sending the packet. */
size_t size = EncodedLengthOfPacketSize();
if (cs != nullptr && cs->send_encryption_handler != nullptr) {
/* Allocate some space for the message authentication code of the encryption. */
size += cs->send_encryption_handler->MACSize();
this->encyption_pending = true;
} else {
this->encyption_pending = false;
}
assert(this->CanWriteToPacket(size));
this->buffer.resize(size, 0);
@@ -70,7 +74,7 @@ void Packet::ResetState(PacketType type)
/**
* Writes the packet size from the raw packet from packet->size
*/
void Packet::PrepareToSend()
void Packet::PrepareForSendQueue()
{
/* Prevent this to be called twice and for packets that have been received. */
assert(this->buffer[0] == 0 && this->buffer[1] == 0);
@@ -78,17 +82,19 @@ void Packet::PrepareToSend()
this->buffer[0] = GB(this->Size(), 0, 8);
this->buffer[1] = GB(this->Size(), 8, 8);
if (cs != nullptr && cs->send_encryption_handler != nullptr) {
size_t offset = EncodedLengthOfPacketSize();
size_t mac_size = cs->send_encryption_handler->MACSize();
size_t message_offset = offset + mac_size;
cs->send_encryption_handler->Encrypt(std::span(&this->buffer[offset], mac_size), std::span(&this->buffer[message_offset], this->buffer.size() - message_offset));
}
this->pos = 0; // We start reading from here
this->pos = 0; // We start reading from here
this->buffer.shrink_to_fit();
}
void Packet::PreSendEncryption()
{
this->encyption_pending = false;
size_t offset = EncodedLengthOfPacketSize();
size_t mac_size = cs->send_encryption_handler->MACSize();
size_t message_offset = offset + mac_size;
cs->send_encryption_handler->Encrypt(std::span(&this->buffer[offset], mac_size), std::span(&this->buffer[message_offset], this->buffer.size() - message_offset));
}
/**
* Is it safe to write to the packet, i.e. didn't we run over the buffer?
* @param bytes_to_write The amount of bytes we want to try to write.

View File

@@ -51,6 +51,10 @@ struct Packet : public BufferSerialisationHelper<Packet>, public BufferDeseriali
private:
/** The current read/write position in the packet */
PacketSize pos;
/** Whether encryption is required for this packet */
bool encyption_pending = false;
/** Packet type, for transmitted packets */
PacketType tx_packet_type;
/** The buffer of this packet. */
std::vector<uint8_t> buffer;
/** The limit for the packet size. */
@@ -59,6 +63,8 @@ private:
/** Socket we're associated with. */
NetworkSocketHandler *cs;
void PreSendEncryption();
public:
struct ReadTag{};
Packet(ReadTag tag, NetworkSocketHandler *cs, size_t limit, size_t initial_read_size = EncodedLengthOfPacketSize());
@@ -66,8 +72,21 @@ public:
void ResetState(PacketType type);
void PrepareForSendQueue();
inline void CheckPendingPreSendEncryption()
{
if (this->encyption_pending) {
this->PreSendEncryption();
}
}
/* Sending/writing of packets */
void PrepareToSend();
inline void PrepareToSend()
{
this->PrepareForSendQueue();
this->CheckPendingPreSendEncryption();
}
std::vector<uint8_t> &GetSerialisationBuffer() { return this->buffer; }
size_t GetSerialisationLimit() const { return this->limit; }
@@ -88,6 +107,7 @@ public:
size_t Size() const;
[[nodiscard]] bool PrepareToRead();
PacketType GetPacketType() const;
PacketType GetTransmitPacketType() const { return this->tx_packet_type; }
bool CanReadFromPacket(size_t bytes_to_read, bool close_connection = false);

View File

@@ -69,7 +69,7 @@ void NetworkTCPSocketHandler::SendPacket(std::unique_ptr<Packet> packet)
{
assert(packet != nullptr);
packet->PrepareToSend();
packet->PrepareForSendQueue();
this->packet_queue.push_back(std::move(packet));
}
@@ -84,11 +84,11 @@ void NetworkTCPSocketHandler::SendPrependPacket(std::unique_ptr<Packet> packet,
{
assert(packet != nullptr);
packet->PrepareToSend();
packet->PrepareForSendQueue();
if (queue_after_packet_type >= 0) {
for (auto iter = this->packet_queue.begin(); iter != this->packet_queue.end(); ++iter) {
if ((*iter)->GetPacketType() == queue_after_packet_type) {
if ((*iter)->GetTransmitPacketType() == queue_after_packet_type) {
++iter;
this->packet_queue.insert(iter, std::move(packet));
return;
@@ -131,6 +131,7 @@ SendPacketsState NetworkTCPSocketHandler::SendPackets(bool closing_down)
while (!this->packet_queue.empty()) {
Packet &p = *this->packet_queue.front();
p.CheckPendingPreSendEncryption();
ssize_t res = p.TransferOut<int>(send, this->sock, 0);
if (res == -1) {
NetworkError err = NetworkError::GetLast();

View File

@@ -295,7 +295,7 @@ std::string NetworkGameSocketHandler::GetDebugInfo() const { return ""; }
void NetworkGameSocketHandler::LogSentPacket(const Packet &pkt)
{
PacketGameType type = (PacketGameType)pkt.GetPacketType();
PacketGameType type = (PacketGameType)pkt.GetTransmitPacketType();
DEBUG(net, 5, "[tcp/game] sent packet type %d (%s) to client %d, %s", type, GetPacketGameTypeName(type), this->client_id, this->GetDebugInfo().c_str());
}

View File

@@ -136,7 +136,7 @@ struct PacketWriter : SaveFilter {
}
bool last_packet = false;
for (auto &p : this->packets) {
if (p->GetPacketType() == PACKET_SERVER_MAP_DONE) last_packet = true;
if (p->GetTransmitPacketType() == PACKET_SERVER_MAP_DONE) last_packet = true;
this->cs->SendPacket(std::move(p));
}