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

OpenTTD Source 14.1

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 <http://www.gnu.org/licenses/>.
6 */
7
12 #include "../../stdafx.h"
13 #include "../../string_func.h"
14
15 #include "packet.h"
16
17 #include "../../safeguards.h"
18
31 Packet::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
47 Packet::Packet(PacketType type, size_t limit) : pos(0), limit(limit), cs(nullptr)
48 {
49 /* Allocate space for the the size so we can write that in just before sending the packet. */
50 this->Send_uint16(0);
51 this->Send_uint8(type);
52 }
53
54
58 void Packet::PrepareToSend()
59 {
60 assert(this->cs == nullptr);
61
62 this->buffer[0] = GB(this->Size(), 0, 8);
63 this->buffer[1] = GB(this->Size(), 8, 8);
64
65 this->pos = 0; // We start reading from here
66 this->buffer.shrink_to_fit();
67 }
68
74 bool Packet::CanWriteToPacket(size_t bytes_to_write)
75 {
76 return this->Size() + bytes_to_write <= this->limit;
77 }
78
79 /*
80 * The next couple of functions make sure we can send
81 * uint8_t, uint16_t, uint32_t and uint64_t endian-safe
82 * over the network. The least significant bytes are
83 * sent first.
84 *
85 * So 0x01234567 would be sent as 67 45 23 01.
86 *
87 * A bool is sent as a uint8_t where zero means false
88 * and non-zero means true.
89 */
90
95 void Packet::Send_bool(bool data)
96 {
97 this->Send_uint8(data ? 1 : 0);
98 }
99
104 void Packet::Send_uint8(uint8_t data)
105 {
106 assert(this->CanWriteToPacket(sizeof(data)));
107 this->buffer.emplace_back(data);
108 }
109
114 void Packet::Send_uint16(uint16_t data)
115 {
116 assert(this->CanWriteToPacket(sizeof(data)));
117 this->buffer.emplace_back(GB(data, 0, 8));
118 this->buffer.emplace_back(GB(data, 8, 8));
119 }
120
125 void Packet::Send_uint32(uint32_t data)
126 {
127 assert(this->CanWriteToPacket(sizeof(data)));
128 this->buffer.emplace_back(GB(data, 0, 8));
129 this->buffer.emplace_back(GB(data, 8, 8));
130 this->buffer.emplace_back(GB(data, 16, 8));
131 this->buffer.emplace_back(GB(data, 24, 8));
132 }
133
138 void Packet::Send_uint64(uint64_t data)
139 {
140 assert(this->CanWriteToPacket(sizeof(data)));
141 this->buffer.emplace_back(GB(data, 0, 8));
142 this->buffer.emplace_back(GB(data, 8, 8));
143 this->buffer.emplace_back(GB(data, 16, 8));
144 this->buffer.emplace_back(GB(data, 24, 8));
145 this->buffer.emplace_back(GB(data, 32, 8));
146 this->buffer.emplace_back(GB(data, 40, 8));
147 this->buffer.emplace_back(GB(data, 48, 8));
148 this->buffer.emplace_back(GB(data, 56, 8));
149 }
150
156 void Packet::Send_string(const std::string_view data)
157 {
158 assert(this->CanWriteToPacket(data.size() + 1));
159 this->buffer.insert(this->buffer.end(), data.begin(), data.end());
160 this->buffer.emplace_back('\0');
161 }
162
167 void Packet::Send_buffer(const std::vector<byte> &data)
168 {
169 assert(this->CanWriteToPacket(sizeof(uint16_t) + data.size()));
170 this->Send_uint16((uint16_t)data.size());
171 this->buffer.insert(this->buffer.end(), data.begin(), data.end());
172 }
173
182 size_t Packet::Send_bytes(const byte *begin, const byte *end)
183 {
184 size_t amount = std::min<size_t>(end - begin, this->limit - this->Size());
185 this->buffer.insert(this->buffer.end(), begin, begin + amount);
186 return amount;
187 }
188
189 /*
190 * Receiving commands
191 * Again, the next couple of functions are endian-safe
192 * see the comment before Send_bool for more info.
193 */
194
195
204 bool Packet::CanReadFromPacket(size_t bytes_to_read, bool close_connection)
205 {
206 /* Don't allow reading from a quit client/client who send bad data */
207 if (this->cs->HasClientQuit()) return false;
208
209 /* Check if variable is within packet-size */
210 if (this->pos + bytes_to_read > this->Size()) {
211 if (close_connection) this->cs->NetworkSocketHandler::MarkClosed();
212 return false;
213 }
214
215 return true;
216 }
217
223 bool Packet::HasPacketSizeData() const
224 {
225 return this->pos >= sizeof(PacketSize);
226 }
227
235 size_t Packet::Size() const
236 {
237 return this->buffer.size();
238 }
239
244 bool Packet::ParsePacketSize()
245 {
246 assert(this->cs != nullptr);
247 size_t size = (size_t)this->buffer[0];
248 size += (size_t)this->buffer[1] << 8;
249
250 /* If the size of the packet is less than the bytes required for the size and type of
251 * the packet, or more than the allowed limit, then something is wrong with the packet.
252 * In those cases the packet can generally be regarded as containing garbage data. */
253 if (size < sizeof(PacketSize) + sizeof(PacketType) || size > this->limit) return false;
254
255 this->buffer.resize(size);
256 this->pos = sizeof(PacketSize);
257 return true;
258 }
259
263 void Packet::PrepareToRead()
264 {
265 /* Put the position on the right place */
266 this->pos = sizeof(PacketSize);
267 }
268
273 PacketType Packet::GetPacketType() const
274 {
275 assert(this->Size() >= sizeof(PacketSize) + sizeof(PacketType));
276 return static_cast<PacketType>(buffer[sizeof(PacketSize)]);
277 }
278
283 bool Packet::Recv_bool()
284 {
285 return this->Recv_uint8() != 0;
286 }
287
292 uint8_t Packet::Recv_uint8()
293 {
294 uint8_t n;
295
296 if (!this->CanReadFromPacket(sizeof(n), true)) return 0;
297
298 n = this->buffer[this->pos++];
299 return n;
300 }
301
306 uint16_t Packet::Recv_uint16()
307 {
308 uint16_t n;
309
310 if (!this->CanReadFromPacket(sizeof(n), true)) return 0;
311
312 n = (uint16_t)this->buffer[this->pos++];
313 n += (uint16_t)this->buffer[this->pos++] << 8;
314 return n;
315 }
316
321 uint32_t Packet::Recv_uint32()
322 {
323 uint32_t n;
324
325 if (!this->CanReadFromPacket(sizeof(n), true)) return 0;
326
327 n = (uint32_t)this->buffer[this->pos++];
328 n += (uint32_t)this->buffer[this->pos++] << 8;
329 n += (uint32_t)this->buffer[this->pos++] << 16;
330 n += (uint32_t)this->buffer[this->pos++] << 24;
331 return n;
332 }
333
338 uint64_t Packet::Recv_uint64()
339 {
340 uint64_t n;
341
342 if (!this->CanReadFromPacket(sizeof(n), true)) return 0;
343
344 n = (uint64_t)this->buffer[this->pos++];
345 n += (uint64_t)this->buffer[this->pos++] << 8;
346 n += (uint64_t)this->buffer[this->pos++] << 16;
347 n += (uint64_t)this->buffer[this->pos++] << 24;
348 n += (uint64_t)this->buffer[this->pos++] << 32;
349 n += (uint64_t)this->buffer[this->pos++] << 40;
350 n += (uint64_t)this->buffer[this->pos++] << 48;
351 n += (uint64_t)this->buffer[this->pos++] << 56;
352 return n;
353 }
354
359 std::vector<byte> Packet::Recv_buffer()
360 {
361 uint16_t size = this->Recv_uint16();
362 if (size == 0 || !this->CanReadFromPacket(size, true)) return {};
363
364 std::vector<byte> data;
365 while (size-- > 0) {
366 data.push_back(this->buffer[this->pos++]);
367 }
368
369 return data;
370 }
371
383 std::string Packet::Recv_string(size_t length, StringValidationSettings settings)
384 {
385 assert(length > 1);
386
387 /* Both loops with Recv_uint8 terminate when reading past the end of the
388 * packet as Recv_uint8 then closes the connection and returns 0. */
389 std::string str;
390 char character;
391 while (--length > 0 && (character = this->Recv_uint8()) != '\0') str.push_back(character);
392
393 if (length == 0) {
394 /* The string in the packet was longer. Read until the termination. */
395 while (this->Recv_uint8() != '\0') {}
396 }
397
398 return StrMakeValid(str, settings);
399 }
400
405 size_t Packet::RemainingBytesToTransfer() const
406 {
407 return this->Size() - this->pos;
408 }
Packet::Recv_uint64
uint64_t Recv_uint64()
Read a 64 bits integer from the packet.
Definition: packet.cpp:338
Packet::Send_uint64
void Send_uint64(uint64_t data)
Package a 64 bits integer in the packet.
Definition: packet.cpp:138
Packet::PrepareToSend
void PrepareToSend()
Writes the packet size from the raw packet from packet->size.
Definition: packet.cpp:58
Packet::Size
size_t Size() const
Get the number of bytes in the packet.
Definition: packet.cpp:235
NetworkSocketHandler
SocketHandler for all network sockets in OpenTTD.
Definition: core.h:42
Packet::Send_bytes
size_t Send_bytes(const byte *begin, const byte *end)
Send as many of the bytes as possible in the packet.
Definition: packet.cpp:182
GB
constexpr static debug_inline 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
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:223
StrMakeValid
static void StrMakeValid(T &dst, const char *str, const char *last, StringValidationSettings settings)
Copies the valid (UTF-8) characters from str up to last to the dst.
Definition: string.cpp:114
PacketType
uint8_t PacketType
Identifier for the packet.
Definition: packet.h:21
Packet::ParsePacketSize
bool ParsePacketSize()
Reads the packet size from the raw packet and stores it in the packet->size.
Definition: packet.cpp:244
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:204
Packet::Recv_string
std::string Recv_string(size_t length, StringValidationSettings settings=SVS_REPLACE_WITH_QUESTION_MARK)
Reads characters (bytes) from the packet until it finds a '\0', or reaches a maximum of length charac...
Definition: packet.cpp:383
Packet::Packet
Packet(NetworkSocketHandler *cs, size_t limit, size_t initial_read_size=sizeof(PacketSize))
Create a packet that is used to read from a network socket.
Definition: packet.cpp:31
Packet::Send_uint32
void Send_uint32(uint32_t data)
Package a 32 bits integer in the packet.
Definition: packet.cpp:125
Packet::Send_uint8
void Send_uint8(uint8_t data)
Package a 8 bits integer in the packet.
Definition: packet.cpp:104
Packet::Recv_uint32
uint32_t Recv_uint32()
Read a 32 bits integer from the packet.
Definition: packet.cpp:321
Packet::PrepareToRead
void PrepareToRead()
Prepares the packet so it can be read.
Definition: packet.cpp:263
Packet::Send_buffer
void Send_buffer(const std::vector< byte > &data)
Copy a sized byte buffer into the packet.
Definition: packet.cpp:167
settings
fluid_settings_t * settings
FluidSynth settings handle.
Definition: fluidsynth.cpp:21
Packet::Recv_buffer
std::vector< byte > Recv_buffer()
Extract a sized byte buffer from the packet.
Definition: packet.cpp:359
PacketSize
uint16_t PacketSize
Size of the whole packet.
Definition: packet.h:20
StringValidationSettings
StringValidationSettings
Settings for the string validation.
Definition: string_type.h:44
Packet::Send_bool
void Send_bool(bool data)
Package a boolean in the packet.
Definition: packet.cpp:95
Packet::limit
size_t limit
The limit for the packet size.
Definition: packet.h:49
NetworkSocketHandler::HasClientQuit
bool HasClientQuit() const
Whether the current client connected to the socket has quit.
Definition: core.h:68
Packet::GetPacketType
PacketType GetPacketType() const
Get the PacketType from this packet.
Definition: packet.cpp:273
Packet::CanWriteToPacket
bool CanWriteToPacket(size_t bytes_to_write)
Is it safe to write to the packet, i.e.
Definition: packet.cpp:74
Packet::Recv_bool
bool Recv_bool()
Read a boolean from the packet.
Definition: packet.cpp:283
packet.h
Packet::cs
NetworkSocketHandler * cs
Socket we're associated with.
Definition: packet.h:52
Packet::Send_string
void Send_string(const std::string_view data)
Sends a string over the network.
Definition: packet.cpp:156
Packet::buffer
std::vector< byte > buffer
The buffer of this packet.
Definition: packet.h:47
Packet::Recv_uint16
uint16_t Recv_uint16()
Read a 16 bits integer from the packet.
Definition: packet.cpp:306
Packet::RemainingBytesToTransfer
size_t RemainingBytesToTransfer() const
Get the amount of bytes that are still available for the Transfer functions.
Definition: packet.cpp:405
Packet::Send_uint16
void Send_uint16(uint16_t data)
Package a 16 bits integer in the packet.
Definition: packet.cpp:114
Packet::Recv_uint8
uint8_t Recv_uint8()
Read a 8 bits integer from the packet.
Definition: packet.cpp:292
Packet::pos
PacketSize pos
The current read/write position in the packet.
Definition: packet.h:45