2 * This file is part of OpenTTD.
3 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
4 * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
5 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
9 * @file packet.cpp Basic functions to create, fill and read packets.
12 #include "../../stdafx.h"
13 #include "../../string_func.h"
17 #include "../../safeguards.h"
20 * Create a packet that is used to read from a network socket.
21 * @param cs The socket handler associated with the socket we are reading from.
22 * @param limit The maximum size of packets to accept.
23 * @param initial_read_size The initial amount of data to transfer from the socket into the
24 * packet. This defaults to just the required bytes to determine the
25 * packet's size. That default is the wanted for streams such as TCP
26 * as you do not want to read data of the next packet yet. For UDP
27 * you need to read the whole packet at once otherwise you might
28 * loose some the data of the packet, so there you pass the maximum
29 * size for the packet you expect from the network.
31 Packet::Packet(NetworkSocketHandler
*cs
, size_t limit
, size_t initial_read_size
) : pos(0), limit(limit
)
33 assert(cs
!= nullptr);
36 this->buffer
.resize(initial_read_size
);
40 * Creates a packet to send
41 * @param cs The socket handler associated with the socket we are writing to; could be \c nullptr.
42 * @param type The type of the packet to send
43 * @param limit The maximum number of bytes the packet may have. Default is COMPAT_MTU.
44 * Be careful of compatibility with older clients/servers when changing
45 * the limit as it might break things if the other side is not expecting
46 * much larger packets than what they support.
48 Packet::Packet(NetworkSocketHandler
*cs
, PacketType type
, size_t limit
) : pos(0), limit(limit
), cs(cs
)
50 /* Allocate space for the the size so we can write that in just before sending the packet. */
51 size_t size
= EncodedLengthOfPacketSize();
52 if (cs
!= nullptr && cs
->send_encryption_handler
!= nullptr) {
53 /* Allocate some space for the message authentication code of the encryption. */
54 size
+= cs
->send_encryption_handler
->MACSize();
56 assert(this->CanWriteToPacket(size
));
57 this->buffer
.resize(size
, 0);
59 this->Send_uint8(type
);
64 * Writes the packet size from the raw packet from packet->size
66 void Packet::PrepareToSend()
68 /* Prevent this to be called twice and for packets that have been received. */
69 assert(this->buffer
[0] == 0 && this->buffer
[1] == 0);
71 this->buffer
[0] = GB(this->Size(), 0, 8);
72 this->buffer
[1] = GB(this->Size(), 8, 8);
74 if (cs
!= nullptr && cs
->send_encryption_handler
!= nullptr) {
75 size_t offset
= EncodedLengthOfPacketSize();
76 size_t mac_size
= cs
->send_encryption_handler
->MACSize();
77 size_t message_offset
= offset
+ mac_size
;
78 cs
->send_encryption_handler
->Encrypt(std::span(&this->buffer
[offset
], mac_size
), std::span(&this->buffer
[message_offset
], this->buffer
.size() - message_offset
));
81 this->pos
= 0; // We start reading from here
82 this->buffer
.shrink_to_fit();
86 * Is it safe to write to the packet, i.e. didn't we run over the buffer?
87 * @param bytes_to_write The amount of bytes we want to try to write.
88 * @return True iff the given amount of bytes can be written to the packet.
90 bool Packet::CanWriteToPacket(size_t bytes_to_write
)
92 return this->Size() + bytes_to_write
<= this->limit
;
96 * The next couple of functions make sure we can send
97 * uint8_t, uint16_t, uint32_t and uint64_t endian-safe
98 * over the network. The least significant bytes are
101 * So 0x01234567 would be sent as 67 45 23 01.
103 * A bool is sent as a uint8_t where zero means false
104 * and non-zero means true.
108 * Package a boolean in the packet.
109 * @param data The data to send.
111 void Packet::Send_bool(bool data
)
113 this->Send_uint8(data
? 1 : 0);
117 * Package a 8 bits integer in the packet.
118 * @param data The data to send.
120 void Packet::Send_uint8(uint8_t data
)
122 assert(this->CanWriteToPacket(sizeof(data
)));
123 this->buffer
.emplace_back(data
);
127 * Package a 16 bits integer in the packet.
128 * @param data The data to send.
130 void Packet::Send_uint16(uint16_t data
)
132 assert(this->CanWriteToPacket(sizeof(data
)));
133 this->buffer
.emplace_back(GB(data
, 0, 8));
134 this->buffer
.emplace_back(GB(data
, 8, 8));
138 * Package a 32 bits integer in the packet.
139 * @param data The data to send.
141 void Packet::Send_uint32(uint32_t data
)
143 assert(this->CanWriteToPacket(sizeof(data
)));
144 this->buffer
.emplace_back(GB(data
, 0, 8));
145 this->buffer
.emplace_back(GB(data
, 8, 8));
146 this->buffer
.emplace_back(GB(data
, 16, 8));
147 this->buffer
.emplace_back(GB(data
, 24, 8));
151 * Package a 64 bits integer in the packet.
152 * @param data The data to send.
154 void Packet::Send_uint64(uint64_t data
)
156 assert(this->CanWriteToPacket(sizeof(data
)));
157 this->buffer
.emplace_back(GB(data
, 0, 8));
158 this->buffer
.emplace_back(GB(data
, 8, 8));
159 this->buffer
.emplace_back(GB(data
, 16, 8));
160 this->buffer
.emplace_back(GB(data
, 24, 8));
161 this->buffer
.emplace_back(GB(data
, 32, 8));
162 this->buffer
.emplace_back(GB(data
, 40, 8));
163 this->buffer
.emplace_back(GB(data
, 48, 8));
164 this->buffer
.emplace_back(GB(data
, 56, 8));
168 * Sends a string over the network. It sends out
169 * the string + '\0'. No size-byte or something.
170 * @param data The string to send
172 void Packet::Send_string(const std::string_view data
)
174 assert(this->CanWriteToPacket(data
.size() + 1));
175 this->buffer
.insert(this->buffer
.end(), data
.begin(), data
.end());
176 this->buffer
.emplace_back('\0');
180 * Copy a sized byte buffer into the packet.
181 * @param data The data to send.
183 void Packet::Send_buffer(const std::vector
<uint8_t> &data
)
185 assert(this->CanWriteToPacket(sizeof(uint16_t) + data
.size()));
186 this->Send_uint16((uint16_t)data
.size());
187 this->buffer
.insert(this->buffer
.end(), data
.begin(), data
.end());
191 * Send as many of the bytes as possible in the packet. This can mean
192 * that it is possible that not all bytes are sent. To cope with this
193 * the function returns the span of bytes that were not sent.
194 * @param span The span describing the range of bytes to send.
195 * @return The span of bytes that were not written.
197 std::span
<const uint8_t> Packet::Send_bytes(const std::span
<const uint8_t> span
)
199 size_t amount
= std::min
<size_t>(span
.size(), this->limit
- this->Size());
200 this->buffer
.insert(this->buffer
.end(), span
.data(), span
.data() + amount
);
201 return span
.subspan(amount
);
206 * Again, the next couple of functions are endian-safe
207 * see the comment before Send_bool for more info.
212 * Is it safe to read from the packet, i.e. didn't we run over the buffer?
213 * In case \c close_connection is true, the connection will be closed when one would
214 * overrun the buffer. When it is false, the connection remains untouched.
215 * @param bytes_to_read The amount of bytes we want to try to read.
216 * @param close_connection Whether to close the connection if one cannot read that amount.
217 * @return True if that is safe, otherwise false.
219 bool Packet::CanReadFromPacket(size_t bytes_to_read
, bool close_connection
)
221 /* Don't allow reading from a quit client/client who send bad data */
222 if (this->cs
->HasClientQuit()) return false;
224 /* Check if variable is within packet-size */
225 if (this->pos
+ bytes_to_read
> this->Size()) {
226 if (close_connection
) this->cs
->NetworkSocketHandler::MarkClosed();
234 * Check whether the packet, given the position of the "write" pointer, has read
235 * enough of the packet to contain its size.
236 * @return True iff there is enough data in the packet to contain the packet's size.
238 bool Packet::HasPacketSizeData() const
240 return this->pos
>= EncodedLengthOfPacketSize();
244 * Get the number of bytes in the packet.
245 * When sending a packet this is the size of the data up to that moment.
246 * When receiving a packet (before PrepareToRead) this is the allocated size for the data to be read.
247 * When reading a packet (after PrepareToRead) this is the full size of the packet.
248 * @return The packet's size.
250 size_t Packet::Size() const
252 return this->buffer
.size();
256 * Reads the packet size from the raw packet and stores it in the packet->size
257 * @return True iff the packet size seems plausible.
259 bool Packet::ParsePacketSize()
261 size_t size
= static_cast<size_t>(this->buffer
[0]);
262 size
+= static_cast<size_t>(this->buffer
[1]) << 8;
264 /* If the size of the packet is less than the bytes required for the size and type of
265 * the packet, or more than the allowed limit, then something is wrong with the packet.
266 * In those cases the packet can generally be regarded as containing garbage data. */
267 if (size
< EncodedLengthOfPacketSize() + EncodedLengthOfPacketType() || size
> this->limit
) return false;
269 this->buffer
.resize(size
);
270 this->pos
= static_cast<PacketSize
>(EncodedLengthOfPacketSize());
275 * Prepares the packet so it can be read
276 * @return True when the packet was valid, otherwise false.
278 bool Packet::PrepareToRead()
280 /* Put the position on the right place */
281 this->pos
= static_cast<PacketSize
>(EncodedLengthOfPacketSize());
283 if (cs
== nullptr || cs
->receive_encryption_handler
== nullptr) return true;
285 size_t mac_size
= cs
->receive_encryption_handler
->MACSize();
286 if (this->buffer
.size() <= pos
+ mac_size
) return false;
288 bool valid
= cs
->receive_encryption_handler
->Decrypt(std::span(&this->buffer
[pos
], mac_size
), std::span(&this->buffer
[pos
+ mac_size
], this->buffer
.size() - pos
- mac_size
));
289 this->pos
+= static_cast<PacketSize
>(mac_size
);
294 * Get the \c PacketType from this packet.
295 * @return The packet type.
297 PacketType
Packet::GetPacketType() const
299 assert(this->Size() >= EncodedLengthOfPacketSize() + EncodedLengthOfPacketType());
300 size_t offset
= EncodedLengthOfPacketSize();
301 if (cs
!= nullptr && cs
->send_encryption_handler
!= nullptr) offset
+= cs
->send_encryption_handler
->MACSize();
302 return static_cast<PacketType
>(buffer
[offset
]);
306 * Read a boolean from the packet.
307 * @return The read data.
309 bool Packet::Recv_bool()
311 return this->Recv_uint8() != 0;
315 * Read a 8 bits integer from the packet.
316 * @return The read data.
318 uint8_t Packet::Recv_uint8()
322 if (!this->CanReadFromPacket(sizeof(n
), true)) return 0;
324 n
= this->buffer
[this->pos
++];
329 * Read a 16 bits integer from the packet.
330 * @return The read data.
332 uint16_t Packet::Recv_uint16()
336 if (!this->CanReadFromPacket(sizeof(n
), true)) return 0;
338 n
= (uint16_t)this->buffer
[this->pos
++];
339 n
+= (uint16_t)this->buffer
[this->pos
++] << 8;
344 * Read a 32 bits integer from the packet.
345 * @return The read data.
347 uint32_t Packet::Recv_uint32()
351 if (!this->CanReadFromPacket(sizeof(n
), true)) return 0;
353 n
= (uint32_t)this->buffer
[this->pos
++];
354 n
+= (uint32_t)this->buffer
[this->pos
++] << 8;
355 n
+= (uint32_t)this->buffer
[this->pos
++] << 16;
356 n
+= (uint32_t)this->buffer
[this->pos
++] << 24;
361 * Read a 64 bits integer from the packet.
362 * @return The read data.
364 uint64_t Packet::Recv_uint64()
368 if (!this->CanReadFromPacket(sizeof(n
), true)) return 0;
370 n
= (uint64_t)this->buffer
[this->pos
++];
371 n
+= (uint64_t)this->buffer
[this->pos
++] << 8;
372 n
+= (uint64_t)this->buffer
[this->pos
++] << 16;
373 n
+= (uint64_t)this->buffer
[this->pos
++] << 24;
374 n
+= (uint64_t)this->buffer
[this->pos
++] << 32;
375 n
+= (uint64_t)this->buffer
[this->pos
++] << 40;
376 n
+= (uint64_t)this->buffer
[this->pos
++] << 48;
377 n
+= (uint64_t)this->buffer
[this->pos
++] << 56;
382 * Extract a sized byte buffer from the packet.
383 * @return The extracted buffer.
385 std::vector
<uint8_t> Packet::Recv_buffer()
387 uint16_t size
= this->Recv_uint16();
388 if (size
== 0 || !this->CanReadFromPacket(size
, true)) return {};
390 std::vector
<uint8_t> data
;
392 data
.push_back(this->buffer
[this->pos
++]);
399 * Extract at most the length of the span bytes from the packet into the span.
400 * @param span The span to write the bytes to.
401 * @return The number of bytes that were actually read.
403 size_t Packet::Recv_bytes(std::span
<uint8_t> span
)
405 auto tranfer_to_span
= [](std::span
<uint8_t> destination
, const char *source
, size_t amount
) {
406 size_t to_copy
= std::min(amount
, destination
.size());
407 std::copy(source
, source
+ to_copy
, destination
.data());
411 return this->TransferOut(tranfer_to_span
, span
);
415 * Reads characters (bytes) from the packet until it finds a '\0', or reaches a
416 * maximum of \c length characters.
417 * When the '\0' has not been reached in the first \c length read characters,
418 * more characters are read from the packet until '\0' has been reached. However,
419 * these characters will not end up in the returned string.
420 * The length of the returned string will be at most \c length - 1 characters.
421 * @param length The maximum length of the string including '\0'.
422 * @param settings The string validation settings.
423 * @return The validated string.
425 std::string
Packet::Recv_string(size_t length
, StringValidationSettings settings
)
429 /* Both loops with Recv_uint8 terminate when reading past the end of the
430 * packet as Recv_uint8 then closes the connection and returns 0. */
433 while (--length
> 0 && (character
= this->Recv_uint8()) != '\0') str
.push_back(character
);
436 /* The string in the packet was longer. Read until the termination. */
437 while (this->Recv_uint8() != '\0') {}
440 return StrMakeValid(str
, settings
);
444 * Get the amount of bytes that are still available for the Transfer functions.
445 * @return The number of bytes that still have to be transfered.
447 size_t Packet::RemainingBytesToTransfer() const
449 return this->Size() - this->pos
;