OpenTTD
packet.cpp
Go to the documentation of this file.
1 /* $Id: packet.cpp 26482 2014-04-23 20:13:33Z rubidium $ */
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 #ifdef ENABLE_NETWORK
15 
16 #include "../../stdafx.h"
17 #include "../../string_func.h"
18 
19 #include "packet.h"
20 
21 #include "../../safeguards.h"
22 
28 {
29  assert(cs != NULL);
30 
31  this->cs = cs;
32  this->next = NULL;
33  this->pos = 0; // We start reading from here
34  this->size = 0;
35  this->buffer = MallocT<byte>(SEND_MTU);
36 }
37 
43 {
44  this->cs = NULL;
45  this->next = NULL;
46 
47  /* Skip the size so we can write that in before sending the packet */
48  this->pos = 0;
49  this->size = sizeof(PacketSize);
50  this->buffer = MallocT<byte>(SEND_MTU);
51  this->buffer[this->size++] = type;
52 }
53 
58 {
59  free(this->buffer);
60 }
61 
66 {
67  assert(this->cs == NULL && this->next == NULL);
68 
69  this->buffer[0] = GB(this->size, 0, 8);
70  this->buffer[1] = GB(this->size, 8, 8);
71 
72  this->pos = 0; // We start reading from here
73 }
74 
75 /*
76  * The next couple of functions make sure we can send
77  * uint8, uint16, uint32 and uint64 endian-safe
78  * over the network. The least significant bytes are
79  * sent first.
80  *
81  * So 0x01234567 would be sent as 67 45 23 01.
82  *
83  * A bool is sent as a uint8 where zero means false
84  * and non-zero means true.
85  */
86 
91 void Packet::Send_bool(bool data)
92 {
93  this->Send_uint8(data ? 1 : 0);
94 }
95 
100 void Packet::Send_uint8(uint8 data)
101 {
102  assert(this->size < SEND_MTU - sizeof(data));
103  this->buffer[this->size++] = data;
104 }
105 
110 void Packet::Send_uint16(uint16 data)
111 {
112  assert(this->size < SEND_MTU - sizeof(data));
113  this->buffer[this->size++] = GB(data, 0, 8);
114  this->buffer[this->size++] = GB(data, 8, 8);
115 }
116 
121 void Packet::Send_uint32(uint32 data)
122 {
123  assert(this->size < SEND_MTU - sizeof(data));
124  this->buffer[this->size++] = GB(data, 0, 8);
125  this->buffer[this->size++] = GB(data, 8, 8);
126  this->buffer[this->size++] = GB(data, 16, 8);
127  this->buffer[this->size++] = GB(data, 24, 8);
128 }
129 
134 void Packet::Send_uint64(uint64 data)
135 {
136  assert(this->size < SEND_MTU - sizeof(data));
137  this->buffer[this->size++] = GB(data, 0, 8);
138  this->buffer[this->size++] = GB(data, 8, 8);
139  this->buffer[this->size++] = GB(data, 16, 8);
140  this->buffer[this->size++] = GB(data, 24, 8);
141  this->buffer[this->size++] = GB(data, 32, 8);
142  this->buffer[this->size++] = GB(data, 40, 8);
143  this->buffer[this->size++] = GB(data, 48, 8);
144  this->buffer[this->size++] = GB(data, 56, 8);
145 }
146 
152 void Packet::Send_string(const char *data)
153 {
154  assert(data != NULL);
155  /* The <= *is* valid due to the fact that we are comparing sizes and not the index. */
156  assert(this->size + strlen(data) + 1 <= SEND_MTU);
157  while ((this->buffer[this->size++] = *data++) != '\0') {}
158 }
159 
160 
161 /*
162  * Receiving commands
163  * Again, the next couple of functions are endian-safe
164  * see the comment before Send_bool for more info.
165  */
166 
167 
173 bool Packet::CanReadFromPacket(uint bytes_to_read)
174 {
175  /* Don't allow reading from a quit client/client who send bad data */
176  if (this->cs->HasClientQuit()) return false;
177 
178  /* Check if variable is within packet-size */
179  if (this->pos + bytes_to_read > this->size) {
180  this->cs->NetworkSocketHandler::CloseConnection();
181  return false;
182  }
183 
184  return true;
185 }
186 
191 {
192  assert(this->cs != NULL && this->next == NULL);
193  this->size = (PacketSize)this->buffer[0];
194  this->size += (PacketSize)this->buffer[1] << 8;
195 }
196 
201 {
202  this->ReadRawPacketSize();
203 
204  /* Put the position on the right place */
205  this->pos = sizeof(PacketSize);
206 }
207 
213 {
214  return this->Recv_uint8() != 0;
215 }
216 
222 {
223  uint8 n;
224 
225  if (!this->CanReadFromPacket(sizeof(n))) return 0;
226 
227  n = this->buffer[this->pos++];
228  return n;
229 }
230 
236 {
237  uint16 n;
238 
239  if (!this->CanReadFromPacket(sizeof(n))) return 0;
240 
241  n = (uint16)this->buffer[this->pos++];
242  n += (uint16)this->buffer[this->pos++] << 8;
243  return n;
244 }
245 
251 {
252  uint32 n;
253 
254  if (!this->CanReadFromPacket(sizeof(n))) return 0;
255 
256  n = (uint32)this->buffer[this->pos++];
257  n += (uint32)this->buffer[this->pos++] << 8;
258  n += (uint32)this->buffer[this->pos++] << 16;
259  n += (uint32)this->buffer[this->pos++] << 24;
260  return n;
261 }
262 
268 {
269  uint64 n;
270 
271  if (!this->CanReadFromPacket(sizeof(n))) return 0;
272 
273  n = (uint64)this->buffer[this->pos++];
274  n += (uint64)this->buffer[this->pos++] << 8;
275  n += (uint64)this->buffer[this->pos++] << 16;
276  n += (uint64)this->buffer[this->pos++] << 24;
277  n += (uint64)this->buffer[this->pos++] << 32;
278  n += (uint64)this->buffer[this->pos++] << 40;
279  n += (uint64)this->buffer[this->pos++] << 48;
280  n += (uint64)this->buffer[this->pos++] << 56;
281  return n;
282 }
283 
291 {
292  PacketSize pos;
293  char *bufp = buffer;
294  const char *last = buffer + size - 1;
295 
296  /* Don't allow reading from a closed socket */
297  if (cs->HasClientQuit()) return;
298 
299  pos = this->pos;
300  while (--size > 0 && pos < this->size && (*buffer++ = this->buffer[pos++]) != '\0') {}
301 
302  if (size == 0 || pos == this->size) {
303  *buffer = '\0';
304  /* If size was sooner to zero then the string in the stream
305  * skip till the \0, so than packet can be read out correctly for the rest */
306  while (pos < this->size && this->buffer[pos] != '\0') pos++;
307  pos++;
308  }
309  this->pos = pos;
310 
311  str_validate(bufp, last, settings);
312 }
313 
314 #endif /* ENABLE_NETWORK */
bool HasClientQuit() const
Whether the current client connected to the socket has quit.
Definition: core.h:71
uint32 Recv_uint32()
Read a 32 bits integer from the packet.
Definition: packet.cpp:250
PacketSize pos
The current read/write position in the packet.
Definition: packet.h:54
void PrepareToSend()
Writes the packet size from the raw packet from packet->size.
Definition: packet.cpp:65
void Send_string(const char *data)
Sends a string over the network.
Definition: packet.cpp:152
uint8 PacketType
Identifier for the packet.
Definition: packet.h:24
void Send_uint8(uint8 data)
Package a 8 bits integer in the packet.
Definition: packet.cpp:100
void Send_uint32(uint32 data)
Package a 32 bits integer in the packet.
Definition: packet.cpp:121
bool CanReadFromPacket(uint bytes_to_read)
Is it safe to read from the packet, i.e.
Definition: packet.cpp:173
StringValidationSettings
Settings for the string validation.
Definition: string_type.h:48
void PrepareToRead()
Prepares the packet so it can be read.
Definition: packet.cpp:200
void Send_uint64(uint64 data)
Package a 64 bits integer in the packet.
Definition: packet.cpp:134
byte * buffer
The buffer of this packet, of basically variable length up to SEND_MTU.
Definition: packet.h:56
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:184
void Send_uint16(uint16 data)
Package a 16 bits integer in the packet.
Definition: packet.cpp:110
~Packet()
Free the buffer of this packet.
Definition: packet.cpp:57
PacketSize size
The size of the whole packet for received packets.
Definition: packet.h:52
bool Recv_bool()
Read a boolean from the packet.
Definition: packet.cpp:212
Packet * next
The next packet.
Definition: packet.h:46
NetworkSocketHandler * cs
Socket we&#39;re associated with.
Definition: packet.h:60
Packet(NetworkSocketHandler *cs)
Create a packet that is used to read from a network socket.
Definition: packet.cpp:27
uint8 Recv_uint8()
Read a 8 bits integer from the packet.
Definition: packet.cpp:221
uint64 Recv_uint64()
Read a 64 bits integer from the packet.
Definition: packet.cpp:267
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:114
void ReadRawPacketSize()
Reads the packet size from the raw packet and stores it in the packet->size.
Definition: packet.cpp:190
uint16 Recv_uint16()
Read a 16 bits integer from the packet.
Definition: packet.cpp:235
void Send_bool(bool data)
Package a boolean in the packet.
Definition: packet.cpp:91
uint16 PacketSize
Size of the whole packet.
Definition: packet.h:23
SocketHandler for all network sockets in OpenTTD.
Definition: core.h:45
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:290