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