sources/network/rconsession.cpp

branch
protocol5
changeset 167
0150f86e68f0
parent 166
af5fa8c43ca8
child 169
febc3ed5435c
--- 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();

mercurial