Fix compiler warnings.
[openttd-joker.git] / src / network / core / packet.cpp
blobb3ebd422e221e87dc273ceab33d9ee80d4fbf785
1 /* $Id$ */
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 */
10 /**
11 * @file packet.cpp Basic functions to create, fill and read packets.
14 #ifdef ENABLE_NETWORK
16 #include "../../stdafx.h"
17 #include "../../string_func.h"
18 #include "../../command_type.h"
20 #include "packet.h"
22 #include "../../safeguards.h"
24 /**
25 * Create a packet that is used to read from a network socket
26 * @param cs the socket handler associated with the socket we are reading from
28 Packet::Packet(NetworkSocketHandler *cs)
30 assert(cs != NULL);
32 this->cs = cs;
33 this->next = NULL;
34 this->pos = 0; // We start reading from here
35 this->size = 0;
36 this->buffer = MallocT<byte>(SHRT_MAX);
39 /**
40 * Creates a packet to send
41 * @param type of the packet to send
43 Packet::Packet(PacketType type)
45 this->cs = NULL;
46 this->next = NULL;
48 /* Skip the size so we can write that in before sending the packet */
49 this->pos = 0;
50 this->size = sizeof(PacketSize);
51 this->buffer = MallocT<byte>(SHRT_MAX);
52 this->buffer[this->size++] = type;
55 /**
56 * Free the buffer of this packet.
58 Packet::~Packet()
60 free(this->buffer);
63 /**
64 * Writes the packet size from the raw packet from packet->size
66 void Packet::PrepareToSend()
68 assert(this->cs == NULL && this->next == NULL);
70 this->buffer[0] = GB(this->size, 0, 8);
71 this->buffer[1] = GB(this->size, 8, 8);
73 this->pos = 0; // We start reading from here
77 * The next couple of functions make sure we can send
78 * uint8, uint16, uint32 and uint64 endian-safe
79 * over the network. The least significant bytes are
80 * sent first.
82 * So 0x01234567 would be sent as 67 45 23 01.
84 * A bool is sent as a uint8 where zero means false
85 * and non-zero means true.
88 /**
89 * Package a boolean in the packet.
90 * @param data The data to send.
92 void Packet::Send_bool(bool data)
94 this->Send_uint8(data ? 1 : 0);
97 /**
98 * Package a 8 bits integer in the packet.
99 * @param data The data to send.
101 void Packet::Send_uint8(uint8 data)
103 assert(this->size < SHRT_MAX - sizeof(data));
104 this->buffer[this->size++] = data;
108 * Package a 16 bits integer in the packet.
109 * @param data The data to send.
111 void Packet::Send_uint16(uint16 data)
113 assert(this->size < SHRT_MAX - sizeof(data));
114 this->buffer[this->size++] = GB(data, 0, 8);
115 this->buffer[this->size++] = GB(data, 8, 8);
119 * Package a 32 bits integer in the packet.
120 * @param data The data to send.
122 void Packet::Send_uint32(uint32 data)
124 assert(this->size < SHRT_MAX - sizeof(data));
125 this->buffer[this->size++] = GB(data, 0, 8);
126 this->buffer[this->size++] = GB(data, 8, 8);
127 this->buffer[this->size++] = GB(data, 16, 8);
128 this->buffer[this->size++] = GB(data, 24, 8);
132 * Package a 64 bits integer in the packet.
133 * @param data The data to send.
135 void Packet::Send_uint64(uint64 data)
137 assert(this->size < SHRT_MAX - sizeof(data));
138 this->buffer[this->size++] = GB(data, 0, 8);
139 this->buffer[this->size++] = GB(data, 8, 8);
140 this->buffer[this->size++] = GB(data, 16, 8);
141 this->buffer[this->size++] = GB(data, 24, 8);
142 this->buffer[this->size++] = GB(data, 32, 8);
143 this->buffer[this->size++] = GB(data, 40, 8);
144 this->buffer[this->size++] = GB(data, 48, 8);
145 this->buffer[this->size++] = GB(data, 56, 8);
149 * Sends a string over the network. It sends out
150 * the string + '\0'. No size-byte or something.
151 * @param data The string to send
153 void Packet::Send_string(const char *data)
155 assert(data != NULL);
156 /* The <= *is* valid due to the fact that we are comparing sizes and not the index. */
157 assert(this->size + strlen(data) + 1 <= SHRT_MAX);
158 while ((this->buffer[this->size++] = *data++) != '\0') {}
162 * Sends a binary data over the network.
163 * @param data The data to send
165 void Packet::Send_binary(const char *data, const size_t size)
167 assert(data != NULL);
168 assert(size < MAX_CMD_TEXT_LENGTH);
169 memcpy(&this->buffer[this->size], data, size);
170 this->size += (PacketSize) size;
175 * Receiving commands
176 * Again, the next couple of functions are endian-safe
177 * see the comment before Send_bool for more info.
182 * Is it safe to read from the packet, i.e. didn't we run over the buffer ?
183 * @param bytes_to_read The amount of bytes we want to try to read.
184 * @return True if that is safe, otherwise false.
186 bool Packet::CanReadFromPacket(uint bytes_to_read)
188 /* Don't allow reading from a quit client/client who send bad data */
189 if (this->cs->HasClientQuit()) return false;
191 /* Check if variable is within packet-size */
192 if (this->pos + bytes_to_read > this->size) {
193 this->cs->NetworkSocketHandler::CloseConnection();
194 return false;
197 return true;
201 * Reads the packet size from the raw packet and stores it in the packet->size
203 void Packet::ReadRawPacketSize()
205 assert(this->cs != NULL && this->next == NULL);
206 this->size = (PacketSize)this->buffer[0];
207 this->size += (PacketSize)this->buffer[1] << 8;
211 * Prepares the packet so it can be read
213 void Packet::PrepareToRead()
215 this->ReadRawPacketSize();
217 /* Put the position on the right place */
218 this->pos = sizeof(PacketSize);
222 * Read a boolean from the packet.
223 * @return The read data.
225 bool Packet::Recv_bool()
227 return this->Recv_uint8() != 0;
231 * Read a 8 bits integer from the packet.
232 * @return The read data.
234 uint8 Packet::Recv_uint8()
236 uint8 n;
238 if (!this->CanReadFromPacket(sizeof(n))) return 0;
240 n = this->buffer[this->pos++];
241 return n;
245 * Read a 16 bits integer from the packet.
246 * @return The read data.
248 uint16 Packet::Recv_uint16()
250 uint16 n;
252 if (!this->CanReadFromPacket(sizeof(n))) return 0;
254 n = (uint16)this->buffer[this->pos++];
255 n += (uint16)this->buffer[this->pos++] << 8;
256 return n;
260 * Read a 32 bits integer from the packet.
261 * @return The read data.
263 uint32 Packet::Recv_uint32()
265 uint32 n;
267 if (!this->CanReadFromPacket(sizeof(n))) return 0;
269 n = (uint32)this->buffer[this->pos++];
270 n += (uint32)this->buffer[this->pos++] << 8;
271 n += (uint32)this->buffer[this->pos++] << 16;
272 n += (uint32)this->buffer[this->pos++] << 24;
273 return n;
277 * Read a 64 bits integer from the packet.
278 * @return The read data.
280 uint64 Packet::Recv_uint64()
282 uint64 n;
284 if (!this->CanReadFromPacket(sizeof(n))) return 0;
286 n = (uint64)this->buffer[this->pos++];
287 n += (uint64)this->buffer[this->pos++] << 8;
288 n += (uint64)this->buffer[this->pos++] << 16;
289 n += (uint64)this->buffer[this->pos++] << 24;
290 n += (uint64)this->buffer[this->pos++] << 32;
291 n += (uint64)this->buffer[this->pos++] << 40;
292 n += (uint64)this->buffer[this->pos++] << 48;
293 n += (uint64)this->buffer[this->pos++] << 56;
294 return n;
298 * Reads a string till it finds a '\0' in the stream.
299 * @param buffer The buffer to put the data into.
300 * @param size The size of the buffer.
301 * @param settings The string validation settings.
303 void Packet::Recv_string(char *buffer, size_t size, StringValidationSettings settings)
305 PacketSize pos;
306 char *bufp = buffer;
307 const char *last = buffer + size - 1;
309 /* Don't allow reading from a closed socket */
310 if (cs->HasClientQuit()) return;
312 pos = this->pos;
313 while (--size > 0 && pos < this->size && (*buffer++ = this->buffer[pos++]) != '\0') {}
315 if (size == 0 || pos == this->size) {
316 *buffer = '\0';
317 /* If size was sooner to zero then the string in the stream
318 * skip till the \0, so than packet can be read out correctly for the rest */
319 while (pos < this->size && this->buffer[pos] != '\0') pos++;
320 pos++;
322 this->pos = pos;
324 str_validate(bufp, last, settings);
328 * Reads binary data.
329 * @param buffer The buffer to put the data into.
330 * @param size The size of the buffer.
332 void Packet::Recv_binary(char *buffer, size_t size)
334 /* Don't allow reading from a closed socket */
335 if (cs->HasClientQuit()) return;
337 memcpy(buffer, &this->buffer[this->pos], size);
338 this->pos += (PacketSize) size;
341 #endif /* ENABLE_NETWORK */