1 | /** |
2 | @file packet.c |
3 | @brief ENet packet management functions |
4 | */ |
5 | #include <string.h> |
6 | #define ENET_BUILDING_LIB 1 |
7 | #include "enet/enet.h" |
8 | |
9 | /** @defgroup Packet ENet packet functions |
10 | @{ |
11 | */ |
12 | |
13 | /** Creates a packet that may be sent to a peer. |
14 | @param data initial contents of the packet's data; the packet's data will remain uninitialized if data is NULL. |
15 | @param dataLength size of the data allocated for this packet |
16 | @param flags flags for this packet as described for the ENetPacket structure. |
17 | @returns the packet on success, NULL on failure |
18 | */ |
19 | ENetPacket * |
20 | enet_packet_create (const void * data, size_t dataLength, enet_uint32 flags) |
21 | { |
22 | ENetPacket * packet = (ENetPacket *) enet_malloc (sizeof (ENetPacket)); |
23 | if (packet == NULL) |
24 | return NULL; |
25 | |
26 | if (flags & ENET_PACKET_FLAG_NO_ALLOCATE) |
27 | packet -> data = (enet_uint8 *) data; |
28 | else |
29 | if (dataLength <= 0) |
30 | packet -> data = NULL; |
31 | else |
32 | { |
33 | packet -> data = (enet_uint8 *) enet_malloc (dataLength); |
34 | if (packet -> data == NULL) |
35 | { |
36 | enet_free (packet); |
37 | return NULL; |
38 | } |
39 | |
40 | if (data != NULL) |
41 | memcpy (packet -> data, data, dataLength); |
42 | } |
43 | |
44 | packet -> referenceCount = 0; |
45 | packet -> flags = flags; |
46 | packet -> dataLength = dataLength; |
47 | packet -> freeCallback = NULL; |
48 | packet -> userData = NULL; |
49 | |
50 | return packet; |
51 | } |
52 | |
53 | /** Destroys the packet and deallocates its data. |
54 | @param packet packet to be destroyed |
55 | */ |
56 | void |
57 | enet_packet_destroy (ENetPacket * packet) |
58 | { |
59 | if (packet == NULL) |
60 | return; |
61 | |
62 | if (packet -> freeCallback != NULL) |
63 | (* packet -> freeCallback) (packet); |
64 | if (! (packet -> flags & ENET_PACKET_FLAG_NO_ALLOCATE) && |
65 | packet -> data != NULL) |
66 | enet_free (packet -> data); |
67 | enet_free (packet); |
68 | } |
69 | |
70 | /** Attempts to resize the data in the packet to length specified in the |
71 | dataLength parameter |
72 | @param packet packet to resize |
73 | @param dataLength new size for the packet data |
74 | @returns 0 on success, < 0 on failure |
75 | */ |
76 | int |
77 | enet_packet_resize (ENetPacket * packet, size_t dataLength) |
78 | { |
79 | enet_uint8 * newData; |
80 | |
81 | if (dataLength <= packet -> dataLength || (packet -> flags & ENET_PACKET_FLAG_NO_ALLOCATE)) |
82 | { |
83 | packet -> dataLength = dataLength; |
84 | |
85 | return 0; |
86 | } |
87 | |
88 | newData = (enet_uint8 *) enet_malloc (dataLength); |
89 | if (newData == NULL) |
90 | return -1; |
91 | |
92 | memcpy (newData, packet -> data, packet -> dataLength); |
93 | enet_free (packet -> data); |
94 | |
95 | packet -> data = newData; |
96 | packet -> dataLength = dataLength; |
97 | |
98 | return 0; |
99 | } |
100 | |
101 | static int initializedCRC32 = 0; |
102 | static enet_uint32 crcTable [256]; |
103 | |
104 | static enet_uint32 |
105 | reflect_crc (int val, int bits) |
106 | { |
107 | int result = 0, bit; |
108 | |
109 | for (bit = 0; bit < bits; bit ++) |
110 | { |
111 | if(val & 1) result |= 1 << (bits - 1 - bit); |
112 | val >>= 1; |
113 | } |
114 | |
115 | return result; |
116 | } |
117 | |
118 | static void |
119 | initialize_crc32 (void) |
120 | { |
121 | int byte; |
122 | |
123 | for (byte = 0; byte < 256; ++ byte) |
124 | { |
125 | enet_uint32 crc = reflect_crc (byte, 8) << 24; |
126 | int offset; |
127 | |
128 | for(offset = 0; offset < 8; ++ offset) |
129 | { |
130 | if (crc & 0x80000000) |
131 | crc = (crc << 1) ^ 0x04c11db7; |
132 | else |
133 | crc <<= 1; |
134 | } |
135 | |
136 | crcTable [byte] = reflect_crc (crc, 32); |
137 | } |
138 | |
139 | initializedCRC32 = 1; |
140 | } |
141 | |
142 | enet_uint32 |
143 | enet_crc32 (const ENetBuffer * buffers, size_t bufferCount) |
144 | { |
145 | enet_uint32 crc = 0xFFFFFFFF; |
146 | |
147 | if (! initializedCRC32) initialize_crc32 (); |
148 | |
149 | while (bufferCount -- > 0) |
150 | { |
151 | const enet_uint8 * data = (const enet_uint8 *) buffers -> data, |
152 | * dataEnd = & data [buffers -> dataLength]; |
153 | |
154 | while (data < dataEnd) |
155 | { |
156 | crc = (crc >> 8) ^ crcTable [(crc & 0xFF) ^ *data++]; |
157 | } |
158 | |
159 | ++ buffers; |
160 | } |
161 | |
162 | return ENET_HOST_TO_NET_32 (~ crc); |
163 | } |
164 | |
165 | /** @} */ |
166 | |