Fix: Data races on cursor state in OpenGL backends
[openttd-github.git] / src / network / core / packet.cpp
blob94ffcc5584e5ad683e9c9eb8fcaa683c6ade4935
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 */
8 /**
9 * @file packet.cpp Basic functions to create, fill and read packets.
12 #include "../../stdafx.h"
13 #include "../../string_func.h"
15 #include "packet.h"
17 #include "../../safeguards.h"
19 /**
20 * Create a packet that is used to read from a network socket
21 * @param cs the socket handler associated with the socket we are reading from
23 Packet::Packet(NetworkSocketHandler *cs)
25 assert(cs != nullptr);
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);
34 /**
35 * Creates a packet to send
36 * @param type of the packet to send
38 Packet::Packet(PacketType type)
40 this->cs = nullptr;
41 this->next = nullptr;
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;
50 /**
51 * Free the buffer of this packet.
53 Packet::~Packet()
55 free(this->buffer);
58 /**
59 * Writes the packet size from the raw packet from packet->size
61 void Packet::PrepareToSend()
63 assert(this->cs == nullptr && this->next == nullptr);
65 this->buffer[0] = GB(this->size, 0, 8);
66 this->buffer[1] = GB(this->size, 8, 8);
68 this->pos = 0; // We start reading from here
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.
77 * So 0x01234567 would be sent as 67 45 23 01.
79 * A bool is sent as a uint8 where zero means false
80 * and non-zero means true.
83 /**
84 * Package a boolean in the packet.
85 * @param data The data to send.
87 void Packet::Send_bool(bool data)
89 this->Send_uint8(data ? 1 : 0);
92 /**
93 * Package a 8 bits integer in the packet.
94 * @param data The data to send.
96 void Packet::Send_uint8(uint8 data)
98 assert(this->size < SEND_MTU - sizeof(data));
99 this->buffer[this->size++] = data;
103 * Package a 16 bits integer in the packet.
104 * @param data The data to send.
106 void Packet::Send_uint16(uint16 data)
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);
114 * Package a 32 bits integer in the packet.
115 * @param data The data to send.
117 void Packet::Send_uint32(uint32 data)
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);
127 * Package a 64 bits integer in the packet.
128 * @param data The data to send.
130 void Packet::Send_uint64(uint64 data)
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);
144 * Sends a string over the network. It sends out
145 * the string + '\0'. No size-byte or something.
146 * @param data The string to send
148 void Packet::Send_string(const char *data)
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') {}
158 * Receiving commands
159 * Again, the next couple of functions are endian-safe
160 * see the comment before Send_bool for more info.
165 * Is it safe to read from the packet, i.e. didn't we run over the buffer ?
166 * @param bytes_to_read The amount of bytes we want to try to read.
167 * @return True if that is safe, otherwise false.
169 bool Packet::CanReadFromPacket(uint bytes_to_read)
171 /* Don't allow reading from a quit client/client who send bad data */
172 if (this->cs->HasClientQuit()) return false;
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;
180 return true;
184 * Reads the packet size from the raw packet and stores it in the packet->size
186 void Packet::ReadRawPacketSize()
188 assert(this->cs != nullptr && this->next == nullptr);
189 this->size = (PacketSize)this->buffer[0];
190 this->size += (PacketSize)this->buffer[1] << 8;
194 * Prepares the packet so it can be read
196 void Packet::PrepareToRead()
198 this->ReadRawPacketSize();
200 /* Put the position on the right place */
201 this->pos = sizeof(PacketSize);
205 * Read a boolean from the packet.
206 * @return The read data.
208 bool Packet::Recv_bool()
210 return this->Recv_uint8() != 0;
214 * Read a 8 bits integer from the packet.
215 * @return The read data.
217 uint8 Packet::Recv_uint8()
219 uint8 n;
221 if (!this->CanReadFromPacket(sizeof(n))) return 0;
223 n = this->buffer[this->pos++];
224 return n;
228 * Read a 16 bits integer from the packet.
229 * @return The read data.
231 uint16 Packet::Recv_uint16()
233 uint16 n;
235 if (!this->CanReadFromPacket(sizeof(n))) return 0;
237 n = (uint16)this->buffer[this->pos++];
238 n += (uint16)this->buffer[this->pos++] << 8;
239 return n;
243 * Read a 32 bits integer from the packet.
244 * @return The read data.
246 uint32 Packet::Recv_uint32()
248 uint32 n;
250 if (!this->CanReadFromPacket(sizeof(n))) return 0;
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;
260 * Read a 64 bits integer from the packet.
261 * @return The read data.
263 uint64 Packet::Recv_uint64()
265 uint64 n;
267 if (!this->CanReadFromPacket(sizeof(n))) return 0;
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;
281 * Reads a string till it finds a '\0' in the stream.
282 * @param buffer The buffer to put the data into.
283 * @param size The size of the buffer.
284 * @param settings The string validation settings.
286 void Packet::Recv_string(char *buffer, size_t size, StringValidationSettings settings)
288 PacketSize pos;
289 char *bufp = buffer;
290 const char *last = buffer + size - 1;
292 /* Don't allow reading from a closed socket */
293 if (cs->HasClientQuit()) return;
295 pos = this->pos;
296 while (--size > 0 && pos < this->size && (*buffer++ = this->buffer[pos++]) != '\0') {}
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++;
305 this->pos = pos;
307 str_validate(bufp, last, settings);