31 #include <time.h> |
31 #include <time.h> |
32 #include "rconsession.h" |
32 #include "rconsession.h" |
33 #include "../interface.h" |
33 #include "../interface.h" |
34 BEGIN_ZFC_NAMESPACE |
34 BEGIN_ZFC_NAMESPACE |
35 |
35 |
|
36 struct PacketHeader |
|
37 { |
|
38 int32_t header; |
|
39 int sequenceNumber; |
|
40 }; |
|
41 |
36 // ------------------------------------------------------------------------------------------------- |
42 // ------------------------------------------------------------------------------------------------- |
37 // |
43 // |
38 RCONSession::RCONSession() : |
44 RCONSession::RCONSession() : |
39 m_state(RCON_DISCONNECTED), |
45 m_state(RCON_DISCONNECTED), |
40 m_lastPing(0), |
46 m_lastPing(0), |
41 m_adminCount(0), |
47 m_adminCount(0), |
|
48 m_lastMissingPacketRequest(0), |
42 m_interface(nullptr) |
49 m_interface(nullptr) |
43 { |
50 { |
44 if (not m_socket.set_blocking(false)) |
51 if (not m_socket.set_blocking(false)) |
45 { |
52 { |
46 fprintf(stderr, "unable to set socket as non-blocking: %s\n", |
53 fprintf(stderr, "unable to set socket as non-blocking: %s\n", |
109 send({CLRC_PONG}); |
116 send({CLRC_PONG}); |
110 bumpLastPing(); |
117 bumpLastPing(); |
111 } |
118 } |
112 } |
119 } |
113 |
120 |
|
121 // Check for new packets in our socket |
114 for (Datagram datagram; m_socket.read(datagram);) |
122 for (Datagram datagram; m_socket.read(datagram);) |
115 handlePacket(datagram); |
123 { |
116 } |
124 // Packet came from the wrong address, ignore |
117 |
125 if (datagram.address != m_address) |
118 // ------------------------------------------------------------------------------------------------- |
126 continue; |
119 // |
127 |
120 void RCONSession::handlePacket(Datagram& datagram) |
128 // Parse and cut off the header. |
121 { |
129 PacketHeader header; |
122 if (datagram.address != m_address) |
130 { |
123 return; |
131 // Read the header, and find the sequence number |
124 |
132 Bytestream stream(datagram.message); |
125 Bytestream stream(datagram.message); |
133 header.header = stream.readLong(); |
|
134 header.sequenceNumber = (header.header != 0) ? stream.readLong() : -1; |
|
135 datagram.message = datagram.message.splice(stream.position(), datagram.message.size()); |
|
136 } |
|
137 |
|
138 // Try to store this packet into the queue. However, do not try to store packets without a sequence number. |
|
139 bool stored = false; |
|
140 |
|
141 if (header.sequenceNumber != -1) |
|
142 stored = m_packetQueue.addPacket(header.sequenceNumber, datagram.message); |
|
143 |
|
144 // If the packet was not stored, we are to just process it right away. |
|
145 if (stored == false) |
|
146 handlePacket(datagram.message); |
|
147 } |
|
148 |
|
149 // Check if we can now also process some packets from the queue. |
|
150 if (m_packetQueue.hasPacketsToPop()) |
|
151 { |
|
152 ByteArray message; |
|
153 while (m_packetQueue.popNextPacket(message)) |
|
154 handlePacket(message); |
|
155 } |
|
156 |
|
157 // Check whether there are packets stuck in the queue. If this is the case, we have lost some packets and need to |
|
158 // ask the game server to re-send them. |
|
159 if (m_packetQueue.isStuck() and m_lastMissingPacketRequest + 1 < time(NULL)) |
|
160 { |
|
161 m_interface->printWarning("Missing packets detected. Packets currently in queue:\n"); |
|
162 |
|
163 for (int packetNumber : m_packetQueue.getWaitingPackets()) |
|
164 m_interface->printWarning("- %d:\n", packetNumber); |
|
165 |
|
166 m_lastMissingPacketRequest = time(NULL); |
|
167 ByteArray message; |
|
168 Bytestream stream(message); |
|
169 stream.writeByte(CLRC_MISSINGPACKET); |
|
170 |
|
171 for (int packetNumber : m_packetQueue.getLostPackets()) |
|
172 { |
|
173 m_interface->printWarning("Requesting lost packet %d\n", packetNumber); |
|
174 stream.writeLong(packetNumber); |
|
175 } |
|
176 |
|
177 send(message); |
|
178 } |
|
179 } |
|
180 |
|
181 // ------------------------------------------------------------------------------------------------- |
|
182 // |
|
183 void RCONSession::handlePacket(ByteArray& message) |
|
184 { |
|
185 Bytestream stream(message); |
126 |
186 |
127 try |
187 try |
128 { |
188 { |
129 int32_t header = stream.readLong(); |
|
130 int32_t sequenceNumber = (header != 0) ? stream.readLong() : 0; |
|
131 m_interface->print("Recieved packet with header 0x%x and sequence number #%d\n", header, sequenceNumber); |
|
132 |
|
133 while (stream.bytesLeft() > 0) |
189 while (stream.bytesLeft() > 0) |
134 { |
190 { |
135 int header = stream.readByte(); |
191 int header = stream.readByte(); |
136 |
192 |
137 switch (ServerResponse(header)) |
193 switch (ServerResponse(header)) |