forked from dolphin-emu/dolphin
		
	
		
			
				
	
	
		
			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);
 | 
						|
}
 | 
						|
 | 
						|
/** @} */
 |