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*/
19ENetPacket *
20enet_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*/
56void
57enet_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*/
76int
77enet_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
101static int initializedCRC32 = 0;
102static enet_uint32 crcTable [256];
103
104static enet_uint32
105reflect_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
118static void
119initialize_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
142enet_uint32
143enet_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