OpenTTD Source  12.0-beta2
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) : next(nullptr), 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) : next(nullptr), 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 
59 /* static */ void Packet::AddToQueue(Packet **queue, Packet *packet)
60 {
61  while (*queue != nullptr) queue = &(*queue)->next;
62  *queue = packet;
63 }
64 
71 /* static */ Packet *Packet::PopFromQueue(Packet **queue)
72 {
73  Packet *p = *queue;
74  *queue = p->next;
75  p->next = nullptr;
76  return p;
77 }
78 
79 
84 {
85  assert(this->cs == nullptr && this->next == nullptr);
86 
87  this->buffer[0] = GB(this->Size(), 0, 8);
88  this->buffer[1] = GB(this->Size(), 8, 8);
89 
90  this->pos = 0; // We start reading from here
91  this->buffer.shrink_to_fit();
92 }
93 
99 bool Packet::CanWriteToPacket(size_t bytes_to_write)
100 {
101  return this->Size() + bytes_to_write <= this->limit;
102 }
103 
104 /*
105  * The next couple of functions make sure we can send
106  * uint8, uint16, uint32 and uint64 endian-safe
107  * over the network. The least significant bytes are
108  * sent first.
109  *
110  * So 0x01234567 would be sent as 67 45 23 01.
111  *
112  * A bool is sent as a uint8 where zero means false
113  * and non-zero means true.
114  */
115 
120 void Packet::Send_bool(bool data)
121 {
122  this->Send_uint8(data ? 1 : 0);
123 }
124 
129 void Packet::Send_uint8(uint8 data)
130 {
131  assert(this->CanWriteToPacket(sizeof(data)));
132  this->buffer.emplace_back(data);
133 }
134 
139 void Packet::Send_uint16(uint16 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 }
145 
150 void Packet::Send_uint32(uint32 data)
151 {
152  assert(this->CanWriteToPacket(sizeof(data)));
153  this->buffer.emplace_back(GB(data, 0, 8));
154  this->buffer.emplace_back(GB(data, 8, 8));
155  this->buffer.emplace_back(GB(data, 16, 8));
156  this->buffer.emplace_back(GB(data, 24, 8));
157 }
158 
163 void Packet::Send_uint64(uint64 data)
164 {
165  assert(this->CanWriteToPacket(sizeof(data)));
166  this->buffer.emplace_back(GB(data, 0, 8));
167  this->buffer.emplace_back(GB(data, 8, 8));
168  this->buffer.emplace_back(GB(data, 16, 8));
169  this->buffer.emplace_back(GB(data, 24, 8));
170  this->buffer.emplace_back(GB(data, 32, 8));
171  this->buffer.emplace_back(GB(data, 40, 8));
172  this->buffer.emplace_back(GB(data, 48, 8));
173  this->buffer.emplace_back(GB(data, 56, 8));
174 }
175 
181 void Packet::Send_string(const std::string_view data)
182 {
183  assert(this->CanWriteToPacket(data.size() + 1));
184  this->buffer.insert(this->buffer.end(), data.begin(), data.end());
185  this->buffer.emplace_back('\0');
186 }
187 
196 size_t Packet::Send_bytes(const byte *begin, const byte *end)
197 {
198  size_t amount = std::min<size_t>(end - begin, this->limit - this->Size());
199  this->buffer.insert(this->buffer.end(), begin, begin + amount);
200  return amount;
201 }
202 
203 /*
204  * Receiving commands
205  * Again, the next couple of functions are endian-safe
206  * see the comment before Send_bool for more info.
207  */
208 
209 
218 bool Packet::CanReadFromPacket(size_t bytes_to_read, bool close_connection)
219 {
220  /* Don't allow reading from a quit client/client who send bad data */
221  if (this->cs->HasClientQuit()) return false;
222 
223  /* Check if variable is within packet-size */
224  if (this->pos + bytes_to_read > this->Size()) {
225  if (close_connection) this->cs->NetworkSocketHandler::MarkClosed();
226  return false;
227  }
228 
229  return true;
230 }
231 
238 {
239  return this->pos >= sizeof(PacketSize);
240 }
241 
249 size_t Packet::Size() const
250 {
251  return this->buffer.size();
252 }
253 
259 {
260  assert(this->cs != nullptr && this->next == nullptr);
261  size_t size = (size_t)this->buffer[0];
262  size += (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 < sizeof(PacketSize) + sizeof(PacketType) || size > this->limit) return false;
268 
269  this->buffer.resize(size);
270  this->pos = sizeof(PacketSize);
271  return true;
272 }
273 
278 {
279  /* Put the position on the right place */
280  this->pos = sizeof(PacketSize);
281 }
282 
288 {
289  assert(this->Size() >= sizeof(PacketSize) + sizeof(PacketType));
290  return static_cast<PacketType>(buffer[sizeof(PacketSize)]);
291 }
292 
298 {
299  return this->Recv_uint8() != 0;
300 }
301 
307 {
308  uint8 n;
309 
310  if (!this->CanReadFromPacket(sizeof(n), true)) return 0;
311 
312  n = this->buffer[this->pos++];
313  return n;
314 }
315 
321 {
322  uint16 n;
323 
324  if (!this->CanReadFromPacket(sizeof(n), true)) return 0;
325 
326  n = (uint16)this->buffer[this->pos++];
327  n += (uint16)this->buffer[this->pos++] << 8;
328  return n;
329 }
330 
336 {
337  uint32 n;
338 
339  if (!this->CanReadFromPacket(sizeof(n), true)) return 0;
340 
341  n = (uint32)this->buffer[this->pos++];
342  n += (uint32)this->buffer[this->pos++] << 8;
343  n += (uint32)this->buffer[this->pos++] << 16;
344  n += (uint32)this->buffer[this->pos++] << 24;
345  return n;
346 }
347 
353 {
354  uint64 n;
355 
356  if (!this->CanReadFromPacket(sizeof(n), true)) return 0;
357 
358  n = (uint64)this->buffer[this->pos++];
359  n += (uint64)this->buffer[this->pos++] << 8;
360  n += (uint64)this->buffer[this->pos++] << 16;
361  n += (uint64)this->buffer[this->pos++] << 24;
362  n += (uint64)this->buffer[this->pos++] << 32;
363  n += (uint64)this->buffer[this->pos++] << 40;
364  n += (uint64)this->buffer[this->pos++] << 48;
365  n += (uint64)this->buffer[this->pos++] << 56;
366  return n;
367 }
368 
381 {
382  assert(length > 1);
383 
384  /* Both loops with Recv_uint8 terminate when reading past the end of the
385  * packet as Recv_uint8 then closes the connection and returns 0. */
386  std::string str;
387  char character;
388  while (--length > 0 && (character = this->Recv_uint8()) != '\0') str.push_back(character);
389 
390  if (length == 0) {
391  /* The string in the packet was longer. Read until the termination. */
392  while (this->Recv_uint8() != '\0') {}
393  }
394 
395  return StrMakeValid(str, settings);
396 }
397 
403 {
404  return this->Size() - this->pos;
405 }
Packet::PrepareToSend
void PrepareToSend()
Writes the packet size from the raw packet from packet->size.
Definition: packet.cpp:83
Packet::Size
size_t Size() const
Get the number of bytes in the packet.
Definition: packet.cpp:249
GB
static uint GB(const T x, const uint8 s, const uint8 n)
Fetch n bits from x, started at bit s.
Definition: bitmath_func.hpp:32
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:196
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:237
Packet::ParsePacketSize
bool ParsePacketSize()
Reads the packet size from the raw packet and stores it in the packet->size.
Definition: packet.cpp:258
Packet::Send_uint8
void Send_uint8(uint8 data)
Package a 8 bits integer in the packet.
Definition: packet.cpp:129
PacketType
uint8 PacketType
Identifier for the packet.
Definition: packet.h:23
Packet::Send_uint32
void Send_uint32(uint32 data)
Package a 32 bits integer in the packet.
Definition: packet.cpp:150
Packet::AddToQueue
static void AddToQueue(Packet **queue, Packet *packet)
Add the given Packet to the end of the queue of packets.
Definition: packet.cpp:59
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:218
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:380
Packet::PopFromQueue
static Packet * PopFromQueue(Packet **queue)
Pop the packet from the begin of the queue and set the begin of the queue to the second element in th...
Definition: packet.cpp:71
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::Recv_uint32
uint32 Recv_uint32()
Read a 32 bits integer from the packet.
Definition: packet.cpp:335
Packet::PrepareToRead
void PrepareToRead()
Prepares the packet so it can be read.
Definition: packet.cpp:277
Packet::Send_uint16
void Send_uint16(uint16 data)
Package a 16 bits integer in the packet.
Definition: packet.cpp:139
settings
fluid_settings_t * settings
FluidSynth settings handle.
Definition: fluidsynth.cpp:21
Packet::next
Packet * next
The next packet.
Definition: packet.h:47
Packet
Internal entity of a packet.
Definition: packet.h:44
StringValidationSettings
StringValidationSettings
Settings for the string validation.
Definition: string_type.h:48
Packet::Send_bool
void Send_bool(bool data)
Package a boolean in the packet.
Definition: packet.cpp:120
Packet::limit
size_t limit
The limit for the packet size.
Definition: packet.h:53
NetworkSocketHandler::HasClientQuit
bool HasClientQuit() const
Whether the current client connected to the socket has quit.
Definition: core.h:68
StrMakeValid
std::string StrMakeValid(const std::string &str, StringValidationSettings settings)
Scans the string for invalid characters and replaces then with a question mark '?' (if not ignored).
Definition: string.cpp:281
Packet::GetPacketType
PacketType GetPacketType() const
Get the PacketType from this packet.
Definition: packet.cpp:287
PacketSize
uint16 PacketSize
Size of the whole packet.
Definition: packet.h:22
Packet::CanWriteToPacket
bool CanWriteToPacket(size_t bytes_to_write)
Is it safe to write to the packet, i.e.
Definition: packet.cpp:99
Packet::Recv_bool
bool Recv_bool()
Read a boolean from the packet.
Definition: packet.cpp:297
Packet::Send_uint64
void Send_uint64(uint64 data)
Package a 64 bits integer in the packet.
Definition: packet.cpp:163
packet.h
Packet::cs
NetworkSocketHandler * cs
Socket we're associated with.
Definition: packet.h:56
Packet::Recv_uint8
uint8 Recv_uint8()
Read a 8 bits integer from the packet.
Definition: packet.cpp:306
Packet::Send_string
void Send_string(const std::string_view data)
Sends a string over the network.
Definition: packet.cpp:181
Packet::Recv_uint64
uint64 Recv_uint64()
Read a 64 bits integer from the packet.
Definition: packet.cpp:352
Packet::buffer
std::vector< byte > buffer
The buffer of this packet.
Definition: packet.h:51
Packet::RemainingBytesToTransfer
size_t RemainingBytesToTransfer() const
Get the amount of bytes that are still available for the Transfer functions.
Definition: packet.cpp:402
Packet::Recv_uint16
uint16 Recv_uint16()
Read a 16 bits integer from the packet.
Definition: packet.cpp:320
Packet::pos
PacketSize pos
The current read/write position in the packet.
Definition: packet.h:49