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 *
enet_packet_create(const void * data,size_t dataLength,enet_uint32 flags)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
enet_packet_destroy(ENetPacket * packet)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
enet_packet_resize(ENetPacket * packet,size_t dataLength)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
reflect_crc(int val,int bits)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
initialize_crc32(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
enet_crc32(const ENetBuffer * buffers,size_t bufferCount)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