--- a/sources/network/rconsession.cpp Sat Jul 23 12:28:07 2016 +0300 +++ b/sources/network/rconsession.cpp Sat Jul 23 12:28:52 2016 +0300 @@ -33,12 +33,19 @@ #include "../interface.h" BEGIN_ZFC_NAMESPACE +struct PacketHeader +{ + int32_t header; + int sequenceNumber; +}; + // ------------------------------------------------------------------------------------------------- // RCONSession::RCONSession() : m_state(RCON_DISCONNECTED), m_lastPing(0), m_adminCount(0), + m_lastMissingPacketRequest(0), m_interface(nullptr) { if (not m_socket.set_blocking(false)) @@ -111,25 +118,74 @@ } } + // Check for new packets in our socket for (Datagram datagram; m_socket.read(datagram);) - handlePacket(datagram); + { + // Packet came from the wrong address, ignore + if (datagram.address != m_address) + continue; + + // Parse and cut off the header. + PacketHeader header; + { + // Read the header, and find the sequence number + Bytestream stream(datagram.message); + header.header = stream.readLong(); + header.sequenceNumber = (header.header != 0) ? stream.readLong() : -1; + datagram.message = datagram.message.splice(stream.position(), datagram.message.size()); + } + + // Try to store this packet into the queue. However, do not try to store packets without a sequence number. + bool stored = false; + + if (header.sequenceNumber != -1) + stored = m_packetQueue.addPacket(header.sequenceNumber, datagram.message); + + // If the packet was not stored, we are to just process it right away. + if (stored == false) + handlePacket(datagram.message); + } + + // Check if we can now also process some packets from the queue. + if (m_packetQueue.hasPacketsToPop()) + { + ByteArray message; + while (m_packetQueue.popNextPacket(message)) + handlePacket(message); + } + + // Check whether there are packets stuck in the queue. If this is the case, we have lost some packets and need to + // ask the game server to re-send them. + if (m_packetQueue.isStuck() and m_lastMissingPacketRequest + 1 < time(NULL)) + { + m_interface->printWarning("Missing packets detected. Packets currently in queue:\n"); + + for (int packetNumber : m_packetQueue.getWaitingPackets()) + m_interface->printWarning("- %d:\n", packetNumber); + + m_lastMissingPacketRequest = time(NULL); + ByteArray message; + Bytestream stream(message); + stream.writeByte(CLRC_MISSINGPACKET); + + for (int packetNumber : m_packetQueue.getLostPackets()) + { + m_interface->printWarning("Requesting lost packet %d\n", packetNumber); + stream.writeLong(packetNumber); + } + + send(message); + } } // ------------------------------------------------------------------------------------------------- // -void RCONSession::handlePacket(Datagram& datagram) +void RCONSession::handlePacket(ByteArray& message) { - if (datagram.address != m_address) - return; - - Bytestream stream(datagram.message); + Bytestream stream(message); try { - int32_t header = stream.readLong(); - int32_t sequenceNumber = (header != 0) ? stream.readLong() : 0; - m_interface->print("Recieved packet with header 0x%x and sequence number #%d\n", header, sequenceNumber); - while (stream.bytesLeft() > 0) { int header = stream.readByte();