]> Dogcows Code - chaz/yoink/blob - src/Moof/Packet.cc
exception-aware packets; other misc socket changes
[chaz/yoink] / src / Moof / Packet.cc
1
2 /*] Copyright (c) 2009-2010, Charles McGarvey [**************************
3 **] All rights reserved.
4 *
5 * vi:ts=4 sw=4 tw=75
6 *
7 * Distributable under the terms and conditions of the 2-clause BSD license;
8 * see the file COPYING for a complete text of the license.
9 *
10 **************************************************************************/
11
12 #include "../config.h"
13
14 #include <algorithm>
15 #if HAVE_BYTESWAP_H
16 #include <byteswap.h>
17 #endif
18 #include <cstdlib>
19
20 #if HAVE_ARPA_INET_H
21 #include <arpa/inet.h>
22 #endif
23
24 #include <SDL/SDL.h>
25
26 #include "Packet.hh"
27
28
29 #ifndef bswap_16
30 #define bswap_16(x) ((((x) >> 8) & 0xff) | (((x) & 0xff) << 8))
31 #endif
32
33 #ifndef bswap_32
34 #define bswap_32(x) ((((x) & 0xff000000) >> 24) | \
35 (((x) & 0x00ff0000) >> 8) | \
36 (((x) & 0x0000ff00) << 8) | \
37 (((x) & 0x000000ff) << 24))
38 #endif
39
40 #ifndef bswap_64
41 #define bswap_64(x) (((x) << 56) | \
42 (((x) << 40) & 0xff000000000000ULL) | \
43 (((x) << 24) & 0xff0000000000ULL) | \
44 (((x) << 8) & 0xff00000000ULL) | \
45 (((x) >> 8) & 0xff000000ULL) | \
46 (((x) >> 24) & 0xff0000ULL) | \
47 (((x) >> 40) & 0xff00ULL) | \
48 ((x) >> 56))
49 #endif
50
51
52 #if !HAVE_ARPA_INET_H
53 static uint16_t htons(uint16_t x)
54 {
55 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
56 return bswap_16(x);
57 #else
58 return x;
59 #endif
60 }
61 static uint16_t ntohs(uint16_t x)
62 {
63 return htons(x);
64 }
65
66 static uint32_t htonl(uint32_t x)
67 {
68 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
69 return bswap_32(x);
70 #else
71 return x;
72 #endif
73 }
74 static uint32_t ntohl(uint32_t x)
75 {
76 return htonl(x);
77 }
78 #endif
79
80
81 static uint64_t htonll(uint64_t x)
82 {
83 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
84 return bswap_64(x);
85 #else
86 return x;
87 #endif
88 }
89 static uint64_t ntohll(uint64_t x)
90 {
91 return htonll(x);
92 }
93
94
95 namespace Mf {
96
97
98 Packet::Packet(size_t size) :
99 mBuffer((char*)malloc(size)),
100 mSize(size),
101 mR(0),
102 mW(0),
103 mOriginalW(0),
104 mBoolR(0),
105 mBoolW(0),
106 mBoolNumR(0),
107 mBoolNumW(0) {}
108
109 Packet::Packet(const char* data, size_t size) :
110 mBuffer((char*)malloc(size)),
111 mSize(size),
112 mR(0),
113 mW(size),
114 mOriginalW(size),
115 mBoolR(0),
116 mBoolW(0),
117 mBoolNumR(0),
118 mBoolNumW(0)
119 {
120 if (mBuffer) memcpy(mBuffer, data, size);
121 else throw std::length_error("out of memory");
122 }
123
124
125 Packet::Packet(const Packet& copy) :
126 mBuffer((char*)malloc(copy.mSize)),
127 mSize(copy.mSize),
128 mR(copy.mR),
129 mW(copy.mW),
130 mOriginalW(copy.mOriginalW),
131 mBoolR(copy.mBoolR),
132 mBoolW(copy.mBoolW),
133 mBoolNumR(copy.mBoolNumR),
134 mBoolNumW(copy.mBoolNumW)
135 {
136 if (mBuffer) memcpy(mBuffer, copy.mBuffer, mSize);
137 else throw std::length_error("out of memory");
138 }
139
140 Packet& Packet::operator=(const Packet& copy)
141 {
142 free(mBuffer);
143
144 mBuffer = (char*)malloc(copy.mSize);
145 mSize = copy.mSize;
146 mR = copy.mR;
147 mW = copy.mW;
148 mOriginalW = copy.mOriginalW;
149 mBoolR = copy.mBoolR;
150 mBoolW = copy.mBoolW;
151 mBoolNumR = copy.mBoolNumR;
152 mBoolNumW = copy.mBoolNumW;
153 if (mBuffer) memcpy(mBuffer, copy.mBuffer, mSize);
154 else throw std::length_error("out of memory");
155 return *this;
156 }
157
158
159 Packet::~Packet()
160 {
161 free(mBuffer);
162 }
163
164
165 Packet& Packet::operator<<(bool value)
166 {
167 int bit = mBoolNumW % 8;
168 if (bit == 0)
169 {
170 mBoolW = mW;
171
172 unsigned char byte = 0;
173 if (write(&byte, 1) == 0) throw std::length_error("out of memory");
174 }
175
176 if (value) mBuffer[mBoolW] |= (1 << bit);
177 ++mBoolNumW;
178
179 return *this;
180 }
181
182
183 Packet& Packet::operator<<(int8_t value)
184 {
185 return *this << (uint8_t)value;
186 }
187
188 Packet& Packet::operator<<(int16_t value)
189 {
190 return *this << (uint16_t)value;
191 }
192
193 Packet& Packet::operator<<(int32_t value)
194 {
195 return *this << (uint32_t)value;
196 }
197
198 Packet& Packet::operator<<(int64_t value)
199 {
200 return *this << (uint64_t)value;
201 }
202
203
204 Packet& Packet::operator<<(uint8_t value)
205 {
206 if (write(&value, sizeof(value)) != sizeof(value))
207 {
208 throw std::length_error("out of memory");
209 }
210 return *this;
211 }
212
213 Packet& Packet::operator<<(uint16_t value)
214 {
215 value = htons(value);
216 if (write(&value, sizeof(value)) != sizeof(value))
217 {
218 throw std::length_error("out of memory");
219 }
220 return *this;
221 }
222
223 Packet& Packet::operator<<(uint32_t value)
224 {
225 value = htonl(value);
226 if (write(&value, sizeof(value)) != sizeof(value))
227 {
228 throw std::length_error("out of memory");
229 }
230 return *this;
231 }
232
233 Packet& Packet::operator<<(uint64_t value)
234 {
235 value = htonll(value);
236 if (write(&value, sizeof(value)) != sizeof(value))
237 {
238 throw std::length_error("out of memory");
239 }
240 return *this;
241 }
242
243 Packet& Packet::operator<<(float value)
244 {
245 // XXX: assumes the ieee-754
246 uint32_t* integer = reinterpret_cast<uint32_t*>(&value);
247 *integer = htonl(*integer);
248 if (write(integer, sizeof(value)) != sizeof(value))
249 {
250 throw std::length_error("out of memory");
251 }
252 return *this;
253 }
254
255 Packet& Packet::operator<<(double value)
256 {
257 // XXX: assumes the ieee-754
258 uint64_t* integer = reinterpret_cast<uint64_t*>(&value);
259 *integer = htonll(*integer);
260 if (write(integer, sizeof(value)) != sizeof(value))
261 {
262 throw std::length_error("out of memory");
263 }
264 return *this;
265 }
266
267 size_t Packet::write(const void* bytes, size_t size)
268 {
269 size_t nBytes = std::min(size, mSize - mW);
270 if (!mBuffer || nBytes < size)
271 {
272 int nPages = 1 + size / PAGE_SIZE;
273 int newSize = mSize + nPages * PAGE_SIZE;
274 char* newBuffer = (char*)realloc(mBuffer, newSize);
275 if (newBuffer)
276 {
277 mBuffer = newBuffer;
278 mSize = newSize;
279 nBytes = size;
280 }
281 if (!mBuffer) return 0;
282 }
283 memcpy(mBuffer + mW, bytes, nBytes);
284 mW += nBytes;
285 return nBytes;
286 }
287
288
289 Packet& Packet::operator>>(bool& value)
290 {
291 int bit = mBoolNumR % 8;
292 if (bit == 0)
293 {
294 mBoolR = mR;
295
296 unsigned char byte = 0;
297 if (read(&byte, 1) == 0) throw std::out_of_range("end of packet");
298 }
299
300 value = 1 & (mBuffer[mBoolR] >> bit);
301 ++mBoolNumR;
302
303 return *this;
304 }
305
306 Packet& Packet::operator>>(int8_t& value)
307 {
308 return *this >> (uint8_t&)value;
309 }
310
311 Packet& Packet::operator>>(int16_t& value)
312 {
313 return *this >> (uint16_t&)value;
314 }
315
316 Packet& Packet::operator>>(int32_t& value)
317 {
318 return *this >> (uint32_t&)value;
319 }
320
321 Packet& Packet::operator>>(int64_t& value)
322 {
323 return *this >> (uint64_t&)value;
324 }
325
326 Packet& Packet::operator>>(uint8_t& value)
327 {
328 if (read(&value, sizeof(value)) != sizeof(value))
329 {
330 throw std::out_of_range("end of packet");
331 }
332 return *this;
333 }
334
335 Packet& Packet::operator>>(uint16_t& value)
336 {
337 if (read(&value, sizeof(value)) != sizeof(value))
338 {
339 throw std::out_of_range("end of packet");
340 }
341 value = ntohs(value);
342 return *this;
343 }
344
345 Packet& Packet::operator>>(uint32_t& value)
346 {
347 if (read(&value, sizeof(value)) != sizeof(value))
348 {
349 throw std::out_of_range("end of packet");
350 }
351 value = ntohl(value);
352 return *this;
353 }
354
355 Packet& Packet::operator>>(uint64_t& value)
356 {
357 if (read(&value, sizeof(value)) != sizeof(value))
358 {
359 throw std::out_of_range("end of packet");
360 }
361 value = ntohll(value);
362 return *this;
363 }
364
365 Packet& Packet::operator>>(float& value)
366 {
367 // XXX: assumes the ieee-754
368 uint32_t* integer = reinterpret_cast<uint32_t*>(&value);
369 if (read(integer, sizeof(value)) != sizeof(value))
370 {
371 throw std::out_of_range("end of packet");
372 }
373 *integer = htonl(*integer);
374 return *this;
375 }
376
377 Packet& Packet::operator>>(double& value)
378 {
379 // XXX: assumes the ieee-754
380 uint64_t* integer = reinterpret_cast<uint64_t*>(&value);
381 if (read(integer, sizeof(value)) != sizeof(value))
382 {
383 throw std::out_of_range("end of packet");
384 }
385 *integer = htonll(*integer);
386 return *this;
387 }
388
389 size_t Packet::read(void* bytes, size_t size)
390 {
391 size_t nBytes = std::min(size, mW - mR);
392 memcpy(bytes, mBuffer + mR, nBytes);
393 mR += nBytes;
394 return nBytes;
395 }
396
397
398 void Packet::clear()
399 {
400 mR = 0;
401 mW = 0;
402 mBoolR = 0;
403 mBoolW = 0;
404 mBoolNumR = 0;
405 mBoolNumW = 0;
406 }
407
408
409 void Packet::reset()
410 {
411 mR = 0;
412 mW = mOriginalW;
413 mBoolR = 0;
414 mBoolW = 0;
415 mBoolNumR = 0;
416 mBoolNumW = 0;
417 }
418
419
420 } // namespace Mf
421
This page took 0.045868 seconds and 4 git commands to generate.