mirror of
				https://github.com/godotengine/godot.git
				synced 2025-10-31 13:41:03 +00:00 
			
		
		
		
	
		
			
	
	
		
			166 lines
		
	
	
	
		
			3.8 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			166 lines
		
	
	
	
		
			3.8 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
|   | /** 
 | ||
|  |  @file  packet.c | ||
|  |  @brief ENet packet management functions | ||
|  | */ | ||
|  | #include <string.h>
 | ||
|  | #define ENET_BUILDING_LIB 1
 | ||
|  | #include "enet/enet.h"
 | ||
|  | 
 | ||
|  | /** @defgroup Packet ENet packet functions 
 | ||
|  |     @{  | ||
|  | */ | ||
|  | 
 | ||
|  | /** Creates a packet that may be sent to a peer.
 | ||
|  |     @param data         initial contents of the packet's data; the packet's data will remain uninitialized if data is NULL. | ||
|  |     @param dataLength   size of the data allocated for this packet | ||
|  |     @param flags        flags for this packet as described for the ENetPacket structure. | ||
|  |     @returns the packet on success, NULL on failure | ||
|  | */ | ||
|  | ENetPacket * | ||
|  | enet_packet_create (const void * data, size_t dataLength, enet_uint32 flags) | ||
|  | { | ||
|  |     ENetPacket * packet = (ENetPacket *) enet_malloc (sizeof (ENetPacket)); | ||
|  |     if (packet == NULL) | ||
|  |       return NULL; | ||
|  | 
 | ||
|  |     if (flags & ENET_PACKET_FLAG_NO_ALLOCATE) | ||
|  |       packet -> data = (enet_uint8 *) data; | ||
|  |     else | ||
|  |     if (dataLength <= 0) | ||
|  |       packet -> data = NULL; | ||
|  |     else | ||
|  |     { | ||
|  |        packet -> data = (enet_uint8 *) enet_malloc (dataLength); | ||
|  |        if (packet -> data == NULL) | ||
|  |        { | ||
|  |           enet_free (packet); | ||
|  |           return NULL; | ||
|  |        } | ||
|  | 
 | ||
|  |        if (data != NULL) | ||
|  |          memcpy (packet -> data, data, dataLength); | ||
|  |     } | ||
|  | 
 | ||
|  |     packet -> referenceCount = 0; | ||
|  |     packet -> flags = flags; | ||
|  |     packet -> dataLength = dataLength; | ||
|  |     packet -> freeCallback = NULL; | ||
|  |     packet -> userData = NULL; | ||
|  | 
 | ||
|  |     return packet; | ||
|  | } | ||
|  | 
 | ||
|  | /** Destroys the packet and deallocates its data.
 | ||
|  |     @param packet packet to be destroyed | ||
|  | */ | ||
|  | void | ||
|  | enet_packet_destroy (ENetPacket * packet) | ||
|  | { | ||
|  |     if (packet == NULL) | ||
|  |       return; | ||
|  | 
 | ||
|  |     if (packet -> freeCallback != NULL) | ||
|  |       (* packet -> freeCallback) (packet); | ||
|  |     if (! (packet -> flags & ENET_PACKET_FLAG_NO_ALLOCATE) && | ||
|  |         packet -> data != NULL) | ||
|  |       enet_free (packet -> data); | ||
|  |     enet_free (packet); | ||
|  | } | ||
|  | 
 | ||
|  | /** Attempts to resize the data in the packet to length specified in the 
 | ||
|  |     dataLength parameter  | ||
|  |     @param packet packet to resize | ||
|  |     @param dataLength new size for the packet data | ||
|  |     @returns 0 on success, < 0 on failure | ||
|  | */ | ||
|  | int | ||
|  | enet_packet_resize (ENetPacket * packet, size_t dataLength) | ||
|  | { | ||
|  |     enet_uint8 * newData; | ||
|  |     | ||
|  |     if (dataLength <= packet -> dataLength || (packet -> flags & ENET_PACKET_FLAG_NO_ALLOCATE)) | ||
|  |     { | ||
|  |        packet -> dataLength = dataLength; | ||
|  | 
 | ||
|  |        return 0; | ||
|  |     } | ||
|  | 
 | ||
|  |     newData = (enet_uint8 *) enet_malloc (dataLength); | ||
|  |     if (newData == NULL) | ||
|  |       return -1; | ||
|  | 
 | ||
|  |     memcpy (newData, packet -> data, packet -> dataLength); | ||
|  |     enet_free (packet -> data); | ||
|  |      | ||
|  |     packet -> data = newData; | ||
|  |     packet -> dataLength = dataLength; | ||
|  | 
 | ||
|  |     return 0; | ||
|  | } | ||
|  | 
 | ||
|  | static int initializedCRC32 = 0; | ||
|  | static enet_uint32 crcTable [256]; | ||
|  | 
 | ||
|  | static enet_uint32  | ||
|  | reflect_crc (int val, int bits) | ||
|  | { | ||
|  |     int result = 0, bit; | ||
|  | 
 | ||
|  |     for (bit = 0; bit < bits; bit ++) | ||
|  |     { | ||
|  |         if(val & 1) result |= 1 << (bits - 1 - bit);  | ||
|  |         val >>= 1; | ||
|  |     } | ||
|  | 
 | ||
|  |     return result; | ||
|  | } | ||
|  | 
 | ||
|  | static void  | ||
|  | initialize_crc32 (void) | ||
|  | { | ||
|  |     int byte; | ||
|  | 
 | ||
|  |     for (byte = 0; byte < 256; ++ byte) | ||
|  |     { | ||
|  |         enet_uint32 crc = reflect_crc (byte, 8) << 24; | ||
|  |         int offset; | ||
|  | 
 | ||
|  |         for(offset = 0; offset < 8; ++ offset) | ||
|  |         { | ||
|  |             if (crc & 0x80000000) | ||
|  |                 crc = (crc << 1) ^ 0x04c11db7; | ||
|  |             else | ||
|  |                 crc <<= 1; | ||
|  |         } | ||
|  | 
 | ||
|  |         crcTable [byte] = reflect_crc (crc, 32); | ||
|  |     } | ||
|  | 
 | ||
|  |     initializedCRC32 = 1; | ||
|  | } | ||
|  |      | ||
|  | enet_uint32 | ||
|  | enet_crc32 (const ENetBuffer * buffers, size_t bufferCount) | ||
|  | { | ||
|  |     enet_uint32 crc = 0xFFFFFFFF; | ||
|  |      | ||
|  |     if (! initializedCRC32) initialize_crc32 (); | ||
|  | 
 | ||
|  |     while (bufferCount -- > 0) | ||
|  |     { | ||
|  |         const enet_uint8 * data = (const enet_uint8 *) buffers -> data, | ||
|  |                          * dataEnd = & data [buffers -> dataLength]; | ||
|  | 
 | ||
|  |         while (data < dataEnd) | ||
|  |         { | ||
|  |             crc = (crc >> 8) ^ crcTable [(crc & 0xFF) ^ *data++];         | ||
|  |         } | ||
|  | 
 | ||
|  |         ++ buffers; | ||
|  |     } | ||
|  | 
 | ||
|  |     return ENET_HOST_TO_NET_32 (~ crc); | ||
|  | } | ||
|  | 
 | ||
|  | /** @} */ |