OpenTTD Source  20241121-master-g67a0fccfad
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 
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 
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(const 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 
197 std::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 
239 {
240  return this->pos >= EncodedLengthOfPacketSize();
241 }
242 
250 size_t Packet::Size() const
251 {
252  return this->buffer.size();
253 }
254 
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 
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 
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 
310 {
311  return this->Recv_uint8() != 0;
312 }
313 
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 
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 
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 
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 
385 std::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> span)
404 {
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());
408  return to_copy;
409  };
410 
411  return this->TransferOut(tranfer_to_span, span);
412 }
413 
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 
448 {
449  return this->Size() - this->pos;
450 }
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.
SocketHandler for all network sockets in OpenTTD.
Definition: core.h:43
bool HasClientQuit() const
Whether the current client connected to the socket has quit.
Definition: core.h:74
std::unique_ptr< class NetworkEncryptionHandler > send_encryption_handler
The handler for encrypting sent packets.
Definition: core.h:50
std::unique_ptr< class NetworkEncryptionHandler > receive_encryption_handler
The handler for decrypting received packets.
Definition: core.h:49
fluid_settings_t * settings
FluidSynth settings handle.
Definition: fluidsynth.cpp:21
uint8_t valid
Bits indicating what variable is valid (for each bit, 0 is invalid, 1 is valid).
Basic functions to create, fill and read packets.
uint8_t PacketType
Identifier for the packet.
Definition: packet.h:21
uint16_t PacketSize
Size of the whole packet.
Definition: packet.h:20
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:107
StringValidationSettings
Settings for the string validation.
Definition: string_type.h:44
size_t Size() const
Get the number of bytes in the packet.
Definition: packet.cpp:250
uint16_t Recv_uint16()
Read a 16 bits integer from the packet.
Definition: packet.cpp:332
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
uint64_t Recv_uint64()
Read a 64 bits integer from the packet.
Definition: packet.cpp:364
bool Recv_bool()
Read a boolean from the packet.
Definition: packet.cpp:309
uint32_t Recv_uint32()
Read a 32 bits integer from the packet.
Definition: packet.cpp:347
NetworkSocketHandler * cs
Socket we're associated with.
Definition: packet.h:54
void Send_bool(bool data)
Package a boolean in the packet.
Definition: packet.cpp:111
bool PrepareToRead()
Prepares the packet so it can be read.
Definition: packet.cpp:278
PacketType GetPacketType() const
Get the PacketType from this packet.
Definition: packet.cpp:297
PacketSize pos
The current read/write position in the packet.
Definition: packet.h:47
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
size_t limit
The limit for the packet size.
Definition: packet.h:51
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
uint8_t Recv_uint8()
Read a 8 bits integer from the packet.
Definition: packet.cpp:318
bool ParsePacketSize()
Reads the packet size from the raw packet and stores it in the packet->size.
Definition: packet.cpp:259
std::vector< uint8_t > buffer
The buffer of this packet.
Definition: packet.h:49
void PrepareToSend()
Writes the packet size from the raw packet from packet->size.
Definition: packet.cpp:66
void Send_uint8(uint8_t data)
Package a 8 bits integer in the packet.
Definition: packet.cpp:120
size_t RemainingBytesToTransfer() const
Get the amount of bytes that are still available for the Transfer functions.
Definition: packet.cpp:447
void Send_uint32(uint32_t data)
Package a 32 bits integer in the packet.
Definition: packet.cpp:141
ssize_t TransferOut(F transfer_function, D destination, Args &&... args)
Transfer data from the packet to the given function.
Definition: packet.h:139
void Send_buffer(const std::vector< uint8_t > &data)
Copy a sized byte buffer into the packet.
Definition: packet.cpp:183
std::vector< uint8_t > Recv_buffer()
Extract a sized byte buffer from the packet.
Definition: packet.cpp:385
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
void Send_uint16(uint16_t data)
Package a 16 bits integer in the packet.
Definition: packet.cpp:130
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
bool CanWriteToPacket(size_t bytes_to_write)
Is it safe to write to the packet, i.e.
Definition: packet.cpp:90
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:425
void Send_string(const std::string_view data)
Sends a string over the network.
Definition: packet.cpp:172
void Send_uint64(uint64_t data)
Package a 64 bits integer in the packet.
Definition: packet.cpp:154