diff --git a/configure.in b/configure.in index bd626c8..eb6a374 100644 --- a/configure.in +++ b/configure.in @@ -1,5 +1,5 @@ -AC_INIT(libenet, 1.0) -AM_INIT_AUTOMAKE(libenet.a, 1.0) +AC_INIT(libenet, 7-6-2006) +AM_INIT_AUTOMAKE(libenet.a, 7-6-2006) AC_PROG_CC AC_PROG_RANLIB @@ -21,4 +21,16 @@ AC_CHECK_TYPE(socklen_t, [AC_DEFINE(HAS_SOCKLEN_T)], , AC_EGREP_HEADER(MSG_MAXIOVLEN, /usr/include/sys/socket.h, AC_DEFINE(ENET_BUFFER_MAXIMUM, [MSG_MAXIOVLEN])) AC_EGREP_HEADER(MSG_MAXIOVLEN, socket.h, AC_DEFINE(ENET_BUFFER_MAXIMUM, [MSG_MAXIOVLEN])) +AC_MSG_CHECKING(whether to use CRC32) +AC_ARG_ENABLE(crc32, + [ --enable-crc32 enable CRC32 packet verification ], + [if test "$enableval" = yes; then + AC_MSG_RESULT(yes) + AC_DEFINE(USE_CRC32) + else + AC_MSG_RESULT(no) + fi], + [AC_MSG_RESULT(no)]) + AC_OUTPUT([Makefile include/Makefile include/enet/Makefile]) + diff --git a/host.c b/host.c index e5db56e..5633fb9 100644 --- a/host.c +++ b/host.c @@ -30,6 +30,9 @@ enet_host_create (const ENetAddress * address, size_t peerCount, enet_uint32 inc ENetHost * host = (ENetHost *) enet_malloc (sizeof (ENetHost)); ENetPeer * currentPeer; + if (peerCount > ENET_PROTOCOL_MAXIMUM_PEER_ID) + return NULL; + host -> peers = (ENetPeer *) enet_malloc (peerCount * sizeof (ENetPeer)); memset (host -> peers, 0, peerCount * sizeof (ENetPeer)); @@ -135,7 +138,7 @@ enet_host_connect (ENetHost * host, const ENetAddress * address, size_t channelC currentPeer -> address = * address; currentPeer -> channels = (ENetChannel *) enet_malloc (channelCount * sizeof (ENetChannel)); currentPeer -> channelCount = channelCount; - currentPeer -> challenge = (enet_uint32) enet_rand (); + currentPeer -> sessionID = (enet_uint32) enet_rand (); if (host -> outgoingBandwidth == 0) currentPeer -> windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE; @@ -163,10 +166,8 @@ enet_host_connect (ENetHost * host, const ENetAddress * address, size_t channelC enet_list_clear (& channel -> incomingUnreliableCommands); } - command.header.command = ENET_PROTOCOL_COMMAND_CONNECT; + command.header.command = ENET_PROTOCOL_COMMAND_CONNECT | ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE; command.header.channelID = 0xFF; - command.header.flags = ENET_PROTOCOL_FLAG_ACKNOWLEDGE; - command.header.commandLength = sizeof (ENetProtocolConnect); command.connect.outgoingPeerID = ENET_HOST_TO_NET_16 (currentPeer -> incomingPeerID); command.connect.mtu = ENET_HOST_TO_NET_16 (currentPeer -> mtu); command.connect.windowSize = ENET_HOST_TO_NET_32 (currentPeer -> windowSize); @@ -176,6 +177,7 @@ enet_host_connect (ENetHost * host, const ENetAddress * address, size_t channelC command.connect.packetThrottleInterval = ENET_HOST_TO_NET_32 (currentPeer -> packetThrottleInterval); command.connect.packetThrottleAcceleration = ENET_HOST_TO_NET_32 (currentPeer -> packetThrottleAcceleration); command.connect.packetThrottleDeceleration = ENET_HOST_TO_NET_32 (currentPeer -> packetThrottleDeceleration); + command.connect.sessionID = currentPeer -> sessionID; enet_peer_queue_outgoing_command (currentPeer, & command, NULL, 0, 0); @@ -243,7 +245,7 @@ enet_host_bandwidth_throttle (ENetHost * host) peer < & host -> peers [host -> peerCount]; ++ peer) { - if (peer -> state != ENET_PEER_STATE_CONNECTED) + if (peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER) continue; ++ peersTotal; @@ -276,7 +278,7 @@ enet_host_bandwidth_throttle (ENetHost * host) { enet_uint32 peerBandwidth; - if (peer -> state != ENET_PEER_STATE_CONNECTED || + if ((peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER) || peer -> incomingBandwidth == 0 || peer -> outgoingBandwidthThrottleEpoch == timeCurrent) continue; @@ -309,7 +311,7 @@ enet_host_bandwidth_throttle (ENetHost * host) peer < & host -> peers [host -> peerCount]; ++ peer) { - if (peer -> state != ENET_PEER_STATE_CONNECTED || + if ((peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER) || peer -> outgoingBandwidthThrottleEpoch == timeCurrent) continue; @@ -339,12 +341,12 @@ enet_host_bandwidth_throttle (ENetHost * host) peer < & host -> peers [host -> peerCount]; ++ peer) { - if (peer -> state != ENET_PEER_STATE_CONNECTED || + if ((peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER) || peer -> incomingBandwidthThrottleEpoch == timeCurrent) continue; if (peer -> outgoingBandwidth > 0 && - bandwidthLimit > peer -> outgoingBandwidth) + peer -> outgoingBandwidth >= bandwidthLimit) continue; peer -> incomingBandwidthThrottleEpoch = timeCurrent; @@ -359,13 +361,11 @@ enet_host_bandwidth_throttle (ENetHost * host) peer < & host -> peers [host -> peerCount]; ++ peer) { - if (peer -> state != ENET_PEER_STATE_CONNECTED) + if (peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER) continue; - command.header.command = ENET_PROTOCOL_COMMAND_BANDWIDTH_LIMIT; + command.header.command = ENET_PROTOCOL_COMMAND_BANDWIDTH_LIMIT | ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE; command.header.channelID = 0xFF; - command.header.flags = ENET_PROTOCOL_FLAG_ACKNOWLEDGE; - command.header.commandLength = sizeof (ENetProtocolBandwidthLimit); command.bandwidthLimit.outgoingBandwidth = ENET_HOST_TO_NET_32 (host -> outgoingBandwidth); if (peer -> incomingBandwidthThrottleEpoch == timeCurrent) diff --git a/include/enet/enet.h b/include/enet/enet.h index 4c48a92..24f6ef9 100644 --- a/include/enet/enet.h +++ b/include/enet/enet.h @@ -80,7 +80,9 @@ typedef enum /** packet will not be sequenced with other packets * not supported for reliable packets */ - ENET_PACKET_FLAG_UNSEQUENCED = (1 << 1) + ENET_PACKET_FLAG_UNSEQUENCED = (1 << 1), + /** packet will not allocate data, and user must supply it instead */ + ENET_PACKET_FLAG_NO_ALLOCATE = (1 << 2) } ENetPacketFlag; /** @@ -115,8 +117,8 @@ typedef struct _ENetAcknowledgement typedef struct _ENetOutgoingCommand { ENetListNode outgoingCommandList; - enet_uint32 reliableSequenceNumber; - enet_uint32 unreliableSequenceNumber; + enet_uint16 reliableSequenceNumber; + enet_uint16 unreliableSequenceNumber; enet_uint32 sentTime; enet_uint32 roundTripTimeout; enet_uint32 roundTripTimeoutLimit; @@ -129,8 +131,8 @@ typedef struct _ENetOutgoingCommand typedef struct _ENetIncomingCommand { ENetListNode incomingCommandList; - enet_uint32 reliableSequenceNumber; - enet_uint32 unreliableSequenceNumber; + enet_uint16 reliableSequenceNumber; + enet_uint16 unreliableSequenceNumber; ENetProtocol command; enet_uint32 fragmentCount; enet_uint32 fragmentsRemaining; @@ -144,10 +146,12 @@ typedef enum ENET_PEER_STATE_CONNECTING = 1, ENET_PEER_STATE_ACKNOWLEDGING_CONNECT = 2, ENET_PEER_STATE_CONNECTION_PENDING = 3, - ENET_PEER_STATE_CONNECTED = 4, - ENET_PEER_STATE_DISCONNECTING = 5, - ENET_PEER_STATE_ACKNOWLEDGING_DISCONNECT = 6, - ENET_PEER_STATE_ZOMBIE = 7 + ENET_PEER_STATE_CONNECTION_SUCCEEDED = 4, + ENET_PEER_STATE_CONNECTED = 5, + ENET_PEER_STATE_DISCONNECT_LATER = 6, + ENET_PEER_STATE_DISCONNECTING = 7, + ENET_PEER_STATE_ACKNOWLEDGING_DISCONNECT = 8, + ENET_PEER_STATE_ZOMBIE = 9 } ENetPeerState; #ifndef ENET_BUFFER_MAXIMUM @@ -157,6 +161,7 @@ typedef enum enum { ENET_HOST_RECEIVE_BUFFER_SIZE = 256 * 1024, + ENET_HOST_SEND_BUFFER_SIZE = 256 * 1024, ENET_HOST_BANDWIDTH_THROTTLE_INTERVAL = 1000, ENET_HOST_DEFAULT_MTU = 1400, @@ -197,7 +202,7 @@ typedef struct _ENetPeer struct _ENetHost * host; enet_uint16 outgoingPeerID; enet_uint16 incomingPeerID; - enet_uint32 challenge; + enet_uint32 sessionID; ENetAddress address; /**< Internet address of the peer */ void * data; /**< Application private data, may be freely modified */ ENetPeerState state; @@ -234,14 +239,14 @@ typedef struct _ENetPeer enet_uint16 mtu; enet_uint32 windowSize; enet_uint32 reliableDataInTransit; - enet_uint32 outgoingReliableSequenceNumber; + enet_uint16 outgoingReliableSequenceNumber; ENetList acknowledgements; ENetList sentReliableCommands; ENetList sentUnreliableCommands; ENetList outgoingReliableCommands; ENetList outgoingUnreliableCommands; - enet_uint32 incomingUnsequencedGroup; - enet_uint32 outgoingUnsequencedGroup; + enet_uint16 incomingUnsequencedGroup; + enet_uint16 outgoingUnsequencedGroup; enet_uint32 unsequencedWindow [ENET_PEER_UNSEQUENCED_WINDOW_SIZE / 32]; enet_uint32 disconnectData; } ENetPeer; @@ -271,7 +276,9 @@ typedef struct _ENetHost ENetPeer * peers; /**< array of peers allocated for this host */ size_t peerCount; /**< number of peers allocated for this host */ ENetPeer * lastServicedPeer; + int continueSending; size_t packetSize; + enet_uint16 headerFlags; ENetProtocol commands [ENET_PROTOCOL_MAXIMUM_PACKET_COMMANDS]; size_t commandCount; ENetBuffer buffers [ENET_BUFFER_MAXIMUM]; @@ -337,7 +344,7 @@ typedef struct _ENetEvent */ ENET_API int enet_initialize (void); -ENET_API int enet_initialize_with_callbacks (ENetVersion version, const ENetCallbacks * inits); +ENET_API int enet_initialize_with_callbacks (ENetVersion, const ENetCallbacks *); /** Shuts down ENet globally. Should be called when a program that has @@ -361,15 +368,14 @@ ENET_API void enet_time_set (enet_uint32); /** @defgroup socket ENet socket functions @{ - @ingroup private */ -extern ENetSocket enet_socket_create (ENetSocketType, const ENetAddress *); -extern ENetSocket enet_socket_accept (ENetSocket, ENetAddress *); -extern int enet_socket_connect (ENetSocket, const ENetAddress *); -extern int enet_socket_send (ENetSocket, const ENetAddress *, const ENetBuffer *, size_t); -extern int enet_socket_receive (ENetSocket, ENetAddress *, ENetBuffer *, size_t); -extern int enet_socket_wait (ENetSocket, enet_uint32 *, enet_uint32); -extern void enet_socket_destroy (ENetSocket); +ENET_API ENetSocket enet_socket_create (ENetSocketType, const ENetAddress *); +ENET_API ENetSocket enet_socket_accept (ENetSocket, ENetAddress *); +ENET_API int enet_socket_connect (ENetSocket, const ENetAddress *); +ENET_API int enet_socket_send (ENetSocket, const ENetAddress *, const ENetBuffer *, size_t); +ENET_API int enet_socket_receive (ENetSocket, ENetAddress *, ENetBuffer *, size_t); +ENET_API int enet_socket_wait (ENetSocket, enet_uint32 *, enet_uint32); +ENET_API void enet_socket_destroy (ENetSocket); /** @} */ @@ -384,7 +390,7 @@ extern void enet_socket_destroy (ENetSocket); @retval < 0 on failure @returns the address of the given hostName in address on success */ -ENET_API int enet_address_set_host (ENetAddress *address, const char *hostName ); +ENET_API int enet_address_set_host (ENetAddress * address, const char * hostName); /** Attempts to do a reserve lookup of the host field in the address parameter. @param address address used for reverse lookup @@ -394,17 +400,18 @@ ENET_API int enet_address_set_host (ENetAddress *address, const char *hostName ) @retval 0 on success @retval < 0 on failure */ -ENET_API int enet_address_get_host (const ENetAddress *address, char *hostName, size_t nameLength ); +ENET_API int enet_address_get_host (const ENetAddress * address, char * hostName, size_t nameLength); /** @} */ -ENET_API ENetPacket * enet_packet_create (const void *dataContents, size_t dataLength, enet_uint32 flags); -ENET_API void enet_packet_destroy (ENetPacket *packet ); -ENET_API int enet_packet_resize (ENetPacket *packet, size_t dataLength ); - -ENET_API ENetHost * enet_host_create (const ENetAddress *address, size_t peerCount, enet_uint32 incomingBandwidth, enet_uint32 outgoingBandwidth ); -ENET_API void enet_host_destroy (ENetHost *host ); -ENET_API ENetPeer * enet_host_connect (ENetHost *host, const ENetAddress *address, size_t channelCount ); +ENET_API ENetPacket * enet_packet_create (const void *, size_t, enet_uint32); +ENET_API void enet_packet_destroy (ENetPacket *); +ENET_API int enet_packet_resize (ENetPacket *, size_t); +extern enet_uint32 enet_crc32 (const ENetBuffer *, size_t); + +ENET_API ENetHost * enet_host_create (const ENetAddress *, size_t, enet_uint32, enet_uint32); +ENET_API void enet_host_destroy (ENetHost *); +ENET_API ENetPeer * enet_host_connect (ENetHost *, const ENetAddress *, size_t); ENET_API int enet_host_service (ENetHost *, ENetEvent *, enet_uint32); ENET_API void enet_host_flush (ENetHost *); ENET_API void enet_host_broadcast (ENetHost *, enet_uint8, ENetPacket *); @@ -417,12 +424,15 @@ ENET_API void enet_peer_ping (ENetPeer *); ENET_API void enet_peer_reset (ENetPeer *); ENET_API void enet_peer_disconnect (ENetPeer *, enet_uint32); ENET_API void enet_peer_disconnect_now (ENetPeer *, enet_uint32); +ENET_API void enet_peer_disconnect_later (ENetPeer *, enet_uint32); ENET_API void enet_peer_throttle_configure (ENetPeer *, enet_uint32, enet_uint32, enet_uint32); extern int enet_peer_throttle (ENetPeer *, enet_uint32); extern void enet_peer_reset_queues (ENetPeer *); extern ENetOutgoingCommand * enet_peer_queue_outgoing_command (ENetPeer *, const ENetProtocol *, ENetPacket *, enet_uint32, enet_uint16); extern ENetIncomingCommand * enet_peer_queue_incoming_command (ENetPeer *, const ENetProtocol *, ENetPacket *, enet_uint32); -extern ENetAcknowledgement * enet_peer_queue_acknowledgement (ENetPeer *, const ENetProtocol *, enet_uint32); +extern ENetAcknowledgement * enet_peer_queue_acknowledgement (ENetPeer *, const ENetProtocol *, enet_uint16); + +extern size_t enet_protocol_command_size (enet_uint8); #ifdef __cplusplus } diff --git a/include/enet/protocol.h b/include/enet/protocol.h index 6d4dae9..e5b4a32 100644 --- a/include/enet/protocol.h +++ b/include/enet/protocol.h @@ -15,7 +15,8 @@ enum ENET_PROTOCOL_MINIMUM_WINDOW_SIZE = 4096, ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE = 32768, ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT = 1, - ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT = 255 + ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT = 255, + ENET_PROTOCOL_MAXIMUM_PEER_ID = 0x7FFF, }; typedef enum @@ -29,41 +30,42 @@ typedef enum ENET_PROTOCOL_COMMAND_SEND_RELIABLE = 6, ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE = 7, ENET_PROTOCOL_COMMAND_SEND_FRAGMENT = 8, - ENET_PROTOCOL_COMMAND_BANDWIDTH_LIMIT = 9, - ENET_PROTOCOL_COMMAND_THROTTLE_CONFIGURE = 10, - ENET_PROTOCOL_COMMAND_SEND_UNSEQUENCED = 11 + ENET_PROTOCOL_COMMAND_SEND_UNSEQUENCED = 9, + ENET_PROTOCOL_COMMAND_BANDWIDTH_LIMIT = 10, + ENET_PROTOCOL_COMMAND_THROTTLE_CONFIGURE = 11, + ENET_PROTOCOL_COMMAND_COUNT = 12, + + ENET_PROTOCOL_COMMAND_MASK = 0x0F, } ENetProtocolCommand; typedef enum { - ENET_PROTOCOL_FLAG_ACKNOWLEDGE = (1 << 0), - ENET_PROTOCOL_FLAG_UNSEQUENCED = (1 << 1) + ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE = (1 << 7), + ENET_PROTOCOL_COMMAND_FLAG_UNSEQUENCED = (1 << 6), + + ENET_PROTOCOL_HEADER_FLAG_SENT_TIME = (1 << 15), + ENET_PROTOCOL_HEADER_FLAG_MASK = 0x8000, } ENetProtocolFlag; typedef struct { + enet_uint32 checksum; enet_uint16 peerID; - enet_uint8 flags; - enet_uint8 commandCount; - enet_uint32 sentTime; - enet_uint32 challenge; + enet_uint16 sentTime; } ENetProtocolHeader; typedef struct { enet_uint8 command; enet_uint8 channelID; - enet_uint8 flags; - enet_uint8 reserved; - enet_uint32 commandLength; - enet_uint32 reliableSequenceNumber; + enet_uint16 reliableSequenceNumber; } ENetProtocolCommandHeader; typedef struct { ENetProtocolCommandHeader header; - enet_uint32 receivedReliableSequenceNumber; - enet_uint32 receivedSentTime; + enet_uint16 receivedReliableSequenceNumber; + enet_uint16 receivedSentTime; } ENetProtocolAcknowledge; typedef struct @@ -78,6 +80,7 @@ typedef struct enet_uint32 packetThrottleInterval; enet_uint32 packetThrottleAcceleration; enet_uint32 packetThrottleDeceleration; + enet_uint32 sessionID; } ENetProtocolConnect; typedef struct @@ -123,24 +126,28 @@ typedef struct typedef struct { ENetProtocolCommandHeader header; + enet_uint16 dataLength; } ENetProtocolSendReliable; typedef struct { ENetProtocolCommandHeader header; - enet_uint32 unreliableSequenceNumber; + enet_uint16 unreliableSequenceNumber; + enet_uint16 dataLength; } ENetProtocolSendUnreliable; typedef struct { ENetProtocolCommandHeader header; - enet_uint32 unsequencedGroup; + enet_uint16 unsequencedGroup; + enet_uint16 dataLength; } ENetProtocolSendUnsequenced; typedef struct { ENetProtocolCommandHeader header; - enet_uint32 startSequenceNumber; + enet_uint16 startSequenceNumber; + enet_uint16 dataLength; enet_uint32 fragmentCount; enet_uint32 fragmentNumber; enet_uint32 totalLength; diff --git a/packet.c b/packet.c index 5226550..77b5583 100644 --- a/packet.c +++ b/packet.c @@ -21,10 +21,15 @@ enet_packet_create (const void * data, size_t dataLength, enet_uint32 flags) { ENetPacket * packet = (ENetPacket *) enet_malloc (sizeof (ENetPacket)); - packet -> data = (enet_uint8 *) enet_malloc (dataLength); + if(flags & ENET_PACKET_FLAG_NO_ALLOCATE) + packet -> data = (enet_uint8 *) data; + else + { + packet -> data = (enet_uint8 *) enet_malloc (dataLength); - if (data != NULL) - memcpy (packet -> data, data, dataLength); + if (data != NULL) + memcpy (packet -> data, data, dataLength); + }; packet -> referenceCount = 0; packet -> flags = flags; @@ -39,7 +44,8 @@ enet_packet_create (const void * data, size_t dataLength, enet_uint32 flags) void enet_packet_destroy (ENetPacket * packet) { - enet_free (packet -> data); + if((packet -> flags & ENET_PACKET_FLAG_NO_ALLOCATE) == 0) + enet_free (packet -> data); enet_free (packet); } @@ -54,7 +60,7 @@ enet_packet_resize (ENetPacket * packet, size_t dataLength) { enet_uint8 * newData; - if (dataLength <= packet -> dataLength) + if (dataLength <= packet -> dataLength || (packet -> flags & ENET_PACKET_FLAG_NO_ALLOCATE)) { packet -> dataLength = dataLength; @@ -71,4 +77,53 @@ enet_packet_resize (ENetPacket * packet, size_t dataLength) return 0; } +static int initializedCRC32 = 0; +static enet_uint32 crcTable [256]; + +static void initialize_crc32 () +{ + int byte; + + for (byte = 0; byte < 256; ++ byte) + { + enet_uint32 crc = byte << 24; + int offset; + + for(offset = 0; offset < 8; ++ offset) + { + if (crc & 0x80000000) + crc = (crc << 1) ^ 0x04c11db7; + else + crc <<= 1; + } + + crcTable [byte] = crc; + } + + 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) | * data ++) ^ crcTable [crc >> 24]; + } + + ++ buffers; + } + + return ENET_HOST_TO_NET_32 (~ crc); +} + /** @} */ diff --git a/peer.c b/peer.c index 754239f..1a23c4c 100644 --- a/peer.c +++ b/peer.c @@ -48,10 +48,8 @@ enet_peer_throttle_configure (ENetPeer * peer, enet_uint32 interval, enet_uint32 peer -> packetThrottleAcceleration = acceleration; peer -> packetThrottleDeceleration = deceleration; - command.header.command = ENET_PROTOCOL_COMMAND_THROTTLE_CONFIGURE; + command.header.command = ENET_PROTOCOL_COMMAND_THROTTLE_CONFIGURE | ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE; command.header.channelID = 0xFF; - command.header.flags = ENET_PROTOCOL_FLAG_ACKNOWLEDGE; - command.header.commandLength = sizeof (ENetProtocolThrottleConfigure); command.throttleConfigure.packetThrottleInterval = ENET_HOST_TO_NET_32 (interval); command.throttleConfigure.packetThrottleAcceleration = ENET_HOST_TO_NET_32 (acceleration); @@ -113,8 +111,8 @@ enet_peer_send (ENetPeer * peer, enet_uint8 channelID, ENetPacket * packet) if (packet -> dataLength > fragmentLength) { + enet_uint16 startSequenceNumber = ENET_HOST_TO_NET_16 (channel -> outgoingReliableSequenceNumber + 1); enet_uint32 fragmentCount = ENET_HOST_TO_NET_32 ((packet -> dataLength + fragmentLength - 1) / fragmentLength), - startSequenceNumber = ENET_HOST_TO_NET_32 (channel -> outgoingReliableSequenceNumber + 1), fragmentNumber, fragmentOffset; @@ -126,19 +124,18 @@ enet_peer_send (ENetPeer * peer, enet_uint8 channelID, ENetPacket * packet) ++ fragmentNumber, fragmentOffset += fragmentLength) { - command.header.command = ENET_PROTOCOL_COMMAND_SEND_FRAGMENT; + if (packet -> dataLength - fragmentOffset < fragmentLength) + fragmentLength = packet -> dataLength - fragmentOffset; + + command.header.command = ENET_PROTOCOL_COMMAND_SEND_FRAGMENT | ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE; command.header.channelID = channelID; - command.header.flags = ENET_PROTOCOL_FLAG_ACKNOWLEDGE; - command.header.commandLength = sizeof (ENetProtocolSendFragment); command.sendFragment.startSequenceNumber = startSequenceNumber; + command.sendFragment.dataLength = ENET_HOST_TO_NET_16 (fragmentLength); command.sendFragment.fragmentCount = fragmentCount; command.sendFragment.fragmentNumber = ENET_HOST_TO_NET_32 (fragmentNumber); command.sendFragment.totalLength = ENET_HOST_TO_NET_32 (packet -> dataLength); command.sendFragment.fragmentOffset = ENET_NET_TO_HOST_32 (fragmentOffset); - if (packet -> dataLength - fragmentOffset < fragmentLength) - fragmentLength = packet -> dataLength - fragmentOffset; - enet_peer_queue_outgoing_command (peer, & command, packet, fragmentOffset, fragmentLength); } @@ -149,24 +146,21 @@ enet_peer_send (ENetPeer * peer, enet_uint8 channelID, ENetPacket * packet) if (packet -> flags & ENET_PACKET_FLAG_RELIABLE) { - command.header.command = ENET_PROTOCOL_COMMAND_SEND_RELIABLE; - command.header.flags = ENET_PROTOCOL_FLAG_ACKNOWLEDGE; - command.header.commandLength = sizeof (ENetProtocolSendReliable); + command.header.command = ENET_PROTOCOL_COMMAND_SEND_RELIABLE | ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE; + command.sendReliable.dataLength = ENET_HOST_TO_NET_16 (packet -> dataLength); } else if (packet -> flags & ENET_PACKET_FLAG_UNSEQUENCED) { - command.header.command = ENET_PROTOCOL_COMMAND_SEND_UNSEQUENCED; - command.header.flags = ENET_PROTOCOL_FLAG_UNSEQUENCED; - command.header.commandLength = sizeof (ENetProtocolSendUnsequenced); - command.sendUnsequenced.unsequencedGroup = ENET_HOST_TO_NET_32 (peer -> outgoingUnsequencedGroup + 1); + command.header.command = ENET_PROTOCOL_COMMAND_SEND_UNSEQUENCED | ENET_PROTOCOL_COMMAND_FLAG_UNSEQUENCED; + command.sendUnsequenced.unsequencedGroup = ENET_HOST_TO_NET_16 (peer -> outgoingUnsequencedGroup + 1); + command.sendUnsequenced.dataLength = ENET_HOST_TO_NET_16 (packet -> dataLength); } else { command.header.command = ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE; - command.header.flags = 0; - command.header.commandLength = sizeof (ENetProtocolSendUnreliable); - command.sendUnreliable.unreliableSequenceNumber = ENET_HOST_TO_NET_32 (channel -> outgoingUnreliableSequenceNumber + 1); + command.sendUnreliable.unreliableSequenceNumber = ENET_HOST_TO_NET_16 (channel -> outgoingUnreliableSequenceNumber + 1); + command.sendUnreliable.dataLength = ENET_HOST_TO_NET_16 (packet -> dataLength); } enet_peer_queue_outgoing_command (peer, & command, packet, 0, packet -> dataLength); @@ -186,13 +180,13 @@ enet_peer_receive (ENetPeer * peer, enet_uint8 channelID) ENetIncomingCommand * incomingCommand = NULL; ENetPacket * packet; - if (enet_list_empty (& channel -> incomingUnreliableCommands) == 0) + if (! enet_list_empty (& channel -> incomingUnreliableCommands)) { incomingCommand = (ENetIncomingCommand *) enet_list_front (& channel -> incomingUnreliableCommands); - if (incomingCommand -> unreliableSequenceNumber > 0) + if ((incomingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_MASK) == ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE) { - if (incomingCommand -> reliableSequenceNumber > channel -> incomingReliableSequenceNumber) + if (incomingCommand -> reliableSequenceNumber != channel -> incomingReliableSequenceNumber) incomingCommand = NULL; else channel -> incomingUnreliableSequenceNumber = incomingCommand -> unreliableSequenceNumber; @@ -200,36 +194,12 @@ enet_peer_receive (ENetPeer * peer, enet_uint8 channelID) } if (incomingCommand == NULL && - enet_list_empty (& channel -> incomingReliableCommands) == 0) + ! enet_list_empty (& channel -> incomingReliableCommands)) { - do - { - incomingCommand = (ENetIncomingCommand *) enet_list_front (& channel -> incomingReliableCommands); + incomingCommand = (ENetIncomingCommand *) enet_list_front (& channel -> incomingReliableCommands); - if (incomingCommand -> fragmentsRemaining > 0 || - incomingCommand -> reliableSequenceNumber > channel -> incomingReliableSequenceNumber + 1) - return NULL; - - if (incomingCommand -> reliableSequenceNumber <= channel -> incomingReliableSequenceNumber) - { - -- incomingCommand -> packet -> referenceCount; - - if (incomingCommand -> packet -> referenceCount == 0) - enet_packet_destroy (incomingCommand -> packet); - - if (incomingCommand -> fragments != NULL) - enet_free (incomingCommand -> fragments); - - enet_list_remove (& incomingCommand -> incomingCommandList); - - enet_free (incomingCommand); - - incomingCommand = NULL; - } - } while (incomingCommand == NULL && - enet_list_empty (& channel -> incomingReliableCommands) == 0); - - if (incomingCommand == NULL) + if (incomingCommand -> fragmentsRemaining > 0 || + incomingCommand -> reliableSequenceNumber != channel -> incomingReliableSequenceNumber + 1) return NULL; channel -> incomingReliableSequenceNumber = incomingCommand -> reliableSequenceNumber; @@ -260,7 +230,7 @@ enet_peer_reset_outgoing_commands (ENetList * queue) { ENetOutgoingCommand * outgoingCommand; - while (enet_list_empty (queue) == 0) + while (! enet_list_empty (queue)) { outgoingCommand = (ENetOutgoingCommand *) enet_list_remove (enet_list_begin (queue)); @@ -281,7 +251,7 @@ enet_peer_reset_incoming_commands (ENetList * queue) { ENetIncomingCommand * incomingCommand; - while (enet_list_empty (queue) == 0) + while (! enet_list_empty (queue)) { incomingCommand = (ENetIncomingCommand *) enet_list_remove (enet_list_begin (queue)); @@ -305,7 +275,7 @@ enet_peer_reset_queues (ENetPeer * peer) { ENetChannel * channel; - while (enet_list_empty (& peer -> acknowledgements) == 0) + while (! enet_list_empty (& peer -> acknowledgements)) enet_free (enet_list_remove (enet_list_begin (& peer -> acknowledgements))); enet_peer_reset_outgoing_commands (& peer -> sentReliableCommands); @@ -338,8 +308,8 @@ enet_peer_reset_queues (ENetPeer * peer) void enet_peer_reset (ENetPeer * peer) { - peer -> outgoingPeerID = 0xFFFF; - peer -> challenge = 0; + peer -> outgoingPeerID = ENET_PROTOCOL_MAXIMUM_PEER_ID; + peer -> sessionID = 0; peer -> address.host = ENET_HOST_ANY; peer -> address.port = 0; @@ -402,10 +372,8 @@ enet_peer_ping (ENetPeer * peer) if (peer -> state != ENET_PEER_STATE_CONNECTED) return; - command.header.command = ENET_PROTOCOL_COMMAND_PING; + command.header.command = ENET_PROTOCOL_COMMAND_PING | ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE; command.header.channelID = 0xFF; - command.header.flags = ENET_PROTOCOL_FLAG_ACKNOWLEDGE; - command.header.commandLength = sizeof (ENetProtocolPing); enet_peer_queue_outgoing_command (peer, & command, NULL, 0, 0); } @@ -430,11 +398,9 @@ enet_peer_disconnect_now (ENetPeer * peer, enet_uint32 data) { enet_peer_reset_queues (peer); - command.header.command = ENET_PROTOCOL_COMMAND_DISCONNECT; + command.header.command = ENET_PROTOCOL_COMMAND_DISCONNECT | ENET_PROTOCOL_COMMAND_FLAG_UNSEQUENCED; command.header.channelID = 0xFF; - command.header.flags = ENET_PROTOCOL_FLAG_UNSEQUENCED; - command.header.commandLength = sizeof (ENetProtocolDisconnect); - command.disconnect.data = data; + command.disconnect.data = ENET_HOST_TO_NET_32 (data); enet_peer_queue_outgoing_command (peer, & command, NULL, 0, 0); @@ -464,16 +430,16 @@ enet_peer_disconnect (ENetPeer * peer, enet_uint32 data) command.header.command = ENET_PROTOCOL_COMMAND_DISCONNECT; command.header.channelID = 0xFF; - command.header.flags = ENET_PROTOCOL_FLAG_UNSEQUENCED; - command.header.commandLength = sizeof (ENetProtocolDisconnect); - command.disconnect.data = data; + command.disconnect.data = ENET_HOST_TO_NET_32 (data); - if (peer -> state == ENET_PEER_STATE_CONNECTED) - command.header.flags = ENET_PROTOCOL_FLAG_ACKNOWLEDGE; + if (peer -> state == ENET_PEER_STATE_CONNECTED || peer -> state == ENET_PEER_STATE_DISCONNECT_LATER) + command.header.command |= ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE; + else + command.header.command |= ENET_PROTOCOL_COMMAND_FLAG_UNSEQUENCED; enet_peer_queue_outgoing_command (peer, & command, NULL, 0, 0); - if (peer -> state == ENET_PEER_STATE_CONNECTED) + if (peer -> state == ENET_PEER_STATE_CONNECTED || peer -> state == ENET_PEER_STATE_DISCONNECT_LATER) peer -> state = ENET_PEER_STATE_DISCONNECTING; else { @@ -482,8 +448,29 @@ enet_peer_disconnect (ENetPeer * peer, enet_uint32 data) } } +/** Request a disconnection from a peer, but only after all queued outgoing packets are sent. + @param peer peer to request a disconnection + @param data data describing the disconnection + @remarks An ENET_EVENT_DISCONNECT event will be generated by enet_host_service() + once the disconnection is complete. +*/ +void +enet_peer_disconnect_later (ENetPeer * peer, enet_uint32 data) +{ + if ((peer -> state == ENET_PEER_STATE_CONNECTED || peer -> state == ENET_PEER_STATE_DISCONNECT_LATER) && + ! (enet_list_empty (& peer -> outgoingReliableCommands) && + enet_list_empty (& peer -> outgoingUnreliableCommands) && + enet_list_empty (& peer -> sentReliableCommands))) + { + peer -> state = ENET_PEER_STATE_DISCONNECT_LATER; + peer -> disconnectData = data; + } + else + enet_peer_disconnect (peer, data); +} + ENetAcknowledgement * -enet_peer_queue_acknowledgement (ENetPeer * peer, const ENetProtocol * command, enet_uint32 sentTime) +enet_peer_queue_acknowledgement (ENetPeer * peer, const ENetProtocol * command, enet_uint16 sentTime) { ENetAcknowledgement * acknowledgement; @@ -505,7 +492,7 @@ enet_peer_queue_outgoing_command (ENetPeer * peer, const ENetProtocol * command, ENetChannel * channel = & peer -> channels [command -> header.channelID]; ENetOutgoingCommand * outgoingCommand; - peer -> outgoingDataTotal += command -> header.commandLength + length; + peer -> outgoingDataTotal += enet_protocol_command_size (command -> header.command) + length; outgoingCommand = (ENetOutgoingCommand *) enet_malloc (sizeof (ENetOutgoingCommand)); @@ -517,7 +504,7 @@ enet_peer_queue_outgoing_command (ENetPeer * peer, const ENetProtocol * command, outgoingCommand -> unreliableSequenceNumber = 0; } else - if (command -> header.flags & ENET_PROTOCOL_FLAG_ACKNOWLEDGE) + if (command -> header.command & ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE) { ++ channel -> outgoingReliableSequenceNumber; @@ -525,7 +512,7 @@ enet_peer_queue_outgoing_command (ENetPeer * peer, const ENetProtocol * command, outgoingCommand -> unreliableSequenceNumber = 0; } else - if (command -> header.flags & ENET_PROTOCOL_FLAG_UNSEQUENCED) + if (command -> header.command & ENET_PROTOCOL_COMMAND_FLAG_UNSEQUENCED) { ++ peer -> outgoingUnsequencedGroup; @@ -547,12 +534,12 @@ enet_peer_queue_outgoing_command (ENetPeer * peer, const ENetProtocol * command, outgoingCommand -> fragmentLength = length; outgoingCommand -> packet = packet; outgoingCommand -> command = * command; - outgoingCommand -> command.header.reliableSequenceNumber = ENET_HOST_TO_NET_32 (outgoingCommand -> reliableSequenceNumber); + outgoingCommand -> command.header.reliableSequenceNumber = ENET_HOST_TO_NET_16 (outgoingCommand -> reliableSequenceNumber); if (packet != NULL) ++ packet -> referenceCount; - if (command -> header.flags & ENET_PROTOCOL_FLAG_ACKNOWLEDGE) + if (command -> header.command & ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE) enet_list_insert (enet_list_end (& peer -> outgoingReliableCommands), outgoingCommand); else enet_list_insert (enet_list_end (& peer -> outgoingUnreliableCommands), outgoingCommand); @@ -564,23 +551,44 @@ ENetIncomingCommand * enet_peer_queue_incoming_command (ENetPeer * peer, const ENetProtocol * command, ENetPacket * packet, enet_uint32 fragmentCount) { ENetChannel * channel = & peer -> channels [command -> header.channelID]; - enet_uint32 unreliableSequenceNumber = 0; + enet_uint32 unreliableSequenceNumber = 0, reliableSequenceNumber; ENetIncomingCommand * incomingCommand; ENetListIterator currentCommand; - switch (command -> header.command) + if (peer -> state == ENET_PEER_STATE_DISCONNECT_LATER) + goto freePacket; + + if ((command -> header.command & ENET_PROTOCOL_COMMAND_MASK) != ENET_PROTOCOL_COMMAND_SEND_UNSEQUENCED) + { + reliableSequenceNumber = command -> header.reliableSequenceNumber; + + if (channel -> incomingReliableSequenceNumber >= 0xF000 && reliableSequenceNumber < 0x1000) + reliableSequenceNumber += 0x10000; + + if (reliableSequenceNumber < channel -> incomingReliableSequenceNumber || + (channel -> incomingReliableSequenceNumber < 0x1000 && (reliableSequenceNumber & 0xFFFF) >= 0xF000)) + goto freePacket; + } + + switch (command -> header.command & ENET_PROTOCOL_COMMAND_MASK) { case ENET_PROTOCOL_COMMAND_SEND_FRAGMENT: case ENET_PROTOCOL_COMMAND_SEND_RELIABLE: + if (reliableSequenceNumber == channel -> incomingReliableSequenceNumber) + goto freePacket; + for (currentCommand = enet_list_previous (enet_list_end (& channel -> incomingReliableCommands)); currentCommand != enet_list_end (& channel -> incomingReliableCommands); currentCommand = enet_list_previous (currentCommand)) { incomingCommand = (ENetIncomingCommand *) currentCommand; - if (incomingCommand -> reliableSequenceNumber <= command -> header.reliableSequenceNumber) + if (reliableSequenceNumber >= 0x10000 && incomingCommand -> reliableSequenceNumber < 0xF000) + reliableSequenceNumber -= 0x10000; + + if (incomingCommand -> reliableSequenceNumber <= reliableSequenceNumber) { - if (incomingCommand -> reliableSequenceNumber < command -> header.reliableSequenceNumber) + if (incomingCommand -> reliableSequenceNumber < reliableSequenceNumber) break; goto freePacket; @@ -589,12 +597,13 @@ enet_peer_queue_incoming_command (ENetPeer * peer, const ENetProtocol * command, break; case ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE: - unreliableSequenceNumber = ENET_NET_TO_HOST_32 (command -> sendUnreliable.unreliableSequenceNumber); + unreliableSequenceNumber = ENET_NET_TO_HOST_16 (command -> sendUnreliable.unreliableSequenceNumber); - if (command -> header.reliableSequenceNumber < channel -> incomingReliableSequenceNumber) - goto freePacket; - - if (unreliableSequenceNumber <= channel -> incomingUnreliableSequenceNumber) + if (channel -> incomingUnreliableSequenceNumber >= 0xF000 && unreliableSequenceNumber < 0x1000) + unreliableSequenceNumber += 0x10000; + + if (unreliableSequenceNumber <= channel -> incomingUnreliableSequenceNumber || + (channel -> incomingUnreliableSequenceNumber < 0x1000 && (unreliableSequenceNumber & 0xFFFF) >= 0xF000)) goto freePacket; for (currentCommand = enet_list_previous (enet_list_end (& channel -> incomingUnreliableCommands)); @@ -603,6 +612,12 @@ enet_peer_queue_incoming_command (ENetPeer * peer, const ENetProtocol * command, { incomingCommand = (ENetIncomingCommand *) currentCommand; + if ((incomingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_MASK) != ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE) + continue; + + if (unreliableSequenceNumber >= 0x10000 && incomingCommand -> unreliableSequenceNumber < 0xF000) + unreliableSequenceNumber -= 0x10000; + if (incomingCommand -> unreliableSequenceNumber <= unreliableSequenceNumber) { if (incomingCommand -> unreliableSequenceNumber < unreliableSequenceNumber) @@ -624,7 +639,7 @@ enet_peer_queue_incoming_command (ENetPeer * peer, const ENetProtocol * command, incomingCommand = (ENetIncomingCommand *) enet_malloc (sizeof (ENetIncomingCommand)); incomingCommand -> reliableSequenceNumber = command -> header.reliableSequenceNumber; - incomingCommand -> unreliableSequenceNumber = unreliableSequenceNumber; + incomingCommand -> unreliableSequenceNumber = unreliableSequenceNumber & 0xFFFF; incomingCommand -> command = * command; incomingCommand -> fragmentCount = fragmentCount; incomingCommand -> fragmentsRemaining = fragmentCount; diff --git a/protocol.c b/protocol.c index e6263eb..5684dc8 100644 --- a/protocol.c +++ b/protocol.c @@ -11,6 +11,28 @@ static enet_uint32 timeCurrent; +static size_t commandSizes [ENET_PROTOCOL_COMMAND_COUNT] = +{ + 0, + sizeof (ENetProtocolAcknowledge), + sizeof (ENetProtocolConnect), + sizeof (ENetProtocolVerifyConnect), + sizeof (ENetProtocolDisconnect), + sizeof (ENetProtocolPing), + sizeof (ENetProtocolSendReliable), + sizeof (ENetProtocolSendUnreliable), + sizeof (ENetProtocolSendFragment), + sizeof (ENetProtocolSendUnsequenced), + sizeof (ENetProtocolBandwidthLimit), + sizeof (ENetProtocolThrottleConfigure), +}; + +size_t +enet_protocol_command_size (enet_uint8 commandNumber) +{ + return commandSizes [commandNumber & ENET_PROTOCOL_COMMAND_MASK]; +} + static int enet_protocol_dispatch_incoming_commands (ENetHost * host, ENetEvent * event) { @@ -27,6 +49,7 @@ enet_protocol_dispatch_incoming_commands (ENetHost * host, ENetEvent * event) switch (currentPeer -> state) { case ENET_PEER_STATE_CONNECTION_PENDING: + case ENET_PEER_STATE_CONNECTION_SUCCEEDED: currentPeer -> state = ENET_PEER_STATE_CONNECTED; event -> type = ENET_EVENT_TYPE_CONNECT; @@ -82,7 +105,7 @@ enet_protocol_notify_connect (ENetHost * host, ENetPeer * peer, ENetEvent * even host -> recalculateBandwidthLimits = 1; if (event == NULL) - peer -> state = ENET_PEER_STATE_CONNECTION_PENDING; + peer -> state = (peer -> state == ENET_PEER_STATE_CONNECTING ? ENET_PEER_STATE_CONNECTION_SUCCEEDED : ENET_PEER_STATE_CONNECTION_PENDING); else { peer -> state = ENET_PEER_STATE_CONNECTED; @@ -98,7 +121,7 @@ enet_protocol_notify_disconnect (ENetHost * host, ENetPeer * peer, ENetEvent * e if (peer -> state >= ENET_PEER_STATE_CONNECTION_PENDING) host -> recalculateBandwidthLimits = 1; - if (peer -> state < ENET_PEER_STATE_CONNECTED) + if (peer -> state < ENET_PEER_STATE_CONNECTION_SUCCEEDED) enet_peer_reset (peer); else if (event == NULL) @@ -118,7 +141,7 @@ enet_protocol_remove_sent_unreliable_commands (ENetPeer * peer) { ENetOutgoingCommand * outgoingCommand; - while (enet_list_empty (& peer -> sentUnreliableCommands) == 0) + while (! enet_list_empty (& peer -> sentUnreliableCommands)) { outgoingCommand = (ENetOutgoingCommand *) enet_list_front (& peer -> sentUnreliableCommands); @@ -137,7 +160,7 @@ enet_protocol_remove_sent_unreliable_commands (ENetPeer * peer) } static ENetProtocolCommand -enet_protocol_remove_sent_reliable_command (ENetPeer * peer, enet_uint32 reliableSequenceNumber, enet_uint8 channelID) +enet_protocol_remove_sent_reliable_command (ENetPeer * peer, enet_uint16 reliableSequenceNumber, enet_uint8 channelID) { ENetOutgoingCommand * outgoingCommand; ENetListIterator currentCommand; @@ -157,7 +180,7 @@ enet_protocol_remove_sent_reliable_command (ENetPeer * peer, enet_uint32 reliabl if (currentCommand == enet_list_end (& peer -> sentReliableCommands)) return ENET_PROTOCOL_COMMAND_NONE; - commandNumber = outgoingCommand -> command.header.command; + commandNumber = outgoingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_MASK; enet_list_remove (& outgoingCommand -> outgoingCommandList); @@ -184,7 +207,7 @@ enet_protocol_remove_sent_reliable_command (ENetPeer * peer, enet_uint32 reliabl } static ENetPeer * -enet_protocol_handle_connect (ENetHost * host, const ENetProtocolHeader * header, const ENetProtocol * command) +enet_protocol_handle_connect (ENetHost * host, ENetProtocolHeader * header, ENetProtocol * command) { enet_uint16 mtu; enet_uint32 windowSize; @@ -193,9 +216,25 @@ enet_protocol_handle_connect (ENetHost * host, const ENetProtocolHeader * header ENetPeer * currentPeer; ENetProtocol verifyCommand; - if (command -> header.commandLength < sizeof (ENetProtocolConnect)) - return NULL; +#ifdef USE_CRC32 + { + enet_uint32 crc = header -> checksum; + ENetBuffer buffer; + command -> header.reliableSequenceNumber = ENET_HOST_TO_NET_16 (command -> header.reliableSequenceNumber); + + header -> checksum = command -> connect.sessionID; + + buffer.data = host -> receivedData; + buffer.dataLength = host -> receivedDataLength; + + if (enet_crc32 (& buffer, 1) != crc) + return NULL; + + command -> header.reliableSequenceNumber = ENET_NET_TO_HOST_16 (command -> header.reliableSequenceNumber); + } +#endif + channelCount = ENET_NET_TO_HOST_32 (command -> connect.channelCount); if (channelCount < ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT || @@ -209,7 +248,7 @@ enet_protocol_handle_connect (ENetHost * host, const ENetProtocolHeader * header if (currentPeer -> state != ENET_PEER_STATE_DISCONNECTED && currentPeer -> address.host == host -> receivedAddress.host && currentPeer -> address.port == host -> receivedAddress.port && - currentPeer -> challenge == header -> challenge) + currentPeer -> sessionID == command -> connect.sessionID) return NULL; } @@ -225,7 +264,7 @@ enet_protocol_handle_connect (ENetHost * host, const ENetProtocolHeader * header return NULL; currentPeer -> state = ENET_PEER_STATE_ACKNOWLEDGING_CONNECT; - currentPeer -> challenge = header -> challenge; + currentPeer -> sessionID = command -> connect.sessionID; currentPeer -> address = host -> receivedAddress; currentPeer -> outgoingPeerID = ENET_NET_TO_HOST_16 (command -> connect.outgoingPeerID); currentPeer -> incomingBandwidth = ENET_NET_TO_HOST_32 (command -> connect.incomingBandwidth); @@ -288,10 +327,8 @@ enet_protocol_handle_connect (ENetHost * host, const ENetProtocolHeader * header if (windowSize > ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE) windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE; - verifyCommand.header.command = ENET_PROTOCOL_COMMAND_VERIFY_CONNECT; + verifyCommand.header.command = ENET_PROTOCOL_COMMAND_VERIFY_CONNECT | ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE; verifyCommand.header.channelID = 0xFF; - verifyCommand.header.flags = ENET_PROTOCOL_FLAG_ACKNOWLEDGE; - verifyCommand.header.commandLength = sizeof (ENetProtocolVerifyConnect); verifyCommand.verifyConnect.outgoingPeerID = ENET_HOST_TO_NET_16 (currentPeer -> incomingPeerID); verifyCommand.verifyConnect.mtu = ENET_HOST_TO_NET_16 (currentPeer -> mtu); verifyCommand.verifyConnect.windowSize = ENET_HOST_TO_NET_32 (windowSize); @@ -307,38 +344,50 @@ enet_protocol_handle_connect (ENetHost * host, const ENetProtocolHeader * header return currentPeer; } -static void -enet_protocol_handle_send_reliable (ENetHost * host, ENetPeer * peer, const ENetProtocol * command) +static int +enet_protocol_handle_send_reliable (ENetHost * host, ENetPeer * peer, const ENetProtocol * command, enet_uint8 ** currentData) { ENetPacket * packet; + size_t dataLength; - if (command -> header.commandLength <= sizeof (ENetProtocolSendReliable) || - command -> header.channelID >= peer -> channelCount || - peer -> state != ENET_PEER_STATE_CONNECTED) - return; + if (command -> header.channelID >= peer -> channelCount || + (peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER)) + return -1; + + dataLength = ENET_NET_TO_HOST_16 (command -> sendReliable.dataLength); + * currentData += dataLength; + if (* currentData > & host -> receivedData [host -> receivedDataLength]) + return -1; packet = enet_packet_create ((const enet_uint8 *) command + sizeof (ENetProtocolSendReliable), - command -> header.commandLength - sizeof (ENetProtocolSendReliable), + dataLength, ENET_PACKET_FLAG_RELIABLE); enet_peer_queue_incoming_command (peer, command, packet, 0); + return 0; } -static void -enet_protocol_handle_send_unsequenced (ENetHost * host, ENetPeer * peer, const ENetProtocol * command) +static int +enet_protocol_handle_send_unsequenced (ENetHost * host, ENetPeer * peer, const ENetProtocol * command, enet_uint8 ** currentData) { ENetPacket * packet; enet_uint32 unsequencedGroup, index; + size_t dataLength; - if (command -> header.commandLength <= sizeof (ENetProtocolSendUnsequenced) || - command -> header.channelID >= peer -> channelCount || - peer -> state != ENET_PEER_STATE_CONNECTED) - return; + if (command -> header.channelID >= peer -> channelCount || + (peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER)) + return -1; - unsequencedGroup = ENET_NET_TO_HOST_32 (command -> sendUnsequenced.unsequencedGroup); + dataLength = ENET_NET_TO_HOST_16 (command -> sendUnsequenced.dataLength); + * currentData += dataLength; + if (* currentData > & host -> receivedData [host -> receivedDataLength]) + return -1; + + unsequencedGroup = ENET_NET_TO_HOST_16 (command -> sendUnsequenced.unsequencedGroup); index = unsequencedGroup % ENET_PEER_UNSEQUENCED_WINDOW_SIZE; - if (unsequencedGroup >= peer -> incomingUnsequencedGroup + ENET_PEER_UNSEQUENCED_WINDOW_SIZE) + if (unsequencedGroup >= peer -> incomingUnsequencedGroup + ENET_PEER_UNSEQUENCED_WINDOW_SIZE || + peer -> incomingUnsequencedGroup >= 0xF000 && unsequencedGroup < 0x1000) { peer -> incomingUnsequencedGroup = unsequencedGroup - index; @@ -347,37 +396,44 @@ enet_protocol_handle_send_unsequenced (ENetHost * host, ENetPeer * peer, const E else if (unsequencedGroup < peer -> incomingUnsequencedGroup || peer -> unsequencedWindow [index / 32] & (1 << (index % 32))) - return; + return 0; peer -> unsequencedWindow [index / 32] |= 1 << (index % 32); packet = enet_packet_create ((const enet_uint8 *) command + sizeof (ENetProtocolSendUnsequenced), - command -> header.commandLength - sizeof (ENetProtocolSendUnsequenced), + dataLength, ENET_PACKET_FLAG_UNSEQUENCED); enet_peer_queue_incoming_command (peer, command, packet, 0); + return 0; } -static void -enet_protocol_handle_send_unreliable (ENetHost * host, ENetPeer * peer, const ENetProtocol * command) +static int +enet_protocol_handle_send_unreliable (ENetHost * host, ENetPeer * peer, const ENetProtocol * command, enet_uint8 ** currentData) { ENetPacket * packet; + size_t dataLength; - if (command -> header.commandLength <= sizeof (ENetProtocolSendUnreliable) || - command -> header.channelID >= peer -> channelCount || - peer -> state != ENET_PEER_STATE_CONNECTED) - return; + if (command -> header.channelID >= peer -> channelCount || + (peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER)) + return -1; + + dataLength = ENET_NET_TO_HOST_16 (command -> sendUnreliable.dataLength); + * currentData += dataLength; + if (* currentData > & host -> receivedData [host -> receivedDataLength]) + return -1; packet = enet_packet_create ((const enet_uint8 *) command + sizeof (ENetProtocolSendUnreliable), - command -> header.commandLength - sizeof (ENetProtocolSendUnreliable), + dataLength, 0); enet_peer_queue_incoming_command (peer, command, packet, 0); + return 0; } -static void -enet_protocol_handle_send_fragment (ENetHost * host, ENetPeer * peer, const ENetProtocol * command) +static int +enet_protocol_handle_send_fragment (ENetHost * host, ENetPeer * peer, const ENetProtocol * command, enet_uint8 ** currentData) { enet_uint32 fragmentNumber, fragmentCount, @@ -389,36 +445,42 @@ enet_protocol_handle_send_fragment (ENetHost * host, ENetPeer * peer, const ENet ENetListIterator currentCommand; ENetIncomingCommand * startCommand; - if (command -> header.commandLength <= sizeof (ENetProtocolSendFragment) || - command -> header.channelID >= peer -> channelCount || - peer -> state != ENET_PEER_STATE_CONNECTED) - return; + if (command -> header.channelID >= peer -> channelCount || + (peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER)) + return -1; + + fragmentLength = ENET_NET_TO_HOST_16 (command -> sendFragment.dataLength); + * currentData += fragmentLength; + if (* currentData > & host -> receivedData [host -> receivedDataLength]) + return -1; + + channel = & peer -> channels [command -> header.channelID]; + startSequenceNumber = ENET_NET_TO_HOST_16 (command -> sendFragment.startSequenceNumber); + if (channel -> incomingReliableSequenceNumber >= 0xF000 && startSequenceNumber < 0x1000) + startSequenceNumber += 0x10000; + + if (startSequenceNumber < channel -> incomingReliableSequenceNumber || + (channel -> incomingReliableSequenceNumber < 0x1000 && (startSequenceNumber & 0xFFFF) >= 0xF000)) + return 0; - startSequenceNumber = ENET_NET_TO_HOST_32 (command -> sendFragment.startSequenceNumber); fragmentNumber = ENET_NET_TO_HOST_32 (command -> sendFragment.fragmentNumber); fragmentCount = ENET_NET_TO_HOST_32 (command -> sendFragment.fragmentCount); fragmentOffset = ENET_NET_TO_HOST_32 (command -> sendFragment.fragmentOffset); totalLength = ENET_NET_TO_HOST_32 (command -> sendFragment.totalLength); - fragmentLength = command -> header.commandLength - sizeof (ENetProtocolSendFragment); if (fragmentOffset >= totalLength || fragmentOffset + fragmentLength > totalLength || fragmentNumber >= fragmentCount) - return; + return -1; - channel = & peer -> channels [command -> header.channelID]; - - if (startSequenceNumber <= channel -> incomingReliableSequenceNumber) - return; - for (currentCommand = enet_list_previous (enet_list_end (& channel -> incomingReliableCommands)); currentCommand != enet_list_end (& channel -> incomingReliableCommands); currentCommand = enet_list_previous (currentCommand)) { startCommand = (ENetIncomingCommand *) currentCommand; - if (startCommand -> command.header.command == ENET_PROTOCOL_COMMAND_SEND_FRAGMENT && - startCommand -> command.sendFragment.startSequenceNumber == startSequenceNumber) + if ((startCommand -> command.header.command & ENET_PROTOCOL_COMMAND_MASK) == ENET_PROTOCOL_COMMAND_SEND_FRAGMENT && + startCommand -> command.sendFragment.startSequenceNumber == (startSequenceNumber & 0xFFFF)) break; } @@ -428,6 +490,7 @@ enet_protocol_handle_send_fragment (ENetHost * host, ENetPeer * peer, const ENet hostCommand.header.reliableSequenceNumber = startSequenceNumber; hostCommand.sendFragment.startSequenceNumber = startSequenceNumber; + hostCommand.sendFragment.dataLength = fragmentLength; hostCommand.sendFragment.fragmentNumber = fragmentNumber; hostCommand.sendFragment.fragmentCount = fragmentCount; hostCommand.sendFragment.fragmentOffset = fragmentOffset; @@ -441,7 +504,7 @@ enet_protocol_handle_send_fragment (ENetHost * host, ENetPeer * peer, const ENet else if (totalLength != startCommand -> packet -> dataLength || fragmentCount != startCommand -> fragmentCount) - return; + return -1; if ((startCommand -> fragments [fragmentNumber / 32] & (1 << (fragmentNumber % 32))) == 0) { @@ -456,26 +519,23 @@ enet_protocol_handle_send_fragment (ENetHost * host, ENetPeer * peer, const ENet (enet_uint8 *) command + sizeof (ENetProtocolSendFragment), fragmentLength); } + + return 0; } -static void +static int enet_protocol_handle_ping (ENetHost * host, ENetPeer * peer, const ENetProtocol * command) { - if (command -> header.commandLength < sizeof (ENetProtocolPing)) - return; + return 0; } -static void +static int enet_protocol_handle_bandwidth_limit (ENetHost * host, ENetPeer * peer, const ENetProtocol * command) { - if (command -> header.commandLength < sizeof (ENetProtocolBandwidthLimit)) - return; - peer -> incomingBandwidth = ENET_NET_TO_HOST_32 (command -> bandwidthLimit.incomingBandwidth); peer -> outgoingBandwidth = ENET_NET_TO_HOST_32 (command -> bandwidthLimit.outgoingBandwidth); - if (peer -> incomingBandwidth == 0 && - host -> outgoingBandwidth == 0) + if (peer -> incomingBandwidth == 0 && host -> outgoingBandwidth == 0) peer -> windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE; else peer -> windowSize = (ENET_MIN (peer -> incomingBandwidth, host -> outgoingBandwidth) / @@ -486,40 +546,42 @@ enet_protocol_handle_bandwidth_limit (ENetHost * host, ENetPeer * peer, const EN else if (peer -> windowSize > ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE) peer -> windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE; + + return 0; } -static void +static int enet_protocol_handle_throttle_configure (ENetHost * host, ENetPeer * peer, const ENetProtocol * command) { - if (command -> header.commandLength < sizeof (ENetProtocolThrottleConfigure)) - return; - peer -> packetThrottleInterval = ENET_NET_TO_HOST_32 (command -> throttleConfigure.packetThrottleInterval); peer -> packetThrottleAcceleration = ENET_NET_TO_HOST_32 (command -> throttleConfigure.packetThrottleAcceleration); peer -> packetThrottleDeceleration = ENET_NET_TO_HOST_32 (command -> throttleConfigure.packetThrottleDeceleration); + + return 0; } -static void +static int enet_protocol_handle_disconnect (ENetHost * host, ENetPeer * peer, const ENetProtocol * command) { - if (command -> header.commandLength < sizeof (ENetProtocolDisconnect)) - return; - enet_peer_reset_queues (peer); - if (peer -> state != ENET_PEER_STATE_CONNECTED) + if (peer -> state == ENET_PEER_STATE_CONNECTION_SUCCEEDED) + peer -> state = ENET_PEER_STATE_ZOMBIE; + else + if (peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER) { if (peer -> state == ENET_PEER_STATE_CONNECTION_PENDING) host -> recalculateBandwidthLimits = 1; enet_peer_reset (peer); } else - if (command -> header.flags & ENET_PROTOCOL_FLAG_ACKNOWLEDGE) + if (command -> header.command & ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE) peer -> state = ENET_PEER_STATE_ACKNOWLEDGING_DISCONNECT; else peer -> state = ENET_PEER_STATE_ZOMBIE; - peer -> disconnectData = command -> disconnect.data; + peer -> disconnectData = ENET_NET_TO_HOST_32 (command -> disconnect.data); + return 0; } static int @@ -530,10 +592,10 @@ enet_protocol_handle_acknowledge (ENetHost * host, ENetEvent * event, ENetPeer * receivedReliableSequenceNumber; ENetProtocolCommand commandNumber; - if (command -> header.commandLength < sizeof (ENetProtocolAcknowledge)) - return 0; - - receivedSentTime = ENET_NET_TO_HOST_32 (command -> acknowledge.receivedSentTime); + receivedSentTime = ENET_NET_TO_HOST_16 (command -> acknowledge.receivedSentTime); + receivedSentTime |= timeCurrent & 0xFFFF0000; + if ((receivedSentTime & 0x8000) > (timeCurrent & 0x8000)) + receivedSentTime -= 0x10000; if (ENET_TIME_LESS (timeCurrent, receivedSentTime)) return 0; @@ -574,7 +636,7 @@ enet_protocol_handle_acknowledge (ENetHost * host, ENetEvent * event, ENetPeer * peer -> packetThrottleEpoch = timeCurrent; } - receivedReliableSequenceNumber = ENET_NET_TO_HOST_32 (command -> acknowledge.receivedReliableSequenceNumber); + receivedReliableSequenceNumber = ENET_NET_TO_HOST_16 (command -> acknowledge.receivedReliableSequenceNumber); commandNumber = enet_protocol_remove_sent_reliable_command (peer, receivedReliableSequenceNumber, command -> header.channelID); @@ -582,34 +644,37 @@ enet_protocol_handle_acknowledge (ENetHost * host, ENetEvent * event, ENetPeer * { case ENET_PEER_STATE_ACKNOWLEDGING_CONNECT: if (commandNumber != ENET_PROTOCOL_COMMAND_VERIFY_CONNECT) - return 0; + return -1; enet_protocol_notify_connect (host, peer, event); - - return 1; + break; case ENET_PEER_STATE_DISCONNECTING: if (commandNumber != ENET_PROTOCOL_COMMAND_DISCONNECT) - return 0; + return -1; enet_protocol_notify_disconnect (host, peer, event); + break; - return 1; + case ENET_PEER_STATE_DISCONNECT_LATER: + if (enet_list_empty (& peer -> outgoingReliableCommands) && + enet_list_empty (& peer -> outgoingUnreliableCommands) && + enet_list_empty (& peer -> sentReliableCommands)) + enet_peer_disconnect (peer, peer -> disconnectData); + break; } return 0; } -static void +static int enet_protocol_handle_verify_connect (ENetHost * host, ENetEvent * event, ENetPeer * peer, const ENetProtocol * command) { enet_uint16 mtu; enet_uint32 windowSize; - if (event == NULL || - command -> header.commandLength < sizeof (ENetProtocolVerifyConnect) || - peer -> state != ENET_PEER_STATE_CONNECTING) - return; + if (peer -> state != ENET_PEER_STATE_CONNECTING) + return -1; if (ENET_NET_TO_HOST_32 (command -> verifyConnect.channelCount) != peer -> channelCount || ENET_NET_TO_HOST_32 (command -> verifyConnect.packetThrottleInterval) != peer -> packetThrottleInterval || @@ -618,9 +683,11 @@ enet_protocol_handle_verify_connect (ENetHost * host, ENetEvent * event, ENetPee { peer -> state = ENET_PEER_STATE_ZOMBIE; - return; + return -1; } + enet_protocol_remove_sent_reliable_command (peer, 1, 0xFF); + peer -> outgoingPeerID = ENET_NET_TO_HOST_16 (command -> verifyConnect.outgoingPeerID); mtu = ENET_NET_TO_HOST_16 (command -> verifyConnect.mtu); @@ -649,6 +716,7 @@ enet_protocol_handle_verify_connect (ENetHost * host, ENetEvent * event, ENetPee peer -> outgoingBandwidth = ENET_NET_TO_HOST_32 (command -> verifyConnect.outgoingBandwidth); enet_protocol_notify_connect (host, peer, event); + return 0; } static int @@ -658,135 +726,175 @@ enet_protocol_handle_incoming_commands (ENetHost * host, ENetEvent * event) ENetProtocol * command; ENetPeer * peer; enet_uint8 * currentData; - size_t commandCount; + size_t headerSize; + enet_uint16 peerID, flags; if (host -> receivedDataLength < sizeof (ENetProtocolHeader)) return 0; header = (ENetProtocolHeader *) host -> receivedData; - header -> peerID = ENET_NET_TO_HOST_16 (header -> peerID); - header -> sentTime = ENET_NET_TO_HOST_32 (header -> sentTime); + peerID = ENET_NET_TO_HOST_16 (header -> peerID); + flags = peerID & ENET_PROTOCOL_HEADER_FLAG_MASK; + peerID &= ~ ENET_PROTOCOL_HEADER_FLAG_MASK; - if (header -> peerID == 0xFFFF) + if (peerID == ENET_PROTOCOL_MAXIMUM_PEER_ID) peer = NULL; else - if (header -> peerID >= host -> peerCount) + if (peerID >= host -> peerCount) return 0; else { - peer = & host -> peers [header -> peerID]; + peer = & host -> peers [peerID]; if (peer -> state == ENET_PEER_STATE_DISCONNECTED || peer -> state == ENET_PEER_STATE_ZOMBIE || (host -> receivedAddress.host != peer -> address.host && - peer -> address.host != ENET_HOST_BROADCAST) || - header -> challenge != peer -> challenge) + peer -> address.host != ENET_HOST_BROADCAST)) return 0; - else + +#ifdef USE_CRC32 { - peer -> address.host = host -> receivedAddress.host; - peer -> address.port = host -> receivedAddress.port; + enet_uint32 crc = header -> checksum; + ENetBuffer buffer; + + header -> checksum = peer -> sessionID; + + buffer.data = host -> receivedData; + buffer.dataLength = host -> receivedDataLength; + + if (enet_crc32 (& buffer, 1) != crc) + return 0; } +#else + if (header -> checksum != peer -> sessionID) + return 0; +#endif + + peer -> address.host = host -> receivedAddress.host; + peer -> address.port = host -> receivedAddress.port; + peer -> incomingDataTotal += host -> receivedDataLength; } - - if (peer != NULL) - peer -> incomingDataTotal += host -> receivedDataLength; - - commandCount = header -> commandCount; - currentData = host -> receivedData + sizeof (ENetProtocolHeader); + + headerSize = (flags & ENET_PROTOCOL_HEADER_FLAG_SENT_TIME ? sizeof (ENetProtocolHeader) : (size_t) & ((ENetProtocolHeader *) 0) -> sentTime); + currentData = host -> receivedData + headerSize; - while (commandCount > 0 && - currentData < & host -> receivedData [host -> receivedDataLength]) + while (currentData < & host -> receivedData [host -> receivedDataLength]) { + enet_uint8 commandNumber; + size_t commandSize; + command = (ENetProtocol *) currentData; if (currentData + sizeof (ENetProtocolCommandHeader) > & host -> receivedData [host -> receivedDataLength]) break; - command -> header.commandLength = ENET_NET_TO_HOST_32 (command -> header.commandLength); - - if (command -> header.commandLength <= 0 || - command -> header.commandLength > & host -> receivedData [host -> receivedDataLength] - currentData) + commandNumber = command -> header.command & ENET_PROTOCOL_COMMAND_MASK; + if (commandNumber >= ENET_PROTOCOL_COMMAND_COUNT) + break; + + commandSize = commandSizes [commandNumber]; + if (commandSize == 0 || currentData + commandSize > & host -> receivedData [host -> receivedDataLength]) break; - -- commandCount; - currentData += command -> header.commandLength; + currentData += commandSize; - if (peer == NULL && command -> header.command != ENET_PROTOCOL_COMMAND_CONNECT) + if (peer == NULL && commandNumber != ENET_PROTOCOL_COMMAND_CONNECT) break; - command -> header.reliableSequenceNumber = ENET_NET_TO_HOST_32 (command -> header.reliableSequenceNumber); + command -> header.reliableSequenceNumber = ENET_NET_TO_HOST_16 (command -> header.reliableSequenceNumber); - switch (command -> header.command) + switch (command -> header.command & ENET_PROTOCOL_COMMAND_MASK) { case ENET_PROTOCOL_COMMAND_ACKNOWLEDGE: - enet_protocol_handle_acknowledge (host, event, peer, command); + if (enet_protocol_handle_acknowledge (host, event, peer, command)) + goto commandError; break; case ENET_PROTOCOL_COMMAND_CONNECT: peer = enet_protocol_handle_connect (host, header, command); + if (peer == NULL) + goto commandError; break; case ENET_PROTOCOL_COMMAND_VERIFY_CONNECT: - enet_protocol_handle_verify_connect (host, event, peer, command); + if (enet_protocol_handle_verify_connect (host, event, peer, command)) + goto commandError; break; case ENET_PROTOCOL_COMMAND_DISCONNECT: - enet_protocol_handle_disconnect (host, peer, command); + if (enet_protocol_handle_disconnect (host, peer, command)) + goto commandError; break; case ENET_PROTOCOL_COMMAND_PING: - enet_protocol_handle_ping (host, peer, command); + if (enet_protocol_handle_ping (host, peer, command)) + goto commandError; break; case ENET_PROTOCOL_COMMAND_SEND_RELIABLE: - enet_protocol_handle_send_reliable (host, peer, command); + if (enet_protocol_handle_send_reliable (host, peer, command, & currentData)) + goto commandError; break; case ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE: - enet_protocol_handle_send_unreliable (host, peer, command); + if (enet_protocol_handle_send_unreliable (host, peer, command, & currentData)) + goto commandError; break; case ENET_PROTOCOL_COMMAND_SEND_UNSEQUENCED: - enet_protocol_handle_send_unsequenced (host, peer, command); + if (enet_protocol_handle_send_unsequenced (host, peer, command, & currentData)) + goto commandError; break; case ENET_PROTOCOL_COMMAND_SEND_FRAGMENT: - enet_protocol_handle_send_fragment (host, peer, command); + if (enet_protocol_handle_send_fragment (host, peer, command, & currentData)) + goto commandError; break; case ENET_PROTOCOL_COMMAND_BANDWIDTH_LIMIT: - enet_protocol_handle_bandwidth_limit (host, peer, command); + if (enet_protocol_handle_bandwidth_limit (host, peer, command)) + goto commandError; break; case ENET_PROTOCOL_COMMAND_THROTTLE_CONFIGURE: - enet_protocol_handle_throttle_configure (host, peer, command); + if (enet_protocol_handle_throttle_configure (host, peer, command)) + goto commandError; break; default: - break; + goto commandError; } if (peer != NULL && - (command -> header.flags & ENET_PROTOCOL_FLAG_ACKNOWLEDGE) != 0) + (command -> header.command & ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE) != 0) { + enet_uint16 sentTime; + + if (! (flags & ENET_PROTOCOL_HEADER_FLAG_SENT_TIME)) + break; + + sentTime = ENET_NET_TO_HOST_16 (header -> sentTime); + switch (peer -> state) { case ENET_PEER_STATE_DISCONNECTING: + case ENET_PEER_STATE_ACKNOWLEDGING_CONNECT: break; case ENET_PEER_STATE_ACKNOWLEDGING_DISCONNECT: - if (command -> header.command != ENET_PROTOCOL_COMMAND_DISCONNECT) - break; + if ((command -> header.command & ENET_PROTOCOL_COMMAND_MASK) == ENET_PROTOCOL_COMMAND_DISCONNECT) + enet_peer_queue_acknowledgement (peer, command, sentTime); + break; default: - enet_peer_queue_acknowledgement (peer, command, header -> sentTime); + enet_peer_queue_acknowledgement (peer, command, sentTime); break; } } } +commandError: if (event != NULL && event -> type != ENET_EVENT_TYPE_NONE) return 1; @@ -848,7 +956,11 @@ enet_protocol_send_acknowledgements (ENetHost * host, ENetPeer * peer) if (command >= & host -> commands [sizeof (host -> commands) / sizeof (ENetProtocol)] || buffer >= & host -> buffers [sizeof (host -> buffers) / sizeof (ENetBuffer)] || peer -> mtu - host -> packetSize < sizeof (ENetProtocolAcknowledge)) - break; + { + host -> continueSending = 1; + + break; + } acknowledgement = (ENetAcknowledgement *) currentAcknowledgement; @@ -861,12 +973,10 @@ enet_protocol_send_acknowledgements (ENetHost * host, ENetPeer * peer) command -> header.command = ENET_PROTOCOL_COMMAND_ACKNOWLEDGE; command -> header.channelID = acknowledgement -> command.header.channelID; - command -> header.flags = 0; - command -> header.commandLength = ENET_HOST_TO_NET_32 (sizeof (ENetProtocolAcknowledge)); - command -> acknowledge.receivedReliableSequenceNumber = ENET_HOST_TO_NET_32 (acknowledgement -> command.header.reliableSequenceNumber); - command -> acknowledge.receivedSentTime = ENET_HOST_TO_NET_32 (acknowledgement -> sentTime); + command -> acknowledge.receivedReliableSequenceNumber = ENET_HOST_TO_NET_16 (acknowledgement -> command.header.reliableSequenceNumber); + command -> acknowledge.receivedSentTime = ENET_HOST_TO_NET_16 (acknowledgement -> sentTime); - if (acknowledgement -> command.header.command == ENET_PROTOCOL_COMMAND_DISCONNECT) + if ((acknowledgement -> command.header.command & ENET_PROTOCOL_COMMAND_MASK) == ENET_PROTOCOL_COMMAND_DISCONNECT) peer -> state = ENET_PEER_STATE_ZOMBIE; enet_list_remove (& acknowledgement -> acknowledgementList); @@ -892,15 +1002,21 @@ enet_protocol_send_unreliable_outgoing_commands (ENetHost * host, ENetPeer * pee while (currentCommand != enet_list_end (& peer -> outgoingUnreliableCommands)) { + size_t commandSize; + outgoingCommand = (ENetOutgoingCommand *) currentCommand; + commandSize = commandSizes [outgoingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_MASK]; if (command >= & host -> commands [sizeof (host -> commands) / sizeof (ENetProtocol)] || buffer + 1 >= & host -> buffers [sizeof (host -> buffers) / sizeof (ENetBuffer)] || - peer -> mtu - host -> packetSize < outgoingCommand -> command.header.commandLength || + peer -> mtu - host -> packetSize < commandSize || (outgoingCommand -> packet != NULL && - peer -> mtu - host -> packetSize < outgoingCommand -> command.header.commandLength + - outgoingCommand -> packet -> dataLength)) - break; + peer -> mtu - host -> packetSize < commandSize + outgoingCommand -> packet -> dataLength)) + { + host -> continueSending = 1; + + break; + } currentCommand = enet_list_next (currentCommand); @@ -924,7 +1040,7 @@ enet_protocol_send_unreliable_outgoing_commands (ENetHost * host, ENetPeer * pee } buffer -> data = command; - buffer -> dataLength = outgoingCommand -> command.header.commandLength; + buffer -> dataLength = commandSize; host -> packetSize += buffer -> dataLength; @@ -939,8 +1055,6 @@ enet_protocol_send_unreliable_outgoing_commands (ENetHost * host, ENetPeer * pee buffer -> data = outgoingCommand -> packet -> data; buffer -> dataLength = outgoingCommand -> packet -> dataLength; - command -> header.commandLength += buffer -> dataLength; - host -> packetSize += buffer -> dataLength; enet_list_insert (enet_list_end (& peer -> sentUnreliableCommands), outgoingCommand); @@ -948,14 +1062,18 @@ enet_protocol_send_unreliable_outgoing_commands (ENetHost * host, ENetPeer * pee else enet_free (outgoingCommand); - command -> header.commandLength = ENET_HOST_TO_NET_32 (command -> header.commandLength); - ++ command; ++ buffer; } host -> commandCount = command - host -> commands; host -> bufferCount = buffer - host -> buffers; + + if (peer -> state == ENET_PEER_STATE_DISCONNECT_LATER && + enet_list_empty (& peer -> outgoingReliableCommands) && + enet_list_empty (& peer -> outgoingUnreliableCommands) && + enet_list_empty (& peer -> sentReliableCommands)) + enet_peer_disconnect (peer, peer -> disconnectData); } static int @@ -1000,7 +1118,7 @@ enet_protocol_check_timeouts (ENetHost * host, ENetPeer * peer, ENetEvent * even enet_list_remove (& outgoingCommand -> outgoingCommandList)); if (currentCommand == enet_list_begin (& peer -> sentReliableCommands) && - enet_list_empty (& peer -> sentReliableCommands) == 0) + ! enet_list_empty (& peer -> sentReliableCommands)) { outgoingCommand = (ENetOutgoingCommand *) currentCommand; @@ -1023,22 +1141,33 @@ enet_protocol_send_reliable_outgoing_commands (ENetHost * host, ENetPeer * peer) while (currentCommand != enet_list_end (& peer -> outgoingReliableCommands)) { - outgoingCommand = (ENetOutgoingCommand *) currentCommand; + size_t commandSize; + outgoingCommand = (ENetOutgoingCommand *) currentCommand; + commandSize = commandSizes [outgoingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_MASK]; + if (command >= & host -> commands [sizeof (host -> commands) / sizeof (ENetProtocol)] || buffer + 1 >= & host -> buffers [sizeof (host -> buffers) / sizeof (ENetBuffer)] || - peer -> mtu - host -> packetSize < outgoingCommand -> command.header.commandLength) - break; + peer -> mtu - host -> packetSize < commandSize) + { + host -> continueSending = 1; + + break; + } currentCommand = enet_list_next (currentCommand); if (outgoingCommand -> packet != NULL) { - if ((enet_uint16) (peer -> mtu - host -> packetSize) < - (enet_uint16) (outgoingCommand -> command.header.commandLength + - outgoingCommand -> fragmentLength) || - peer -> reliableDataInTransit + outgoingCommand -> fragmentLength > peer -> windowSize) + if (peer -> reliableDataInTransit + outgoingCommand -> fragmentLength > peer -> windowSize) break; + + if ((enet_uint16) (peer -> mtu - host -> packetSize) < (enet_uint16) (commandSize + outgoingCommand -> fragmentLength)) + { + host -> continueSending = 1; + + break; + } } if (outgoingCommand -> roundTripTimeout == 0) @@ -1056,9 +1185,10 @@ enet_protocol_send_reliable_outgoing_commands (ENetHost * host, ENetPeer * peer) outgoingCommand -> sentTime = timeCurrent; buffer -> data = command; - buffer -> dataLength = outgoingCommand -> command.header.commandLength; + buffer -> dataLength = commandSize; host -> packetSize += buffer -> dataLength; + host -> headerFlags |= ENET_PROTOCOL_HEADER_FLAG_SENT_TIME; * command = outgoingCommand -> command; @@ -1069,15 +1199,11 @@ enet_protocol_send_reliable_outgoing_commands (ENetHost * host, ENetPeer * peer) buffer -> data = outgoingCommand -> packet -> data + outgoingCommand -> fragmentOffset; buffer -> dataLength = outgoingCommand -> fragmentLength; - command -> header.commandLength += outgoingCommand -> fragmentLength; - host -> packetSize += outgoingCommand -> fragmentLength; peer -> reliableDataInTransit += outgoingCommand -> fragmentLength; } - command -> header.commandLength = ENET_HOST_TO_NET_32 (command -> header.commandLength); - ++ peer -> packetsSent; ++ command; @@ -1091,14 +1217,15 @@ enet_protocol_send_reliable_outgoing_commands (ENetHost * host, ENetPeer * peer) static int enet_protocol_send_outgoing_commands (ENetHost * host, ENetEvent * event, int checkForTimeouts) { - size_t packetsSent = 1; ENetProtocolHeader header; ENetPeer * currentPeer; int sentLength; - while (packetsSent > 0) - for (currentPeer = host -> peers, - packetsSent = 0; + host -> continueSending = 1; + + while (host -> continueSending) + for (host -> continueSending = 0, + currentPeer = host -> peers; currentPeer < & host -> peers [host -> peerCount]; ++ currentPeer) { @@ -1106,22 +1233,21 @@ enet_protocol_send_outgoing_commands (ENetHost * host, ENetEvent * event, int ch currentPeer -> state == ENET_PEER_STATE_ZOMBIE) continue; + host -> headerFlags = 0; host -> commandCount = 0; host -> bufferCount = 1; host -> packetSize = sizeof (ENetProtocolHeader); - if (enet_list_empty (& currentPeer -> acknowledgements) == 0) + if (! enet_list_empty (& currentPeer -> acknowledgements)) enet_protocol_send_acknowledgements (host, currentPeer); - - if (host -> commandCount < sizeof (host -> commands) / sizeof (ENetProtocol)) - { - if (checkForTimeouts != 0 && - enet_list_empty (& currentPeer -> sentReliableCommands) == 0 && - ENET_TIME_GREATER_EQUAL (timeCurrent, currentPeer -> nextTimeout) && - enet_protocol_check_timeouts (host, currentPeer, event) == 1) - return 1; - } - if (enet_list_empty (& currentPeer -> outgoingReliableCommands) == 0) + + if (checkForTimeouts != 0 && + ! enet_list_empty (& currentPeer -> sentReliableCommands) && + ENET_TIME_GREATER_EQUAL (timeCurrent, currentPeer -> nextTimeout) && + enet_protocol_check_timeouts (host, currentPeer, event) == 1) + return 1; + + if (! enet_list_empty (& currentPeer -> outgoingReliableCommands)) enet_protocol_send_reliable_outgoing_commands (host, currentPeer); else if (enet_list_empty (& currentPeer -> sentReliableCommands) && @@ -1132,8 +1258,7 @@ enet_protocol_send_outgoing_commands (ENetHost * host, ENetEvent * event, int ch enet_protocol_send_reliable_outgoing_commands (host, currentPeer); } - if (host -> commandCount < sizeof (host -> commands) / sizeof (ENetProtocol) && - enet_list_empty (& currentPeer -> outgoingUnreliableCommands) == 0) + if (! enet_list_empty (& currentPeer -> outgoingUnreliableCommands)) enet_protocol_send_unreliable_outgoing_commands (host, currentPeer); if (host -> commandCount == 0) @@ -1174,19 +1299,25 @@ enet_protocol_send_outgoing_commands (ENetHost * host, ENetEvent * event, int ch currentPeer -> packetsLost = 0; } - header.peerID = ENET_HOST_TO_NET_16 (currentPeer -> outgoingPeerID); - header.flags = 0; - header.commandCount = host -> commandCount; - header.sentTime = ENET_HOST_TO_NET_32 (timeCurrent); - header.challenge = currentPeer -> challenge; - + header.checksum = currentPeer -> sessionID; + header.peerID = ENET_HOST_TO_NET_16 (currentPeer -> outgoingPeerID | host -> headerFlags); + host -> buffers -> data = & header; - host -> buffers -> dataLength = sizeof (ENetProtocolHeader); + if (host -> headerFlags & ENET_PROTOCOL_HEADER_FLAG_SENT_TIME) + { + header.sentTime = ENET_HOST_TO_NET_16 (timeCurrent & 0xFFFF); + + host -> buffers -> dataLength = sizeof (ENetProtocolHeader); + } + else + host -> buffers -> dataLength = (size_t) & ((ENetProtocolHeader *) 0) -> sentTime; + +#ifdef USE_CRC32 + header.checksum = enet_crc32 (host -> buffers, host -> bufferCount); +#endif currentPeer -> lastSendTime = timeCurrent; - ++ packetsSent; - sentLength = enet_socket_send (host -> socket, & currentPeer -> address, host -> buffers, host -> bufferCount); enet_protocol_remove_sent_unreliable_commands (currentPeer); diff --git a/unix.c b/unix.c index 3772fef..75385a8 100644 --- a/unix.c +++ b/unix.c @@ -80,7 +80,7 @@ enet_address_set_host (ENetAddress * address, const char * name) char buffer [2048]; int errnum; -#ifdef linux +#if defined(linux) || defined(FREEBSD) gethostbyname_r (name, & hostData, buffer, sizeof (buffer), & hostEntry, & errnum); #else hostEntry = gethostbyname_r (name, & hostData, buffer, sizeof (buffer), & errnum); @@ -118,7 +118,7 @@ enet_address_get_host (const ENetAddress * address, char * name, size_t nameLeng in.s_addr = address -> host; -#ifdef linux +#if defined(linux) || defined(FREEBSD) gethostbyaddr_r ((char *) & in, sizeof (struct in_addr), AF_INET, & hostData, buffer, sizeof (buffer), & hostEntry, & errnum); #else hostEntry = gethostbyaddr_r ((char *) & in, sizeof (struct in_addr), AF_INET, & hostData, buffer, sizeof (buffer), & errnum); @@ -153,6 +153,7 @@ enet_socket_create (ENetSocketType type, const ENetAddress * address) { ENetSocket newSocket = socket (PF_INET, type == ENET_SOCKET_TYPE_DATAGRAM ? SOCK_DGRAM : SOCK_STREAM, 0); int receiveBufferSize = ENET_HOST_RECEIVE_BUFFER_SIZE, + sendBufferSize = ENET_HOST_SEND_BUFFER_SIZE, allowBroadcasting = 1; #ifndef HAS_FCNTL int nonBlocking = 1; @@ -171,6 +172,7 @@ enet_socket_create (ENetSocketType type, const ENetAddress * address) #endif setsockopt (newSocket, SOL_SOCKET, SO_RCVBUF, (char *) & receiveBufferSize, sizeof (int)); + setsockopt (newSocket, SOL_SOCKET, SO_SNDBUF, (char *) & sendBufferSize, sizeof (int)); setsockopt (newSocket, SOL_SOCKET, SO_BROADCAST, (char *) & allowBroadcasting, sizeof (int)); } diff --git a/win32.c b/win32.c index 2300071..8fdd746 100644 --- a/win32.c +++ b/win32.c @@ -102,6 +102,7 @@ enet_socket_create (ENetSocketType type, const ENetAddress * address) ENetSocket newSocket = socket (PF_INET, type == ENET_SOCKET_TYPE_DATAGRAM ? SOCK_DGRAM : SOCK_STREAM, 0); u_long nonBlocking = 1; int receiveBufferSize = ENET_HOST_RECEIVE_BUFFER_SIZE, + sendBufferSize = ENET_HOST_SEND_BUFFER_SIZE, allowBroadcasting = 1; struct sockaddr_in sin; @@ -113,6 +114,7 @@ enet_socket_create (ENetSocketType type, const ENetAddress * address) ioctlsocket (newSocket, FIONBIO, & nonBlocking); setsockopt (newSocket, SOL_SOCKET, SO_RCVBUF, (char *) & receiveBufferSize, sizeof (int)); + setsockopt (newSocket, SOL_SOCKET, SO_SNDBUF, (char *) & sendBufferSize, sizeof (int)); setsockopt (newSocket, SOL_SOCKET, SO_BROADCAST, (char *) & allowBroadcasting, sizeof (int)); }