OpenTTD Source: src/network/core/packet.cpp Source File

OpenTTD Source 15.3

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
12#include "../../stdafx.h"
13#include "../../string_func.h"
14
15#include "packet.h"
16
17#include "../../safeguards.h"
18
31Packet::Packet(NetworkSocketHandler *cs, size_t limit, size_t initial_read_size) : pos(0), limit(limit)
32{
33 assert(cs != nullptr);
34
35 this->cs = cs;
36 this->buffer.resize(initial_read_size);
37}
38
48 Packet::Packet(NetworkSocketHandler *cs, PacketType type, size_t limit) : pos(0), limit(limit), cs(cs)
49{
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();
55 }
56 assert(this->CanWriteToPacket(size));
57 this->buffer.resize(size, 0);
58
59 this->Send_uint8(type);
60}
61
62
66 void Packet::PrepareToSend()
67{
68 /* Prevent this to be called twice and for packets that have been received. */
69 assert(this->buffer[0] == 0 && this->buffer[1] == 0);
70
71 this->buffer[0] = GB(this->Size(), 0, 8);
72 this->buffer[1] = GB(this->Size(), 8, 8);
73
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));
79 }
80
81 this->pos = 0; // We start reading from here
82 this->buffer.shrink_to_fit();
83}
84
90 bool Packet::CanWriteToPacket(size_t bytes_to_write)
91{
92 return this->Size() + bytes_to_write <= this->limit;
93}
94
95/*
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
99 * sent first.
100 *
101 * So 0x01234567 would be sent as 67 45 23 01.
102 *
103 * A bool is sent as a uint8_t where zero means false
104 * and non-zero means true.
105 */
106
111 void Packet::Send_bool(bool data)
112{
113 this->Send_uint8(data ? 1 : 0);
114}
115
120 void Packet::Send_uint8(uint8_t data)
121{
122 assert(this->CanWriteToPacket(sizeof(data)));
123 this->buffer.emplace_back(data);
124}
125
130 void Packet::Send_uint16(uint16_t data)
131{
132 assert(this->CanWriteToPacket(sizeof(data)));
133 this->buffer.emplace_back(GB(data, 0, 8));
134 this->buffer.emplace_back(GB(data, 8, 8));
135}
136
141 void Packet::Send_uint32(uint32_t data)
142{
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));
148}
149
154 void Packet::Send_uint64(uint64_t data)
155{
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));
165}
166
172 void Packet::Send_string(std::string_view data)
173{
174 assert(this->CanWriteToPacket(data.size() + 1));
175 this->buffer.insert(this->buffer.end(), data.begin(), data.end());
176 this->buffer.emplace_back('\0');
177}
178
183 void Packet::Send_buffer(const std::vector<uint8_t> &data)
184{
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());
188}
189
197std::span<const uint8_t> Packet::Send_bytes(const std::span<const uint8_t> span)
198{
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);
202}
203
204/*
205 * Receiving commands
206 * Again, the next couple of functions are endian-safe
207 * see the comment before Send_bool for more info.
208 */
209
210
219 bool Packet::CanReadFromPacket(size_t bytes_to_read, bool close_connection)
220{
221 /* Don't allow reading from a quit client/client who send bad data */
222 if (this->cs->HasClientQuit()) return false;
223
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();
227 return false;
228 }
229
230 return true;
231}
232
238 bool Packet::HasPacketSizeData() const
239{
240 return this->pos >= EncodedLengthOfPacketSize();
241}
242
250 size_t Packet::Size() const
251{
252 return this->buffer.size();
253}
254
259 bool Packet::ParsePacketSize()
260{
261 size_t size = static_cast<size_t>(this->buffer[0]);
262 size += static_cast<size_t>(this->buffer[1]) << 8;
263
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;
268
269 this->buffer.resize(size);
270 this->pos = static_cast<PacketSize>(EncodedLengthOfPacketSize());
271 return true;
272}
273
278 bool Packet::PrepareToRead()
279{
280 /* Put the position on the right place */
281 this->pos = static_cast<PacketSize>(EncodedLengthOfPacketSize());
282
283 if (cs == nullptr || cs->receive_encryption_handler == nullptr) return true;
284
285 size_t mac_size = cs->receive_encryption_handler->MACSize();
286 if (this->buffer.size() <= pos + mac_size) return false;
287
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);
290 return valid;
291}
292
297 PacketType Packet::GetPacketType() const
298{
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]);
303}
304
309 bool Packet::Recv_bool()
310{
311 return this->Recv_uint8() != 0;
312}
313
318uint8_t Packet::Recv_uint8()
319{
320 uint8_t n;
321
322 if (!this->CanReadFromPacket(sizeof(n), true)) return 0;
323
324 n = this->buffer[this->pos++];
325 return n;
326}
327
332uint16_t Packet::Recv_uint16()
333{
334 uint16_t n;
335
336 if (!this->CanReadFromPacket(sizeof(n), true)) return 0;
337
338 n = (uint16_t)this->buffer[this->pos++];
339 n += (uint16_t)this->buffer[this->pos++] << 8;
340 return n;
341}
342
347uint32_t Packet::Recv_uint32()
348{
349 uint32_t n;
350
351 if (!this->CanReadFromPacket(sizeof(n), true)) return 0;
352
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;
357 return n;
358}
359
364uint64_t Packet::Recv_uint64()
365{
366 uint64_t n;
367
368 if (!this->CanReadFromPacket(sizeof(n), true)) return 0;
369
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;
378 return n;
379}
380
385std::vector<uint8_t> Packet::Recv_buffer()
386{
387 uint16_t size = this->Recv_uint16();
388 if (size == 0 || !this->CanReadFromPacket(size, true)) return {};
389
390 std::vector<uint8_t> data;
391 while (size-- > 0) {
392 data.push_back(this->buffer[this->pos++]);
393 }
394
395 return data;
396}
397
403 size_t Packet::Recv_bytes(std::span<uint8_t> destination)
404{
405 auto transfer_to_span = [&destination](std::span<const uint8_t> source) {
406 auto to_copy = source.subspan(0, destination.size());
407 std::ranges::copy(to_copy, destination.begin());
408 return to_copy.size();
409 };
410
411 return this->TransferOut(transfer_to_span);
412}
413
425std::string Packet::Recv_string(size_t length, StringValidationSettings settings)
426{
427 assert(length > 1);
428
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. */
431 std::string str;
432 char character;
433 while (--length > 0 && (character = this->Recv_uint8()) != '\0') str.push_back(character);
434
435 if (length == 0) {
436 /* The string in the packet was longer. Read until the termination. */
437 while (this->Recv_uint8() != '\0') {}
438 }
439
440 return StrMakeValid(str, settings);
441}
442
447 size_t Packet::RemainingBytesToTransfer() const
448{
449 return this->Size() - this->pos;
450}
GB
static constexpr uint GB(const T x, const uint8_t s, const uint8_t n)
Fetch n bits from x, started at bit s.
Definition bitmath_func.hpp:32
EnumBitSet
Enum-as-bit-set wrapper.
Definition enum_type.hpp:177
NetworkSocketHandler
SocketHandler for all network sockets in OpenTTD.
Definition core.h:43
NetworkSocketHandler::HasClientQuit
bool HasClientQuit() const
Whether the current client connected to the socket has quit.
Definition core.h:74
NetworkSocketHandler::send_encryption_handler
std::unique_ptr< class NetworkEncryptionHandler > send_encryption_handler
The handler for encrypting sent packets.
Definition core.h:50
NetworkSocketHandler::receive_encryption_handler
std::unique_ptr< class NetworkEncryptionHandler > receive_encryption_handler
The handler for decrypting received packets.
Definition core.h:49
settings
fluid_settings_t * settings
FluidSynth settings handle.
Definition fluidsynth.cpp:25
packet.h
Basic functions to create, fill and read packets.
PacketType
uint8_t PacketType
Identifier for the packet.
Definition packet.h:22
PacketSize
uint16_t PacketSize
Size of the whole packet.
Definition packet.h:21
StrMakeValid
static void StrMakeValid(Builder &builder, StringConsumer &consumer, StringValidationSettings settings)
Copies the valid (UTF-8) characters from consumer to the builder.
Definition string.cpp:119
Packet::Size
size_t Size() const
Get the number of bytes in the packet.
Definition packet.cpp:250
Packet::Recv_uint16
uint16_t Recv_uint16()
Read a 16 bits integer from the packet.
Definition packet.cpp:332
Packet::Recv_bytes
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:403
Packet::Recv_uint64
uint64_t Recv_uint64()
Read a 64 bits integer from the packet.
Definition packet.cpp:364
Packet::Recv_bool
bool Recv_bool()
Read a boolean from the packet.
Definition packet.cpp:309
Packet::Recv_uint32
uint32_t Recv_uint32()
Read a 32 bits integer from the packet.
Definition packet.cpp:347
Packet::cs
NetworkSocketHandler * cs
Socket we're associated with.
Definition packet.h:55
Packet::Send_string
void Send_string(std::string_view data)
Sends a string over the network.
Definition packet.cpp:172
Packet::Recv_string
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:425
Packet::Send_bool
void Send_bool(bool data)
Package a boolean in the packet.
Definition packet.cpp:111
Packet::PrepareToRead
bool PrepareToRead()
Prepares the packet so it can be read.
Definition packet.cpp:278
Packet::GetPacketType
PacketType GetPacketType() const
Get the PacketType from this packet.
Definition packet.cpp:297
Packet::pos
PacketSize pos
The current read/write position in the packet.
Definition packet.h:48
Packet::Send_bytes
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:197
Packet::limit
size_t limit
The limit for the packet size.
Definition packet.h:52
Packet::HasPacketSizeData
bool HasPacketSizeData() const
Check whether the packet, given the position of the "write" pointer, has read enough of the packet to...
Definition packet.cpp:238
Packet::Recv_uint8
uint8_t Recv_uint8()
Read a 8 bits integer from the packet.
Definition packet.cpp:318
Packet::ParsePacketSize
bool ParsePacketSize()
Reads the packet size from the raw packet and stores it in the packet->size.
Definition packet.cpp:259
Packet::buffer
std::vector< uint8_t > buffer
The buffer of this packet.
Definition packet.h:50
Packet::PrepareToSend
void PrepareToSend()
Writes the packet size from the raw packet from packet->size.
Definition packet.cpp:66
Packet::Send_uint8
void Send_uint8(uint8_t data)
Package a 8 bits integer in the packet.
Definition packet.cpp:120
Packet::RemainingBytesToTransfer
size_t RemainingBytesToTransfer() const
Get the amount of bytes that are still available for the Transfer functions.
Definition packet.cpp:447
Packet::Send_uint32
void Send_uint32(uint32_t data)
Package a 32 bits integer in the packet.
Definition packet.cpp:141
Packet::Send_buffer
void Send_buffer(const std::vector< uint8_t > &data)
Copy a sized byte buffer into the packet.
Definition packet.cpp:183
Packet::Recv_buffer
std::vector< uint8_t > Recv_buffer()
Extract a sized byte buffer from the packet.
Definition packet.cpp:385
Packet::Packet
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:31
Packet::Send_uint16
void Send_uint16(uint16_t data)
Package a 16 bits integer in the packet.
Definition packet.cpp:130
Packet::CanReadFromPacket
bool CanReadFromPacket(size_t bytes_to_read, bool close_connection=false)
Is it safe to read from the packet, i.e.
Definition packet.cpp:219
Packet::CanWriteToPacket
bool CanWriteToPacket(size_t bytes_to_write)
Is it safe to write to the packet, i.e.
Definition packet.cpp:90
Packet::Send_uint64
void Send_uint64(uint64_t data)
Package a 64 bits integer in the packet.
Definition packet.cpp:154
Packet::TransferOut
ssize_t TransferOut(F transfer_function)
Transfer data from the packet to the given function.
Definition packet.h:128