1 //
2 // Copyright(C) 2005-2014 Simon Howard
3 //
4 // This program is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU General Public License
6 // as published by the Free Software Foundation; either version 2
7 // of the License, or (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
13 //
14 // DESCRIPTION:
15 // Network packet manipulation (net_packet_t)
16 //
17
18 #include <ctype.h>
19 #include <string.h>
20 #include "m_misc.h"
21 #include "net_packet.h"
22 #include "z_zone.h"
23
24 static int total_packet_memory = 0;
25
NET_NewPacket(int initial_size)26 net_packet_t *NET_NewPacket(int initial_size)
27 {
28 net_packet_t *packet;
29
30 packet = (net_packet_t *) Z_Malloc(sizeof(net_packet_t), PU_STATIC, 0);
31
32 if (initial_size == 0)
33 initial_size = 256;
34
35 packet->alloced = initial_size;
36 packet->data = Z_Malloc(initial_size, PU_STATIC, 0);
37 packet->len = 0;
38 packet->pos = 0;
39
40 total_packet_memory += sizeof(net_packet_t) + initial_size;
41
42 //printf("total packet memory: %i bytes\n", total_packet_memory);
43 //printf("%p: allocated\n", packet);
44
45 return packet;
46 }
47
48 // duplicates an existing packet
49
NET_PacketDup(net_packet_t * packet)50 net_packet_t *NET_PacketDup(net_packet_t *packet)
51 {
52 net_packet_t *newpacket;
53
54 newpacket = NET_NewPacket(packet->len);
55 memcpy(newpacket->data, packet->data, packet->len);
56 newpacket->len = packet->len;
57
58 return newpacket;
59 }
60
NET_FreePacket(net_packet_t * packet)61 void NET_FreePacket(net_packet_t *packet)
62 {
63 //printf("%p: destroyed\n", packet);
64
65 total_packet_memory -= sizeof(net_packet_t) + packet->alloced;
66 Z_Free(packet->data);
67 Z_Free(packet);
68 }
69
70 // Read a byte from the packet, returning true if read
71 // successfully
72
NET_ReadInt8(net_packet_t * packet,unsigned int * data)73 boolean NET_ReadInt8(net_packet_t *packet, unsigned int *data)
74 {
75 if (packet->pos + 1 > packet->len)
76 return false;
77
78 *data = packet->data[packet->pos];
79
80 packet->pos += 1;
81
82 return true;
83 }
84
85 // Read a 16-bit integer from the packet, returning true if read
86 // successfully
87
NET_ReadInt16(net_packet_t * packet,unsigned int * data)88 boolean NET_ReadInt16(net_packet_t *packet, unsigned int *data)
89 {
90 byte *p;
91
92 if (packet->pos + 2 > packet->len)
93 return false;
94
95 p = packet->data + packet->pos;
96
97 *data = (p[0] << 8) | p[1];
98 packet->pos += 2;
99
100 return true;
101 }
102
103 // Read a 32-bit integer from the packet, returning true if read
104 // successfully
105
NET_ReadInt32(net_packet_t * packet,unsigned int * data)106 boolean NET_ReadInt32(net_packet_t *packet, unsigned int *data)
107 {
108 byte *p;
109
110 if (packet->pos + 4 > packet->len)
111 return false;
112
113 p = packet->data + packet->pos;
114
115 *data = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
116 packet->pos += 4;
117
118 return true;
119 }
120
121 // Signed read functions
122
NET_ReadSInt8(net_packet_t * packet,signed int * data)123 boolean NET_ReadSInt8(net_packet_t *packet, signed int *data)
124 {
125 if (NET_ReadInt8(packet,(unsigned int *) data))
126 {
127 if (*data & (1 << 7))
128 {
129 *data &= ~(1 << 7);
130 *data -= (1 << 7);
131 }
132 return true;
133 }
134 else
135 {
136 return false;
137 }
138 }
139
NET_ReadSInt16(net_packet_t * packet,signed int * data)140 boolean NET_ReadSInt16(net_packet_t *packet, signed int *data)
141 {
142 if (NET_ReadInt16(packet, (unsigned int *) data))
143 {
144 if (*data & (1 << 15))
145 {
146 *data &= ~(1 << 15);
147 *data -= (1 << 15);
148 }
149 return true;
150 }
151 else
152 {
153 return false;
154 }
155 }
156
NET_ReadSInt32(net_packet_t * packet,signed int * data)157 boolean NET_ReadSInt32(net_packet_t *packet, signed int *data)
158 {
159 if (NET_ReadInt32(packet, (unsigned int *) data))
160 {
161 if (*data & (1U << 31))
162 {
163 *data &= ~(1U << 31);
164 *data -= (1U << 31);
165 }
166 return true;
167 }
168 else
169 {
170 return false;
171 }
172 }
173
174 // Read a string from the packet. Returns NULL if a terminating
175 // NUL character was not found before the end of the packet.
176
NET_ReadString(net_packet_t * packet)177 char *NET_ReadString(net_packet_t *packet)
178 {
179 char *start;
180
181 start = (char *) packet->data + packet->pos;
182
183 // Search forward for a NUL character
184
185 while (packet->pos < packet->len && packet->data[packet->pos] != '\0')
186 {
187 ++packet->pos;
188 }
189
190 if (packet->pos >= packet->len)
191 {
192 // Reached the end of the packet
193
194 return NULL;
195 }
196
197 // packet->data[packet->pos] == '\0': We have reached a terminating
198 // NULL. Skip past this NULL and continue reading immediately
199 // after it.
200
201 ++packet->pos;
202
203 return start;
204 }
205
206 // Read a string from the packet, but (potentially) modify it to strip
207 // out any unprintable characters which could be malicious control codes.
208 // Note that this may modify the original packet contents.
NET_ReadSafeString(net_packet_t * packet)209 char *NET_ReadSafeString(net_packet_t *packet)
210 {
211 char *r, *w, *result;
212
213 result = NET_ReadString(packet);
214 if (result == NULL)
215 {
216 return NULL;
217 }
218
219 // w is always <= r, so we never produce a longer string than the original.
220 w = result;
221 for (r = result; *r != '\0'; ++r)
222 {
223 // TODO: This is a very naive way of producing a safe string; only
224 // ASCII characters are allowed. Probably this should really support
225 // UTF-8 characters as well.
226 if (isprint(*r) || *r == '\n')
227 {
228 *w = *r;
229 ++w;
230 }
231 }
232 *w = '\0';
233
234 return result;
235 }
236
237 // Dynamically increases the size of a packet
238
NET_IncreasePacket(net_packet_t * packet)239 static void NET_IncreasePacket(net_packet_t *packet)
240 {
241 byte *newdata;
242
243 total_packet_memory -= packet->alloced;
244
245 packet->alloced *= 2;
246
247 newdata = Z_Malloc(packet->alloced, PU_STATIC, 0);
248
249 memcpy(newdata, packet->data, packet->len);
250
251 Z_Free(packet->data);
252 packet->data = newdata;
253
254 total_packet_memory += packet->alloced;
255 }
256
257 // Write a single byte to the packet
258
NET_WriteInt8(net_packet_t * packet,unsigned int i)259 void NET_WriteInt8(net_packet_t *packet, unsigned int i)
260 {
261 if (packet->len + 1 > packet->alloced)
262 NET_IncreasePacket(packet);
263
264 packet->data[packet->len] = i;
265 packet->len += 1;
266 }
267
268 // Write a 16-bit integer to the packet
269
NET_WriteInt16(net_packet_t * packet,unsigned int i)270 void NET_WriteInt16(net_packet_t *packet, unsigned int i)
271 {
272 byte *p;
273
274 if (packet->len + 2 > packet->alloced)
275 NET_IncreasePacket(packet);
276
277 p = packet->data + packet->len;
278
279 p[0] = (i >> 8) & 0xff;
280 p[1] = i & 0xff;
281
282 packet->len += 2;
283 }
284
285
286 // Write a single byte to the packet
287
NET_WriteInt32(net_packet_t * packet,unsigned int i)288 void NET_WriteInt32(net_packet_t *packet, unsigned int i)
289 {
290 byte *p;
291
292 if (packet->len + 4 > packet->alloced)
293 NET_IncreasePacket(packet);
294
295 p = packet->data + packet->len;
296
297 p[0] = (i >> 24) & 0xff;
298 p[1] = (i >> 16) & 0xff;
299 p[2] = (i >> 8) & 0xff;
300 p[3] = i & 0xff;
301
302 packet->len += 4;
303 }
304
NET_WriteString(net_packet_t * packet,const char * string)305 void NET_WriteString(net_packet_t *packet, const char *string)
306 {
307 byte *p;
308 size_t string_size;
309
310 string_size = strlen(string) + 1;
311
312 // Increase the packet size until large enough to hold the string
313
314 while (packet->len + string_size > packet->alloced)
315 {
316 NET_IncreasePacket(packet);
317 }
318
319 p = packet->data + packet->len;
320
321 M_StringCopy((char *) p, string, string_size);
322
323 packet->len += string_size;
324 }
325
326
327
328
329