OpenTTD
packet.cpp
Go to the documentation of this file.
1 /* $Id$ */
2 
3 /*
4  * This file is part of OpenTTD.
5  * 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.
6  * 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.
7  * 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/>.
8  */
9 
14 #include "../../stdafx.h"
15 #include "../../string_func.h"
16 
17 #include "packet.h"
18 
19 #include "../../safeguards.h"
20 
26 {
27  assert(cs != nullptr);
28 
29  this->cs = cs;
30  this->next = nullptr;
31  this->pos = 0; // We start reading from here
32  this->size = 0;
33  this->buffer = MallocT<byte>(SEND_MTU);
34 }
35 
41 {
42  this->cs = nullptr;
43  this->next = nullptr;
44 
45  /* Skip the size so we can write that in before sending the packet */
46  this->pos = 0;
47  this->size = sizeof(PacketSize);
48  this->buffer = MallocT<byte>(SEND_MTU);
49  this->buffer[this->size++] = type;
50 }
51 
56 {
57  free(this->buffer);
58 }
59 
64 {
65  assert(this->cs == nullptr && this->next == nullptr);
66 
67  this->buffer[0] = GB(this->size, 0, 8);
68  this->buffer[1] = GB(this->size, 8, 8);
69 
70  this->pos = 0; // We start reading from here
71 }
72 
73 /*
74  * The next couple of functions make sure we can send
75  * uint8, uint16, uint32 and uint64 endian-safe
76  * over the network. The least significant bytes are
77  * sent first.
78  *
79  * So 0x01234567 would be sent as 67 45 23 01.
80  *
81  * A bool is sent as a uint8 where zero means false
82  * and non-zero means true.
83  */
84 
89 void Packet::Send_bool(bool data)
90 {
91  this->Send_uint8(data ? 1 : 0);
92 }
93 
98 void Packet::Send_uint8(uint8 data)
99 {
100  assert(this->size < SEND_MTU - sizeof(data));
101  this->buffer[this->size++] = data;
102 }
103 
108 void Packet::Send_uint16(uint16 data)
109 {
110  assert(this->size < SEND_MTU - sizeof(data));
111  this->buffer[this->size++] = GB(data, 0, 8);
112  this->buffer[this->size++] = GB(data, 8, 8);
113 }
114 
119 void Packet::Send_uint32(uint32 data)
120 {
121  assert(this->size < SEND_MTU - sizeof(data));
122  this->buffer[this->size++] = GB(data, 0, 8);
123  this->buffer[this->size++] = GB(data, 8, 8);
124  this->buffer[this->size++] = GB(data, 16, 8);
125  this->buffer[this->size++] = GB(data, 24, 8);
126 }
127 
132 void Packet::Send_uint64(uint64 data)
133 {
134  assert(this->size < SEND_MTU - sizeof(data));
135  this->buffer[this->size++] = GB(data, 0, 8);
136  this->buffer[this->size++] = GB(data, 8, 8);
137  this->buffer[this->size++] = GB(data, 16, 8);
138  this->buffer[this->size++] = GB(data, 24, 8);
139  this->buffer[this->size++] = GB(data, 32, 8);
140  this->buffer[this->size++] = GB(data, 40, 8);
141  this->buffer[this->size++] = GB(data, 48, 8);
142  this->buffer[this->size++] = GB(data, 56, 8);
143 }
144 
150 void Packet::Send_string(const char *data)
151 {
152  assert(data != nullptr);
153  /* The <= *is* valid due to the fact that we are comparing sizes and not the index. */
154  assert(this->size + strlen(data) + 1 <= SEND_MTU);
155  while ((this->buffer[this->size++] = *data++) != '\0') {}
156 }
157 
158 
159 /*
160  * Receiving commands
161  * Again, the next couple of functions are endian-safe
162  * see the comment before Send_bool for more info.
163  */
164 
165 
171 bool Packet::CanReadFromPacket(uint bytes_to_read)
172 {
173  /* Don't allow reading from a quit client/client who send bad data */
174  if (this->cs->HasClientQuit()) return false;
175 
176  /* Check if variable is within packet-size */
177  if (this->pos + bytes_to_read > this->size) {
178  this->cs->NetworkSocketHandler::CloseConnection();
179  return false;
180  }
181 
182  return true;
183 }
184 
189 {
190  assert(this->cs != nullptr && this->next == nullptr);
191  this->size = (PacketSize)this->buffer[0];
192  this->size += (PacketSize)this->buffer[1] << 8;
193 }
194 
199 {
200  this->ReadRawPacketSize();
201 
202  /* Put the position on the right place */
203  this->pos = sizeof(PacketSize);
204 }
205 
211 {
212  return this->Recv_uint8() != 0;
213 }
214 
220 {
221  uint8 n;
222 
223  if (!this->CanReadFromPacket(sizeof(n))) return 0;
224 
225  n = this->buffer[this->pos++];
226  return n;
227 }
228 
234 {
235  uint16 n;
236 
237  if (!this->CanReadFromPacket(sizeof(n))) return 0;
238 
239  n = (uint16)this->buffer[this->pos++];
240  n += (uint16)this->buffer[this->pos++] << 8;
241  return n;
242 }
243 
249 {
250  uint32 n;
251 
252  if (!this->CanReadFromPacket(sizeof(n))) return 0;
253 
254  n = (uint32)this->buffer[this->pos++];
255  n += (uint32)this->buffer[this->pos++] << 8;
256  n += (uint32)this->buffer[this->pos++] << 16;
257  n += (uint32)this->buffer[this->pos++] << 24;
258  return n;
259 }
260 
266 {
267  uint64 n;
268 
269  if (!this->CanReadFromPacket(sizeof(n))) return 0;
270 
271  n = (uint64)this->buffer[this->pos++];
272  n += (uint64)this->buffer[this->pos++] << 8;
273  n += (uint64)this->buffer[this->pos++] << 16;
274  n += (uint64)this->buffer[this->pos++] << 24;
275  n += (uint64)this->buffer[this->pos++] << 32;
276  n += (uint64)this->buffer[this->pos++] << 40;
277  n += (uint64)this->buffer[this->pos++] << 48;
278  n += (uint64)this->buffer[this->pos++] << 56;
279  return n;
280 }
281 
289 {
290  PacketSize pos;
291  char *bufp = buffer;
292  const char *last = buffer + size - 1;
293 
294  /* Don't allow reading from a closed socket */
295  if (cs->HasClientQuit()) return;
296 
297  pos = this->pos;
298  while (--size > 0 && pos < this->size && (*buffer++ = this->buffer[pos++]) != '\0') {}
299 
300  if (size == 0 || pos == this->size) {
301  *buffer = '\0';
302  /* If size was sooner to zero then the string in the stream
303  * skip till the \0, so than packet can be read out correctly for the rest */
304  while (pos < this->size && this->buffer[pos] != '\0') pos++;
305  pos++;
306  }
307  this->pos = pos;
308 
309  str_validate(bufp, last, settings);
310 }
bool HasClientQuit() const
Whether the current client connected to the socket has quit.
Definition: core.h:69
uint32 Recv_uint32()
Read a 32 bits integer from the packet.
Definition: packet.cpp:248
PacketSize pos
The current read/write position in the packet.
Definition: packet.h:52
void PrepareToSend()
Writes the packet size from the raw packet from packet->size.
Definition: packet.cpp:63
void Send_string(const char *data)
Sends a string over the network.
Definition: packet.cpp:150
uint8 PacketType
Identifier for the packet.
Definition: packet.h:22
fluid_settings_t * settings
FluidSynth settings handle.
Definition: fluidsynth.cpp:22
void Send_uint8(uint8 data)
Package a 8 bits integer in the packet.
Definition: packet.cpp:98
void Send_uint32(uint32 data)
Package a 32 bits integer in the packet.
Definition: packet.cpp:119
bool CanReadFromPacket(uint bytes_to_read)
Is it safe to read from the packet, i.e.
Definition: packet.cpp:171
StringValidationSettings
Settings for the string validation.
Definition: string_type.h:50
void PrepareToRead()
Prepares the packet so it can be read.
Definition: packet.cpp:198
void Send_uint64(uint64 data)
Package a 64 bits integer in the packet.
Definition: packet.cpp:132
byte * buffer
The buffer of this packet, of basically variable length up to SEND_MTU.
Definition: packet.h:54
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:196
void Send_uint16(uint16 data)
Package a 16 bits integer in the packet.
Definition: packet.cpp:108
~Packet()
Free the buffer of this packet.
Definition: packet.cpp:55
PacketSize size
The size of the whole packet for received packets.
Definition: packet.h:50
bool Recv_bool()
Read a boolean from the packet.
Definition: packet.cpp:210
Packet * next
The next packet.
Definition: packet.h:44
NetworkSocketHandler * cs
Socket we&#39;re associated with.
Definition: packet.h:58
Packet(NetworkSocketHandler *cs)
Create a packet that is used to read from a network socket.
Definition: packet.cpp:25
uint8 Recv_uint8()
Read a 8 bits integer from the packet.
Definition: packet.cpp:219
uint64 Recv_uint64()
Read a 64 bits integer from the packet.
Definition: packet.cpp:265
static uint GB(const T x, const uint8 s, const uint8 n)
Fetch n bits from x, started at bit s.
static const uint16 SEND_MTU
Number of bytes we can pack in a single packet.
Definition: config.h:35
Basic functions to create, fill and read packets.
static void free(const void *ptr)
Version of the standard free that accepts const pointers.
Definition: depend.cpp:131
void ReadRawPacketSize()
Reads the packet size from the raw packet and stores it in the packet->size.
Definition: packet.cpp:188
uint16 Recv_uint16()
Read a 16 bits integer from the packet.
Definition: packet.cpp:233
void Send_bool(bool data)
Package a boolean in the packet.
Definition: packet.cpp:89
uint16 PacketSize
Size of the whole packet.
Definition: packet.h:21
SocketHandler for all network sockets in OpenTTD.
Definition: core.h:43
void Recv_string(char *buffer, size_t size, StringValidationSettings settings=SVS_REPLACE_WITH_QUESTION_MARK)
Reads a string till it finds a &#39;\0&#39; in the stream.
Definition: packet.cpp:288