OpenTTD Source 20260108-master-g8ba1860eaa
packet.cpp
Go to the documentation of this file.
1/*
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 <https://www.gnu.org/licenses/old-licenses/gpl-2.0>.
6 */
7
10#include "../../stdafx.h"
11#include "../../string_func.h"
12
13#include "packet.h"
14
15#include "../../safeguards.h"
16
29Packet::Packet(NetworkSocketHandler *cs, size_t limit, size_t initial_read_size) : pos(0), limit(limit)
30{
31 assert(cs != nullptr);
32
33 this->cs = cs;
34 this->buffer.resize(initial_read_size);
35}
36
46Packet::Packet(NetworkSocketHandler *cs, PacketType type, size_t limit) : pos(0), limit(limit), cs(cs)
47{
48 /* Allocate space for the the size so we can write that in just before sending the packet. */
49 size_t size = EncodedLengthOfPacketSize();
50 if (cs != nullptr && cs->send_encryption_handler != nullptr) {
51 /* Allocate some space for the message authentication code of the encryption. */
52 size += cs->send_encryption_handler->MACSize();
53 }
54 assert(this->CanWriteToPacket(size));
55 this->buffer.resize(size, 0);
56
57 this->Send_uint8(type);
58}
59
60
65{
66 /* Prevent this to be called twice and for packets that have been received. */
67 assert(this->buffer[0] == 0 && this->buffer[1] == 0);
68
69 this->buffer[0] = GB(this->Size(), 0, 8);
70 this->buffer[1] = GB(this->Size(), 8, 8);
71
72 if (cs != nullptr && cs->send_encryption_handler != nullptr) {
73 size_t offset = EncodedLengthOfPacketSize();
74 size_t mac_size = cs->send_encryption_handler->MACSize();
75 size_t message_offset = offset + mac_size;
76 cs->send_encryption_handler->Encrypt(std::span(&this->buffer[offset], mac_size), std::span(&this->buffer[message_offset], this->buffer.size() - message_offset));
77 }
78
79 this->pos = 0; // We start reading from here
80 this->buffer.shrink_to_fit();
81}
82
88bool Packet::CanWriteToPacket(size_t bytes_to_write)
89{
90 return this->Size() + bytes_to_write <= this->limit;
91}
92
93/*
94 * The next couple of functions make sure we can send
95 * uint8_t, uint16_t, uint32_t and uint64_t endian-safe
96 * over the network. The least significant bytes are
97 * sent first.
98 *
99 * So 0x01234567 would be sent as 67 45 23 01.
100 *
101 * A bool is sent as a uint8_t where zero means false
102 * and non-zero means true.
103 */
104
109void Packet::Send_bool(bool data)
110{
111 this->Send_uint8(data ? 1 : 0);
112}
113
118void Packet::Send_uint8(uint8_t data)
119{
120 assert(this->CanWriteToPacket(sizeof(data)));
121 this->buffer.emplace_back(data);
122}
123
128void Packet::Send_uint16(uint16_t data)
129{
130 assert(this->CanWriteToPacket(sizeof(data)));
131 this->buffer.emplace_back(GB(data, 0, 8));
132 this->buffer.emplace_back(GB(data, 8, 8));
133}
134
139void Packet::Send_uint32(uint32_t data)
140{
141 assert(this->CanWriteToPacket(sizeof(data)));
142 this->buffer.emplace_back(GB(data, 0, 8));
143 this->buffer.emplace_back(GB(data, 8, 8));
144 this->buffer.emplace_back(GB(data, 16, 8));
145 this->buffer.emplace_back(GB(data, 24, 8));
146}
147
152void Packet::Send_uint64(uint64_t data)
153{
154 assert(this->CanWriteToPacket(sizeof(data)));
155 this->buffer.emplace_back(GB(data, 0, 8));
156 this->buffer.emplace_back(GB(data, 8, 8));
157 this->buffer.emplace_back(GB(data, 16, 8));
158 this->buffer.emplace_back(GB(data, 24, 8));
159 this->buffer.emplace_back(GB(data, 32, 8));
160 this->buffer.emplace_back(GB(data, 40, 8));
161 this->buffer.emplace_back(GB(data, 48, 8));
162 this->buffer.emplace_back(GB(data, 56, 8));
163}
164
170void Packet::Send_string(std::string_view data)
171{
172 assert(this->CanWriteToPacket(data.size() + 1));
173 this->buffer.insert(this->buffer.end(), data.begin(), data.end());
174 this->buffer.emplace_back('\0');
175}
176
181void Packet::Send_buffer(const std::vector<uint8_t> &data)
182{
183 assert(this->CanWriteToPacket(sizeof(uint16_t) + data.size()));
184 this->Send_uint16((uint16_t)data.size());
185 this->buffer.insert(this->buffer.end(), data.begin(), data.end());
186}
187
195std::span<const uint8_t> Packet::Send_bytes(const std::span<const uint8_t> span)
196{
197 size_t amount = std::min<size_t>(span.size(), this->limit - this->Size());
198 this->buffer.insert(this->buffer.end(), span.data(), span.data() + amount);
199 return span.subspan(amount);
200}
201
202/*
203 * Receiving commands
204 * Again, the next couple of functions are endian-safe
205 * see the comment before Send_bool for more info.
206 */
207
208
217bool Packet::CanReadFromPacket(size_t bytes_to_read, bool close_connection)
218{
219 /* Don't allow reading from a quit client/client who send bad data */
220 if (this->cs->HasClientQuit()) return false;
221
222 /* Check if variable is within packet-size */
223 if (this->pos + bytes_to_read > this->Size()) {
224 if (close_connection) this->cs->NetworkSocketHandler::MarkClosed();
225 return false;
226 }
227
228 return true;
229}
230
237{
238 return this->pos >= EncodedLengthOfPacketSize();
239}
240
248size_t Packet::Size() const
249{
250 return this->buffer.size();
251}
252
258{
259 size_t size = static_cast<size_t>(this->buffer[0]);
260 size += static_cast<size_t>(this->buffer[1]) << 8;
261
262 /* If the size of the packet is less than the bytes required for the size and type of
263 * the packet, or more than the allowed limit, then something is wrong with the packet.
264 * In those cases the packet can generally be regarded as containing garbage data. */
265 if (size < EncodedLengthOfPacketSize() + EncodedLengthOfPacketType() || size > this->limit) return false;
266
267 this->buffer.resize(size);
268 this->pos = static_cast<PacketSize>(EncodedLengthOfPacketSize());
269 return true;
270}
271
277{
278 /* Put the position on the right place */
279 this->pos = static_cast<PacketSize>(EncodedLengthOfPacketSize());
280
281 if (cs == nullptr || cs->receive_encryption_handler == nullptr) return true;
282
283 size_t mac_size = cs->receive_encryption_handler->MACSize();
284 if (this->buffer.size() <= pos + mac_size) return false;
285
286 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));
287 this->pos += static_cast<PacketSize>(mac_size);
288 return valid;
289}
290
296{
297 assert(this->Size() >= EncodedLengthOfPacketSize() + EncodedLengthOfPacketType());
298 size_t offset = EncodedLengthOfPacketSize();
299 if (cs != nullptr && cs->send_encryption_handler != nullptr) offset += cs->send_encryption_handler->MACSize();
300 return static_cast<PacketType>(buffer[offset]);
301}
302
308{
309 return this->Recv_uint8() != 0;
310}
311
317{
318 uint8_t n;
319
320 if (!this->CanReadFromPacket(sizeof(n), true)) return 0;
321
322 n = this->buffer[this->pos++];
323 return n;
324}
325
331{
332 uint16_t n;
333
334 if (!this->CanReadFromPacket(sizeof(n), true)) return 0;
335
336 n = (uint16_t)this->buffer[this->pos++];
337 n += (uint16_t)this->buffer[this->pos++] << 8;
338 return n;
339}
340
346{
347 uint32_t n;
348
349 if (!this->CanReadFromPacket(sizeof(n), true)) return 0;
350
351 n = (uint32_t)this->buffer[this->pos++];
352 n += (uint32_t)this->buffer[this->pos++] << 8;
353 n += (uint32_t)this->buffer[this->pos++] << 16;
354 n += (uint32_t)this->buffer[this->pos++] << 24;
355 return n;
356}
357
363{
364 uint64_t n;
365
366 if (!this->CanReadFromPacket(sizeof(n), true)) return 0;
367
368 n = (uint64_t)this->buffer[this->pos++];
369 n += (uint64_t)this->buffer[this->pos++] << 8;
370 n += (uint64_t)this->buffer[this->pos++] << 16;
371 n += (uint64_t)this->buffer[this->pos++] << 24;
372 n += (uint64_t)this->buffer[this->pos++] << 32;
373 n += (uint64_t)this->buffer[this->pos++] << 40;
374 n += (uint64_t)this->buffer[this->pos++] << 48;
375 n += (uint64_t)this->buffer[this->pos++] << 56;
376 return n;
377}
378
383std::vector<uint8_t> Packet::Recv_buffer()
384{
385 uint16_t size = this->Recv_uint16();
386 if (size == 0 || !this->CanReadFromPacket(size, true)) return {};
387
388 std::vector<uint8_t> data;
389 while (size-- > 0) {
390 data.push_back(this->buffer[this->pos++]);
391 }
392
393 return data;
394}
395
401size_t Packet::Recv_bytes(std::span<uint8_t> destination)
402{
403 auto transfer_to_span = [&destination](std::span<const uint8_t> source) {
404 auto to_copy = source.subspan(0, destination.size());
405 std::ranges::copy(to_copy, destination.begin());
406 return to_copy.size();
407 };
408
409 return this->TransferOut(transfer_to_span);
410}
411
424{
425 assert(length > 1);
426
427 /* Both loops with Recv_uint8 terminate when reading past the end of the
428 * packet as Recv_uint8 then closes the connection and returns 0. */
429 std::string str;
430 char character;
431 while (--length > 0 && (character = this->Recv_uint8()) != '\0') str.push_back(character);
432
433 if (length == 0) {
434 /* The string in the packet was longer. Read until the termination. */
435 while (this->Recv_uint8() != '\0') {}
436 }
437
438 return StrMakeValid(str, settings);
439}
440
446{
447 return this->Size() - this->pos;
448}
static constexpr uint GB(const T x, const uint8_t s, const uint8_t n)
Fetch n bits from x, started at bit s.
Enum-as-bit-set wrapper.
SocketHandler for all network sockets in OpenTTD.
Definition core.h:41
bool HasClientQuit() const
Whether the current client connected to the socket has quit.
Definition core.h:72
std::unique_ptr< class NetworkEncryptionHandler > send_encryption_handler
The handler for encrypting sent packets.
Definition core.h:48
std::unique_ptr< class NetworkEncryptionHandler > receive_encryption_handler
The handler for decrypting received packets.
Definition core.h:47
fluid_settings_t * settings
FluidSynth settings handle.
Basic functions to create, fill and read packets.
uint8_t PacketType
Identifier for the packet.
Definition packet.h:20
uint16_t PacketSize
Size of the whole packet.
Definition packet.h:19
static void StrMakeValid(Builder &builder, StringConsumer &consumer, StringValidationSettings settings)
Copies the valid (UTF-8) characters from consumer to the builder.
Definition string.cpp:119
size_t Size() const
Get the number of bytes in the packet.
Definition packet.cpp:248
uint16_t Recv_uint16()
Read a 16 bits integer from the packet.
Definition packet.cpp:330
size_t Recv_bytes(std::span< uint8_t > span)
Extract at most the length of the span bytes from the packet into the span.
Definition packet.cpp:401
uint64_t Recv_uint64()
Read a 64 bits integer from the packet.
Definition packet.cpp:362
bool Recv_bool()
Read a boolean from the packet.
Definition packet.cpp:307
uint32_t Recv_uint32()
Read a 32 bits integer from the packet.
Definition packet.cpp:345
NetworkSocketHandler * cs
Socket we're associated with.
Definition packet.h:53
void Send_string(std::string_view data)
Sends a string over the network.
Definition packet.cpp:170
std::string Recv_string(size_t length, StringValidationSettings settings=StringValidationSetting::ReplaceWithQuestionMark)
Reads characters (bytes) from the packet until it finds a '\0', or reaches a maximum of length charac...
Definition packet.cpp:423
void Send_bool(bool data)
Package a boolean in the packet.
Definition packet.cpp:109
bool PrepareToRead()
Prepares the packet so it can be read.
Definition packet.cpp:276
PacketType GetPacketType() const
Get the PacketType from this packet.
Definition packet.cpp:295
PacketSize pos
The current read/write position in the packet.
Definition packet.h:46
std::span< const uint8_t > Send_bytes(const std::span< const uint8_t > span)
Send as many of the bytes as possible in the packet.
Definition packet.cpp:195
size_t limit
The limit for the packet size.
Definition packet.h:50
bool HasPacketSizeData() const
Check whether the packet, given the position of the "write" pointer, has read enough of the packet to...
Definition packet.cpp:236
uint8_t Recv_uint8()
Read a 8 bits integer from the packet.
Definition packet.cpp:316
bool ParsePacketSize()
Reads the packet size from the raw packet and stores it in the packet->size.
Definition packet.cpp:257
std::vector< uint8_t > buffer
The buffer of this packet.
Definition packet.h:48
void PrepareToSend()
Writes the packet size from the raw packet from packet->size.
Definition packet.cpp:64
void Send_uint8(uint8_t data)
Package a 8 bits integer in the packet.
Definition packet.cpp:118
size_t RemainingBytesToTransfer() const
Get the amount of bytes that are still available for the Transfer functions.
Definition packet.cpp:445
void Send_uint32(uint32_t data)
Package a 32 bits integer in the packet.
Definition packet.cpp:139
void Send_buffer(const std::vector< uint8_t > &data)
Copy a sized byte buffer into the packet.
Definition packet.cpp:181
std::vector< uint8_t > Recv_buffer()
Extract a sized byte buffer from the packet.
Definition packet.cpp:383
Packet(NetworkSocketHandler *cs, size_t limit, size_t initial_read_size=EncodedLengthOfPacketSize())
Create a packet that is used to read from a network socket.
Definition packet.cpp:29
void Send_uint16(uint16_t data)
Package a 16 bits integer in the packet.
Definition packet.cpp:128
bool CanReadFromPacket(size_t bytes_to_read, bool close_connection=false)
Is it safe to read from the packet, i.e.
Definition packet.cpp:217
bool CanWriteToPacket(size_t bytes_to_write)
Is it safe to write to the packet, i.e.
Definition packet.cpp:88
void Send_uint64(uint64_t data)
Package a 64 bits integer in the packet.
Definition packet.cpp:152
ssize_t TransferOut(F transfer_function)
Transfer data from the packet to the given function.
Definition packet.h:126