OpenTTD Source  1.11.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 
24 {
25  assert(cs != nullptr);
26 
27  this->cs = cs;
28  this->next = nullptr;
29  this->pos = 0; // We start reading from here
30  this->size = 0;
31  this->buffer = MallocT<byte>(SEND_MTU);
32 }
33 
39 {
40  this->cs = nullptr;
41  this->next = nullptr;
42 
43  /* Skip the size so we can write that in before sending the packet */
44  this->pos = 0;
45  this->size = sizeof(PacketSize);
46  this->buffer = MallocT<byte>(SEND_MTU);
47  this->buffer[this->size++] = type;
48 }
49 
54 {
55  free(this->buffer);
56 }
57 
62 {
63  assert(this->cs == nullptr && this->next == nullptr);
64 
65  this->buffer[0] = GB(this->size, 0, 8);
66  this->buffer[1] = GB(this->size, 8, 8);
67 
68  this->pos = 0; // We start reading from here
69 }
70 
71 /*
72  * The next couple of functions make sure we can send
73  * uint8, uint16, uint32 and uint64 endian-safe
74  * over the network. The least significant bytes are
75  * sent first.
76  *
77  * So 0x01234567 would be sent as 67 45 23 01.
78  *
79  * A bool is sent as a uint8 where zero means false
80  * and non-zero means true.
81  */
82 
87 void Packet::Send_bool(bool data)
88 {
89  this->Send_uint8(data ? 1 : 0);
90 }
91 
96 void Packet::Send_uint8(uint8 data)
97 {
98  assert(this->size < SEND_MTU - sizeof(data));
99  this->buffer[this->size++] = data;
100 }
101 
106 void Packet::Send_uint16(uint16 data)
107 {
108  assert(this->size < SEND_MTU - sizeof(data));
109  this->buffer[this->size++] = GB(data, 0, 8);
110  this->buffer[this->size++] = GB(data, 8, 8);
111 }
112 
117 void Packet::Send_uint32(uint32 data)
118 {
119  assert(this->size < SEND_MTU - sizeof(data));
120  this->buffer[this->size++] = GB(data, 0, 8);
121  this->buffer[this->size++] = GB(data, 8, 8);
122  this->buffer[this->size++] = GB(data, 16, 8);
123  this->buffer[this->size++] = GB(data, 24, 8);
124 }
125 
130 void Packet::Send_uint64(uint64 data)
131 {
132  assert(this->size < SEND_MTU - sizeof(data));
133  this->buffer[this->size++] = GB(data, 0, 8);
134  this->buffer[this->size++] = GB(data, 8, 8);
135  this->buffer[this->size++] = GB(data, 16, 8);
136  this->buffer[this->size++] = GB(data, 24, 8);
137  this->buffer[this->size++] = GB(data, 32, 8);
138  this->buffer[this->size++] = GB(data, 40, 8);
139  this->buffer[this->size++] = GB(data, 48, 8);
140  this->buffer[this->size++] = GB(data, 56, 8);
141 }
142 
148 void Packet::Send_string(const char *data)
149 {
150  assert(data != nullptr);
151  /* The <= *is* valid due to the fact that we are comparing sizes and not the index. */
152  assert(this->size + strlen(data) + 1 <= SEND_MTU);
153  while ((this->buffer[this->size++] = *data++) != '\0') {}
154 }
155 
156 
157 /*
158  * Receiving commands
159  * Again, the next couple of functions are endian-safe
160  * see the comment before Send_bool for more info.
161  */
162 
163 
169 bool Packet::CanReadFromPacket(uint bytes_to_read)
170 {
171  /* Don't allow reading from a quit client/client who send bad data */
172  if (this->cs->HasClientQuit()) return false;
173 
174  /* Check if variable is within packet-size */
175  if (this->pos + bytes_to_read > this->size) {
176  this->cs->NetworkSocketHandler::CloseConnection();
177  return false;
178  }
179 
180  return true;
181 }
182 
187 {
188  assert(this->cs != nullptr && this->next == nullptr);
189  this->size = (PacketSize)this->buffer[0];
190  this->size += (PacketSize)this->buffer[1] << 8;
191 }
192 
197 {
198  this->ReadRawPacketSize();
199 
200  /* Put the position on the right place */
201  this->pos = sizeof(PacketSize);
202 }
203 
209 {
210  return this->Recv_uint8() != 0;
211 }
212 
218 {
219  uint8 n;
220 
221  if (!this->CanReadFromPacket(sizeof(n))) return 0;
222 
223  n = this->buffer[this->pos++];
224  return n;
225 }
226 
232 {
233  uint16 n;
234 
235  if (!this->CanReadFromPacket(sizeof(n))) return 0;
236 
237  n = (uint16)this->buffer[this->pos++];
238  n += (uint16)this->buffer[this->pos++] << 8;
239  return n;
240 }
241 
247 {
248  uint32 n;
249 
250  if (!this->CanReadFromPacket(sizeof(n))) return 0;
251 
252  n = (uint32)this->buffer[this->pos++];
253  n += (uint32)this->buffer[this->pos++] << 8;
254  n += (uint32)this->buffer[this->pos++] << 16;
255  n += (uint32)this->buffer[this->pos++] << 24;
256  return n;
257 }
258 
264 {
265  uint64 n;
266 
267  if (!this->CanReadFromPacket(sizeof(n))) return 0;
268 
269  n = (uint64)this->buffer[this->pos++];
270  n += (uint64)this->buffer[this->pos++] << 8;
271  n += (uint64)this->buffer[this->pos++] << 16;
272  n += (uint64)this->buffer[this->pos++] << 24;
273  n += (uint64)this->buffer[this->pos++] << 32;
274  n += (uint64)this->buffer[this->pos++] << 40;
275  n += (uint64)this->buffer[this->pos++] << 48;
276  n += (uint64)this->buffer[this->pos++] << 56;
277  return n;
278 }
279 
286 void Packet::Recv_string(char *buffer, size_t size, StringValidationSettings settings)
287 {
288  PacketSize pos;
289  char *bufp = buffer;
290  const char *last = buffer + size - 1;
291 
292  /* Don't allow reading from a closed socket */
293  if (cs->HasClientQuit()) return;
294 
295  pos = this->pos;
296  while (--size > 0 && pos < this->size && (*buffer++ = this->buffer[pos++]) != '\0') {}
297 
298  if (size == 0 || pos == this->size) {
299  *buffer = '\0';
300  /* If size was sooner to zero then the string in the stream
301  * skip till the \0, so than packet can be read out correctly for the rest */
302  while (pos < this->size && this->buffer[pos] != '\0') pos++;
303  pos++;
304  }
305  this->pos = pos;
306 
307  str_validate(bufp, last, settings);
308 }
Packet::PrepareToSend
void PrepareToSend()
Writes the packet size from the raw packet from packet->size.
Definition: packet.cpp:61
Packet::Recv_string
void Recv_string(char *buffer, size_t size, StringValidationSettings settings=SVS_REPLACE_WITH_QUESTION_MARK)
Reads a string till it finds a '\0' in the stream.
Definition: packet.cpp:286
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
str_validate
void str_validate(char *str, const char *last, StringValidationSettings settings)
Scans the string for valid characters and if it finds invalid ones, replaces them with a question mar...
Definition: string.cpp:237
Packet::buffer
byte * buffer
The buffer of this packet, of basically variable length up to SEND_MTU.
Definition: packet.h:52
NetworkSocketHandler
SocketHandler for all network sockets in OpenTTD.
Definition: core.h:41
Packet::Send_uint8
void Send_uint8(uint8 data)
Package a 8 bits integer in the packet.
Definition: packet.cpp:96
PacketType
uint8 PacketType
Identifier for the packet.
Definition: packet.h:20
Packet::Send_uint32
void Send_uint32(uint32 data)
Package a 32 bits integer in the packet.
Definition: packet.cpp:117
Packet::Recv_uint32
uint32 Recv_uint32()
Read a 32 bits integer from the packet.
Definition: packet.cpp:246
Packet::Send_string
void Send_string(const char *data)
Sends a string over the network.
Definition: packet.cpp:148
Packet::PrepareToRead
void PrepareToRead()
Prepares the packet so it can be read.
Definition: packet.cpp:196
Packet::size
PacketSize size
The size of the whole packet for received packets.
Definition: packet.h:48
SEND_MTU
static const uint16 SEND_MTU
Number of bytes we can pack in a single packet.
Definition: config.h:33
Packet::Send_uint16
void Send_uint16(uint16 data)
Package a 16 bits integer in the packet.
Definition: packet.cpp:106
settings
fluid_settings_t * settings
FluidSynth settings handle.
Definition: fluidsynth.cpp:21
Packet::next
Packet * next
The next packet.
Definition: packet.h:42
Packet::CanReadFromPacket
bool CanReadFromPacket(uint bytes_to_read)
Is it safe to read from the packet, i.e.
Definition: packet.cpp:169
Packet::ReadRawPacketSize
void ReadRawPacketSize()
Reads the packet size from the raw packet and stores it in the packet->size.
Definition: packet.cpp:186
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:87
NetworkSocketHandler::HasClientQuit
bool HasClientQuit() const
Whether the current client connected to the socket has quit.
Definition: core.h:67
Packet::~Packet
~Packet()
Free the buffer of this packet.
Definition: packet.cpp:53
PacketSize
uint16 PacketSize
Size of the whole packet.
Definition: packet.h:19
Packet::Recv_bool
bool Recv_bool()
Read a boolean from the packet.
Definition: packet.cpp:208
Packet::Send_uint64
void Send_uint64(uint64 data)
Package a 64 bits integer in the packet.
Definition: packet.cpp:130
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:217
Packet::Packet
Packet(NetworkSocketHandler *cs)
Create a packet that is used to read from a network socket.
Definition: packet.cpp:23
Packet::Recv_uint64
uint64 Recv_uint64()
Read a 64 bits integer from the packet.
Definition: packet.cpp:263
free
static void free(const void *ptr)
Version of the standard free that accepts const pointers.
Definition: stdafx.h:454
Packet::Recv_uint16
uint16 Recv_uint16()
Read a 16 bits integer from the packet.
Definition: packet.cpp:231
Packet::pos
PacketSize pos
The current read/write position in the packet.
Definition: packet.h:50