From 7fab9d1695f005bce343cbd4f93ab645e4af3d7f Mon Sep 17 00:00:00 2001 From: Lee Salzman Date: Tue, 31 May 2011 09:59:42 +0000 Subject: [PATCH] enet 1.3.2 git-svn-id: svn://svn.code.sf.net/p/actiongame/code/trunk/ac@6484 e016b1c5-ed68-44aa-a2f7-31cac88cffde --- source/enet/ChangeLog | 16 +++ source/enet/Makefile.am | 2 +- source/enet/configure | 20 ++-- source/enet/configure.ac | 2 +- source/enet/docs/mainpage.dox | 4 +- source/enet/host.c | 1 + source/enet/include/enet/enet.h | 8 +- source/enet/include/enet/protocol.h | 3 +- source/enet/peer.c | 126 +++++++++++++++------ source/enet/protocol.c | 164 +++++++++++++++++++++++++--- source/lib/enet.lib | Bin 45262 -> 46312 bytes 11 files changed, 282 insertions(+), 64 deletions(-) diff --git a/source/enet/ChangeLog b/source/enet/ChangeLog index b1fc2008..47c38adc 100644 --- a/source/enet/ChangeLog +++ b/source/enet/ChangeLog @@ -1,3 +1,10 @@ +ENet 1.3.2 (May 31, 2011): + +* added support for unreliable packet fragmenting via the packet flag +ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT +* fixed regression in unreliable packet queuing +* added check against received port to limit some forms of IP-spoofing + ENet 1.3.1 (February 10, 2011): * fixed bug in tracking of reliable data in transit @@ -21,6 +28,15 @@ Caveats: This version is not protocol compatible with the 1.2 series or earlier. The enet_host_connect and enet_host_create API functions require supplying additional parameters. +ENet 1.2.4 (May 31, 2011): + +* fixed regression in unreliable packet queuing +* added check against received port to limit some forms of IP-spoofing + +ENet 1.2.3 (February 10, 2011): + +* fixed bug in tracking reliable data in transit + ENet 1.2.2 (June 5, 2010): * checksum functionality is now enabled by setting a checksum callback diff --git a/source/enet/Makefile.am b/source/enet/Makefile.am index 4f396883..da792bce 100755 --- a/source/enet/Makefile.am +++ b/source/enet/Makefile.am @@ -16,7 +16,7 @@ enetinclude_HEADERS = \ lib_LTLIBRARIES = libenet.la libenet_la_SOURCES = callbacks.c compress.c host.c list.c packet.c peer.c protocol.c unix.c win32.c # see info '(libtool) Updating version info' before making a release -libenet_la_LDFLAGS = $(AM_LDFLAGS) -version-info 1:1:0 +libenet_la_LDFLAGS = $(AM_LDFLAGS) -version-info 1:2:0 INCLUDES = -Iinclude ACLOCAL_AMFLAGS = -Im4 diff --git a/source/enet/configure b/source/enet/configure index c6342c03..34bd1eb3 100755 --- a/source/enet/configure +++ b/source/enet/configure @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.67 for libenet 1.3.1. +# Generated by GNU Autoconf 2.67 for libenet 1.3.2. # # # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, @@ -698,8 +698,8 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='libenet' PACKAGE_TARNAME='libenet' -PACKAGE_VERSION='1.3.1' -PACKAGE_STRING='libenet 1.3.1' +PACKAGE_VERSION='1.3.2' +PACKAGE_STRING='libenet 1.3.2' PACKAGE_BUGREPORT='' PACKAGE_URL='' @@ -1415,7 +1415,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures libenet 1.3.1 to adapt to many kinds of systems. +\`configure' configures libenet 1.3.2 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1485,7 +1485,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of libenet 1.3.1:";; + short | recursive ) echo "Configuration of libenet 1.3.2:";; esac cat <<\_ACEOF @@ -1586,7 +1586,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -libenet configure 1.3.1 +libenet configure 1.3.2 generated by GNU Autoconf 2.67 Copyright (C) 2010 Free Software Foundation, Inc. @@ -1975,7 +1975,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by libenet $as_me 1.3.1, which was +It was created by libenet $as_me 1.3.2, which was generated by GNU Autoconf 2.67. Invocation command line was $ $0 $@ @@ -2791,7 +2791,7 @@ fi # Define the identity of the package. PACKAGE='libenet' - VERSION='1.3.1' + VERSION='1.3.2' cat >>confdefs.h <<_ACEOF @@ -11108,7 +11108,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by libenet $as_me 1.3.1, which was +This file was extended by libenet $as_me 1.3.2, which was generated by GNU Autoconf 2.67. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -11165,7 +11165,7 @@ _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -libenet config.status 1.3.1 +libenet config.status 1.3.2 configured by $0, generated by GNU Autoconf 2.67, with options \\"\$ac_cs_config\\" diff --git a/source/enet/configure.ac b/source/enet/configure.ac index e5a07446..3486ca80 100644 --- a/source/enet/configure.ac +++ b/source/enet/configure.ac @@ -1,4 +1,4 @@ -AC_INIT([libenet], [1.3.1]) +AC_INIT([libenet], [1.3.2]) AC_CONFIG_SRCDIR([include/enet/enet.h]) AM_INIT_AUTOMAKE([foreign]) AM_MAINTAINER_MODE([enable]) diff --git a/source/enet/docs/mainpage.dox b/source/enet/docs/mainpage.dox index 1ea5b4e7..3b6234a4 100755 --- a/source/enet/docs/mainpage.dox +++ b/source/enet/docs/mainpage.dox @@ -36,8 +36,8 @@ portable, and easily embeddable. You can retrieve the source to ENet by downloading it in either .tar.gz form or accessing the cvs distribution directly. -The most recent stable release (1.3.1) can be downloaded here. -The last release that is protocol compatible with the 1.2 series or earlier (1.2.3) can be downloaded here +The most recent stable release (1.3.2) can be downloaded here. +The last release that is protocol compatible with the 1.2 series or earlier (1.2.4) can be downloaded here To access ENet via anonymous CVS, you must use the CVSROOT :pserver:anonymous\@bespin.org:/var/lib/cvs/enet with an empty diff --git a/source/enet/host.c b/source/enet/host.c index 8bb2433f..c44f2ed3 100755 --- a/source/enet/host.c +++ b/source/enet/host.c @@ -210,6 +210,7 @@ enet_host_connect (ENetHost * host, const ENetAddress * address, size_t channelC channel -> outgoingReliableSequenceNumber = 0; channel -> outgoingUnreliableSequenceNumber = 0; channel -> incomingReliableSequenceNumber = 0; + channel -> incomingUnreliableSequenceNumber = 0; enet_list_clear (& channel -> incomingReliableCommands); enet_list_clear (& channel -> incomingUnreliableCommands); diff --git a/source/enet/include/enet/enet.h b/source/enet/include/enet/enet.h index b572590e..02dc2c0a 100755 --- a/source/enet/include/enet/enet.h +++ b/source/enet/include/enet/enet.h @@ -25,7 +25,7 @@ extern "C" #define ENET_VERSION_MAJOR 1 #define ENET_VERSION_MINOR 3 -#define ENET_VERSION_PATCH 1 +#define ENET_VERSION_PATCH 2 #define ENET_VERSION_CREATE(major, minor, patch) (((major)<<16) | ((minor)<<8) | (patch)) #define ENET_VERSION ENET_VERSION_CREATE(ENET_VERSION_MAJOR, ENET_VERSION_MINOR, ENET_VERSION_PATCH) @@ -96,7 +96,10 @@ typedef enum _ENetPacketFlag */ ENET_PACKET_FLAG_UNSEQUENCED = (1 << 1), /** packet will not allocate data, and user must supply it instead */ - ENET_PACKET_FLAG_NO_ALLOCATE = (1 << 2) + ENET_PACKET_FLAG_NO_ALLOCATE = (1 << 2), + /** packet will be fragmented using unreliable (instead of reliable) sends + * if it exceeds the MTU */ + ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT = (1 << 3) } ENetPacketFlag; struct _ENetPacket; @@ -218,6 +221,7 @@ typedef struct _ENetChannel enet_uint16 usedReliableWindows; enet_uint16 reliableWindows [ENET_PEER_RELIABLE_WINDOWS]; enet_uint16 incomingReliableSequenceNumber; + enet_uint16 incomingUnreliableSequenceNumber; ENetList incomingReliableCommands; ENetList incomingUnreliableCommands; } ENetChannel; diff --git a/source/enet/include/enet/protocol.h b/source/enet/include/enet/protocol.h index 19f7e45d..faef9179 100755 --- a/source/enet/include/enet/protocol.h +++ b/source/enet/include/enet/protocol.h @@ -33,7 +33,8 @@ typedef enum _ENetProtocolCommand 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_SEND_UNRELIABLE_FRAGMENT = 12, + ENET_PROTOCOL_COMMAND_COUNT = 13, ENET_PROTOCOL_COMMAND_MASK = 0x0F } ENetProtocolCommand; diff --git a/source/enet/peer.c b/source/enet/peer.c index e1c117f8..566f7978 100755 --- a/source/enet/peer.c +++ b/source/enet/peer.c @@ -113,13 +113,26 @@ 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), fragmentNumber, fragmentOffset; + enet_uint8 commandNumber; + enet_uint16 startSequenceNumber; ENetList fragments; ENetOutgoingCommand * fragment; + if ((packet -> flags & (ENET_PACKET_FLAG_RELIABLE | ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT)) == ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT && + channel -> outgoingUnreliableSequenceNumber < 0xFFFF) + { + commandNumber = ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE_FRAGMENT; + startSequenceNumber = ENET_HOST_TO_NET_16 (channel -> outgoingUnreliableSequenceNumber + 1); + } + else + { + commandNumber = ENET_PROTOCOL_COMMAND_SEND_FRAGMENT | ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE; + startSequenceNumber = ENET_HOST_TO_NET_16 (channel -> outgoingReliableSequenceNumber + 1); + } + enet_list_clear (& fragments); for (fragmentNumber = 0, @@ -147,7 +160,7 @@ enet_peer_send (ENetPeer * peer, enet_uint8 channelID, ENetPacket * packet) fragment -> fragmentOffset = fragmentOffset; fragment -> fragmentLength = fragmentLength; fragment -> packet = packet; - fragment -> command.header.command = ENET_PROTOCOL_COMMAND_SEND_FRAGMENT | ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE; + fragment -> command.header.command = commandNumber; fragment -> command.header.channelID = channelID; fragment -> command.sendFragment.startSequenceNumber = startSequenceNumber; fragment -> command.sendFragment.dataLength = ENET_HOST_TO_NET_16 (fragmentLength); @@ -173,20 +186,13 @@ enet_peer_send (ENetPeer * peer, enet_uint8 channelID, ENetPacket * packet) command.header.channelID = channelID; - if (packet -> flags & ENET_PACKET_FLAG_RELIABLE) - { - 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) + if ((packet -> flags & (ENET_PACKET_FLAG_RELIABLE | ENET_PACKET_FLAG_UNSEQUENCED)) == ENET_PACKET_FLAG_UNSEQUENCED) { 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 - if (channel -> outgoingUnreliableSequenceNumber >= 0xFFFF) + if (packet -> flags & ENET_PACKET_FLAG_RELIABLE || channel -> outgoingUnreliableSequenceNumber >= 0xFFFF) { command.header.command = ENET_PROTOCOL_COMMAND_SEND_RELIABLE | ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE; command.sendReliable.dataLength = ENET_HOST_TO_NET_16 (packet -> dataLength); @@ -194,7 +200,6 @@ enet_peer_send (ENetPeer * peer, enet_uint8 channelID, ENetPacket * packet) else { command.header.command = ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE; - command.sendUnreliable.unreliableSequenceNumber = ENET_HOST_TO_NET_16 (channel -> outgoingUnreliableSequenceNumber + 1); command.sendUnreliable.dataLength = ENET_HOST_TO_NET_16 (packet -> dataLength); } @@ -257,14 +262,18 @@ enet_peer_reset_outgoing_commands (ENetList * queue) } static void -enet_peer_reset_incoming_commands (ENetList * queue) +enet_peer_remove_incoming_commands (ENetList * queue, ENetListIterator startCommand, ENetListIterator endCommand) { - ENetIncomingCommand * incomingCommand; - - while (! enet_list_empty (queue)) + ENetListIterator currentCommand; + + for (currentCommand = startCommand; currentCommand != endCommand; ) { - incomingCommand = (ENetIncomingCommand *) enet_list_remove (enet_list_begin (queue)); + ENetIncomingCommand * incomingCommand = (ENetIncomingCommand *) currentCommand; + currentCommand = enet_list_next (currentCommand); + + enet_list_remove (& incomingCommand -> incomingCommandList); + if (incomingCommand -> packet != NULL) { -- incomingCommand -> packet -> referenceCount; @@ -280,6 +289,12 @@ enet_peer_reset_incoming_commands (ENetList * queue) } } +static void +enet_peer_reset_incoming_commands (ENetList * queue) +{ + enet_peer_remove_incoming_commands(queue, enet_list_begin (queue), enet_list_end(queue)); +} + void enet_peer_reset_queues (ENetPeer * peer) { @@ -550,7 +565,8 @@ enet_peer_setup_outgoing_command (ENetPeer * peer, ENetOutgoingCommand * outgoin } else { - ++ channel -> outgoingUnreliableSequenceNumber; + if (outgoingCommand -> fragmentOffset == 0) + ++ channel -> outgoingUnreliableSequenceNumber; outgoingCommand -> reliableSequenceNumber = channel -> outgoingReliableSequenceNumber; outgoingCommand -> unreliableSequenceNumber = channel -> outgoingUnreliableSequenceNumber; @@ -562,6 +578,20 @@ enet_peer_setup_outgoing_command (ENetPeer * peer, ENetOutgoingCommand * outgoin outgoingCommand -> roundTripTimeoutLimit = 0; outgoingCommand -> command.header.reliableSequenceNumber = ENET_HOST_TO_NET_16 (outgoingCommand -> reliableSequenceNumber); + switch (outgoingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_MASK) + { + case ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE: + outgoingCommand -> command.sendUnreliable.unreliableSequenceNumber = ENET_HOST_TO_NET_16 (outgoingCommand -> unreliableSequenceNumber); + break; + + case ENET_PROTOCOL_COMMAND_SEND_UNSEQUENCED: + outgoingCommand -> command.sendUnsequenced.unsequencedGroup = ENET_HOST_TO_NET_16 (peer -> outgoingUnsequencedGroup); + break; + + default: + break; + } + if (outgoingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE) enet_list_insert (enet_list_end (& peer -> outgoingReliableCommands), outgoingCommand); else @@ -590,30 +620,55 @@ enet_peer_queue_outgoing_command (ENetPeer * peer, const ENetProtocol * command, void enet_peer_dispatch_incoming_unreliable_commands (ENetPeer * peer, ENetChannel * channel) { - ENetListIterator currentCommand; + ENetListIterator droppedCommand, startCommand, currentCommand; - for (currentCommand = enet_list_begin (& channel -> incomingUnreliableCommands); + for (droppedCommand = startCommand = currentCommand = enet_list_begin (& channel -> incomingUnreliableCommands); currentCommand != enet_list_end (& channel -> incomingUnreliableCommands); currentCommand = enet_list_next (currentCommand)) { ENetIncomingCommand * incomingCommand = (ENetIncomingCommand *) currentCommand; - if ((incomingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_MASK) == ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE && - incomingCommand -> reliableSequenceNumber != channel -> incomingReliableSequenceNumber) + if ((incomingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_MASK) == ENET_PROTOCOL_COMMAND_SEND_UNSEQUENCED) + continue; + else + if (incomingCommand -> reliableSequenceNumber != channel -> incomingReliableSequenceNumber) break; + else + if (incomingCommand -> fragmentsRemaining <= 0) + channel -> incomingUnreliableSequenceNumber = incomingCommand -> unreliableSequenceNumber; + else + if (startCommand == currentCommand) + startCommand = enet_list_next (currentCommand); + else + { + enet_list_move (enet_list_end (& peer -> dispatchedCommands), startCommand, enet_list_previous (currentCommand)); + + if (! peer -> needsDispatch) + { + enet_list_insert (enet_list_end (& peer -> host -> dispatchQueue), & peer -> dispatchList); + + peer -> needsDispatch = 1; + } + + droppedCommand = startCommand = enet_list_next (currentCommand); + } } - if (currentCommand == enet_list_begin (& channel -> incomingUnreliableCommands)) - return; - - enet_list_move (enet_list_end (& peer -> dispatchedCommands), enet_list_begin (& channel -> incomingUnreliableCommands), enet_list_previous (currentCommand)); - - if (! peer -> needsDispatch) + if (startCommand != currentCommand) { - enet_list_insert (enet_list_end (& peer -> host -> dispatchQueue), & peer -> dispatchList); + enet_list_move (enet_list_end (& peer -> dispatchedCommands), startCommand, enet_list_previous (currentCommand)); - peer -> needsDispatch = 1; + if (! peer -> needsDispatch) + { + enet_list_insert (enet_list_end (& peer -> host -> dispatchQueue), & peer -> dispatchList); + + peer -> needsDispatch = 1; + } + + droppedCommand = startCommand = enet_list_next (currentCommand); } + + enet_peer_remove_incoming_commands (& channel -> incomingUnreliableCommands, enet_list_begin (& channel -> incomingUnreliableCommands), droppedCommand); } void @@ -640,6 +695,8 @@ enet_peer_dispatch_incoming_reliable_commands (ENetPeer * peer, ENetChannel * ch if (currentCommand == enet_list_begin (& channel -> incomingReliableCommands)) return; + channel -> incomingUnreliableSequenceNumber = 0; + enet_list_move (enet_list_end (& peer -> dispatchedCommands), enet_list_begin (& channel -> incomingReliableCommands), enet_list_previous (currentCommand)); if (! peer -> needsDispatch) @@ -684,7 +741,7 @@ enet_peer_queue_incoming_command (ENetPeer * peer, const ENetProtocol * command, case ENET_PROTOCOL_COMMAND_SEND_FRAGMENT: case ENET_PROTOCOL_COMMAND_SEND_RELIABLE: if (reliableSequenceNumber == channel -> incomingReliableSequenceNumber) - goto freePacket; + goto freePacket; for (currentCommand = enet_list_previous (enet_list_end (& channel -> incomingReliableCommands)); currentCommand != enet_list_end (& channel -> incomingReliableCommands); @@ -712,15 +769,20 @@ enet_peer_queue_incoming_command (ENetPeer * peer, const ENetProtocol * command, break; case ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE: + case ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE_FRAGMENT: unreliableSequenceNumber = ENET_NET_TO_HOST_16 (command -> sendUnreliable.unreliableSequenceNumber); + if (reliableSequenceNumber == channel -> incomingReliableSequenceNumber && + unreliableSequenceNumber <= channel -> incomingUnreliableSequenceNumber) + goto freePacket; + for (currentCommand = enet_list_previous (enet_list_end (& channel -> incomingUnreliableCommands)); currentCommand != enet_list_end (& channel -> incomingUnreliableCommands); currentCommand = enet_list_previous (currentCommand)) { incomingCommand = (ENetIncomingCommand *) currentCommand; - if ((incomingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_MASK) != ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE) + if ((command -> header.command & ENET_PROTOCOL_COMMAND_MASK) == ENET_PROTOCOL_COMMAND_SEND_UNSEQUENCED) continue; if (reliableSequenceNumber >= channel -> incomingReliableSequenceNumber) diff --git a/source/enet/protocol.c b/source/enet/protocol.c index 9791839d..d7c3fede 100755 --- a/source/enet/protocol.c +++ b/source/enet/protocol.c @@ -23,6 +23,7 @@ static size_t commandSizes [ENET_PROTOCOL_COMMAND_COUNT] = sizeof (ENetProtocolSendUnsequenced), sizeof (ENetProtocolBandwidthLimit), sizeof (ENetProtocolThrottleConfigure), + sizeof (ENetProtocolSendFragment) }; size_t @@ -319,6 +320,7 @@ enet_protocol_handle_connect (ENetHost * host, ENetProtocolHeader * header, ENet channel -> outgoingReliableSequenceNumber = 0; channel -> outgoingUnreliableSequenceNumber = 0; channel -> incomingReliableSequenceNumber = 0; + channel -> incomingUnreliableSequenceNumber = 0; enet_list_clear (& channel -> incomingReliableCommands); enet_list_clear (& channel -> incomingUnreliableCommands); @@ -573,12 +575,6 @@ enet_protocol_handle_send_fragment (ENetHost * host, ENetPeer * peer, const ENet return -1; hostCommand.header.reliableSequenceNumber = startSequenceNumber; - hostCommand.sendFragment.startSequenceNumber = startSequenceNumber; - hostCommand.sendFragment.dataLength = fragmentLength; - hostCommand.sendFragment.fragmentNumber = fragmentNumber; - hostCommand.sendFragment.fragmentCount = fragmentCount; - hostCommand.sendFragment.fragmentOffset = fragmentOffset; - hostCommand.sendFragment.totalLength = totalLength; startCommand = enet_peer_queue_incoming_command (peer, & hostCommand, packet, fragmentCount); if (startCommand == NULL) @@ -605,6 +601,124 @@ enet_protocol_handle_send_fragment (ENetHost * host, ENetPeer * peer, const ENet return 0; } +static int +enet_protocol_handle_send_unreliable_fragment (ENetHost * host, ENetPeer * peer, const ENetProtocol * command, enet_uint8 ** currentData) +{ + enet_uint32 fragmentNumber, + fragmentCount, + fragmentOffset, + fragmentLength, + reliableSequenceNumber, + startSequenceNumber, + totalLength; + enet_uint16 reliableWindow, currentWindow; + ENetChannel * channel; + ENetListIterator currentCommand; + ENetIncomingCommand * startCommand = NULL; + + 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]; + reliableSequenceNumber = command -> header.reliableSequenceNumber; + startSequenceNumber = ENET_NET_TO_HOST_16 (command -> sendFragment.startSequenceNumber); + + reliableWindow = reliableSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE; + currentWindow = channel -> incomingReliableSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE; + + if (reliableSequenceNumber < channel -> incomingReliableSequenceNumber) + reliableWindow += ENET_PEER_RELIABLE_WINDOWS; + + if (reliableWindow < currentWindow || reliableWindow >= currentWindow + ENET_PEER_FREE_RELIABLE_WINDOWS - 1) + return 0; + + if (reliableSequenceNumber == channel -> incomingReliableSequenceNumber && + startSequenceNumber <= channel -> incomingUnreliableSequenceNumber) + return 0; + + 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); + + if (fragmentOffset >= totalLength || + fragmentOffset + fragmentLength > totalLength || + fragmentNumber >= fragmentCount) + return -1; + + for (currentCommand = enet_list_previous (enet_list_end (& channel -> incomingUnreliableCommands)); + currentCommand != enet_list_end (& channel -> incomingUnreliableCommands); + currentCommand = enet_list_previous (currentCommand)) + { + ENetIncomingCommand * incomingCommand = (ENetIncomingCommand *) currentCommand; + + if (reliableSequenceNumber >= channel -> incomingReliableSequenceNumber) + { + if (incomingCommand -> reliableSequenceNumber < channel -> incomingReliableSequenceNumber) + continue; + } + else + if (incomingCommand -> reliableSequenceNumber >= channel -> incomingReliableSequenceNumber) + break; + + if (incomingCommand -> reliableSequenceNumber < reliableSequenceNumber) + break; + + if (incomingCommand -> reliableSequenceNumber > reliableSequenceNumber) + continue; + + if (incomingCommand -> unreliableSequenceNumber <= startSequenceNumber) + { + if (incomingCommand -> unreliableSequenceNumber < startSequenceNumber) + break; + + if ((incomingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_MASK) != ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE_FRAGMENT || + totalLength != incomingCommand -> packet -> dataLength || + fragmentCount != incomingCommand -> fragmentCount) + return -1; + + startCommand = incomingCommand; + break; + } + } + + if (startCommand == NULL) + { + ENetPacket * packet = enet_packet_create (NULL, totalLength, ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT); + if (packet == NULL) + return -1; + + startCommand = enet_peer_queue_incoming_command (peer, command, packet, fragmentCount); + if (startCommand == NULL) + return -1; + } + + if ((startCommand -> fragments [fragmentNumber / 32] & (1 << (fragmentNumber % 32))) == 0) + { + -- startCommand -> fragmentsRemaining; + + startCommand -> fragments [fragmentNumber / 32] |= (1 << (fragmentNumber % 32)); + + if (fragmentOffset + fragmentLength > startCommand -> packet -> dataLength) + fragmentLength = startCommand -> packet -> dataLength - fragmentOffset; + + memcpy (startCommand -> packet -> data + fragmentOffset, + (enet_uint8 *) command + sizeof (ENetProtocolSendFragment), + fragmentLength); + + if (startCommand -> fragmentsRemaining <= 0) + enet_peer_dispatch_incoming_unreliable_commands (peer, channel); + } + + return 0; +} + static int enet_protocol_handle_ping (ENetHost * host, ENetPeer * peer, const ENetProtocol * command) { @@ -986,6 +1100,11 @@ enet_protocol_handle_incoming_commands (ENetHost * host, ENetEvent * event) goto commandError; break; + case ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE_FRAGMENT: + if (enet_protocol_handle_send_unreliable_fragment (host, peer, command, & currentData)) + goto commandError; + break; + default: goto commandError; } @@ -1139,7 +1258,7 @@ enet_protocol_send_unreliable_outgoing_commands (ENetHost * host, ENetPeer * pee buffer + 1 >= & host -> buffers [sizeof (host -> buffers) / sizeof (ENetBuffer)] || peer -> mtu - host -> packetSize < commandSize || (outgoingCommand -> packet != NULL && - peer -> mtu - host -> packetSize < commandSize + outgoingCommand -> packet -> dataLength)) + peer -> mtu - host -> packetSize < commandSize + outgoingCommand -> fragmentLength)) { host -> continueSending = 1; @@ -1148,20 +1267,35 @@ enet_protocol_send_unreliable_outgoing_commands (ENetHost * host, ENetPeer * pee currentCommand = enet_list_next (currentCommand); - if (outgoingCommand -> packet != NULL) + if (outgoingCommand -> packet != NULL && outgoingCommand -> fragmentOffset == 0) { peer -> packetThrottleCounter += ENET_PEER_PACKET_THROTTLE_COUNTER; peer -> packetThrottleCounter %= ENET_PEER_PACKET_THROTTLE_SCALE; if (peer -> packetThrottleCounter > peer -> packetThrottle) { - -- outgoingCommand -> packet -> referenceCount; + enet_uint16 reliableSequenceNumber = outgoingCommand -> reliableSequenceNumber, + unreliableSequenceNumber = outgoingCommand -> unreliableSequenceNumber; + for (;;) + { + -- outgoingCommand -> packet -> referenceCount; - if (outgoingCommand -> packet -> referenceCount == 0) - enet_packet_destroy (outgoingCommand -> packet); + if (outgoingCommand -> packet -> referenceCount == 0) + enet_packet_destroy (outgoingCommand -> packet); - enet_list_remove (& outgoingCommand -> outgoingCommandList); - enet_free (outgoingCommand); + enet_list_remove (& outgoingCommand -> outgoingCommandList); + enet_free (outgoingCommand); + + if (currentCommand == enet_list_end (& peer -> outgoingUnreliableCommands)) + break; + + outgoingCommand = (ENetOutgoingCommand *) currentCommand; + if (outgoingCommand -> reliableSequenceNumber != reliableSequenceNumber || + outgoingCommand -> unreliableSequenceNumber != unreliableSequenceNumber) + break; + + currentCommand = enet_list_next (currentCommand); + } continue; } @@ -1180,8 +1314,8 @@ enet_protocol_send_unreliable_outgoing_commands (ENetHost * host, ENetPeer * pee { ++ buffer; - buffer -> data = outgoingCommand -> packet -> data; - buffer -> dataLength = outgoingCommand -> packet -> dataLength; + buffer -> data = outgoingCommand -> packet -> data + outgoingCommand -> fragmentOffset; + buffer -> dataLength = outgoingCommand -> fragmentLength; host -> packetSize += buffer -> dataLength; diff --git a/source/lib/enet.lib b/source/lib/enet.lib index c10ec1b6b5a514d2f870a10bfb071cf8a6b1c1ba..448d09f2c641bf0f061134db2899ebe7b0ee6342 100644 GIT binary patch delta 17836 zcmbt+4}4U`wg25@69Qel0Tu`lA>aizbj1WCWDUyZuaO4bgd`w;1S_tHK{447RPbiA zy9qbL*3gUn`6^c0+Sc0EqM`4J^=T3?8}Pk0VzsD!HuTqOu0cf+4XEUO&&=JMAo||# z_v!M<-gD2KIdkUBnKNh3%<_j53H?SwTY7SCR&LgUtlhKjP}fUR-dFyvoi0fu|BA*) z(m(U(e@Bu={yp9(N%6m{jZt#tws8yiP`uYukX9{D*ZQ) zj?uT;SL@q1Ow~`=r|VOa94WWmR=ck5w!1dyf7ozYyEo~8jq4$6k>0p(QhVyCg^45I zzdI&>LQ>igKKi~()AWu@>uo`O;q(rhqJK7h?zfz*Oi8o#uu8?*o;hQFLgK)zHhuL> zWyXkt?A~ioUD|qSaJvFdk|ejx*MBr~inHHdNBqC@!|jHLy4Gz8s!> zerO0CRN5=%f7@nD&>y(s(VJFA|CN}BPCBB6Zhs5{_+y0${Cf`nc1e=2pGcyGInn!* zHM_#!zR2!4m;x-Q?Wlfe@#$Y_{jAz$>kS=F^&D?_O1~@XukygywvnIqitMd+btqYq zrlG1+8apZuEd?~5TgUY(c-Ypo13FZ9%VF(0~O=kavb8sc86efRlM6 zRe;hs^ix1nIP?ynsT^{SjzhVCCUD$3Ku!)d0Gi05W(#`Qf}XUXzXF=X>7K>ZQ$^qB zekSpn5<;=ypJ&BZmPA@&Chu1_22HN5O~$G{t3s-?pG@0g1{z zNs@Fam-T6V^P+ZV26SPQG9;J;K0m`>M~d#fW~yyz`;EC1FPLGCc|S=ImYvII;I-HG znwHMrr{v}?%o#RySPecoXltJS+kKPAwV^`?fLTv+;IkU$zC?erC{3UL`Pv&J9on_}Go^F%XG`)f`4*;t);}8)Q;Iqx zy6w72(?$XHgg0=Xf2aj+4CY&c4&oaFqi0{|p4nQR;nzxLX)t3)s80?Jj*`Pc5QYXv z2bP47ZM#|DblucZ?5?!P`}KBx#&r|FZQKv1fcfKRoFn%GV#a_MxPYA!K6dXiy2%M=&+F%|Tdo#MUaeU2`IfUH z#qH}KkEx7_2KL(V)iN>5wCjk$PC+7{6BRV(K){+x4$_-ju^9 zf%dUNyRU*I;VeaOAr72N279g#6pc|mw(Wfl59BZVyP@FW-g)SItZbg;q>i?P4 z7zZMZ09&It*>)wBEq6!j+@6o+a61^W0d^vTy} zs>|Jh4e+ThQgVSEigx>=Ei`VXd@X%|g>F(cGy(_jL`RIiFNcPFz7_1c;l5BmI63uW zB<%svqRt^!S)Fw)mvl&6kWeEO_+75M$@^tOk8_ho#8cc53 zGo(a_IJ!0`o95-FGHzxN7PApHC5Ia@PI$GW!#U`<{UE#_`c{(ggrxiyneFc`vnsA~|f()Gt$G|Hfr=xdt8-dB+tW4(Xk3Xe543&1E^vAN|Zo-UJRRkgv<4_sySLr z>kYn3h9T^gbEC_0JTJ@P7r}={2YyhD&uBS3i*yD}6Me1I_%Bo- z*UDDgJu0e1sR}%$r%P@Q0_II{-YvCwtvyaIQy^otFMDEg%W9yFw=u>vGvx4}0I{`M z(JHs+)qp~{+DQYe{B0Jay2aGitAP~WOswIZ>>*<^c!W->rY=YYKOi>6F0&=M`2oBe z3Wk=;(tI~wQLm4vNZMG#w}u<|3vZyF7{3@N=xUf{5y&l109`w7L|5bxoTfTN6<@CZ zqoGkX%p6Z8Cc8sm&l+`vJ?j`$IAf>Va}Dr?#gT<{Qm zdyWS#YqN}6Gh**-hV`Q}we3Zm@z{b2*9E6BL2@!>kVx zKd%qV#4F6TOmnf^$WVQ^RgThuXXCA?9lRO(MlY{8F}9yps$h)1J?HCZ4=n%R z7yc|L@oN`;-j|ffk>Pb;rG;>Um zqU3o=4*d-%R_~7PaQ~AssogAfsg}wv5XzLPJ}0^(=bz;NKd?uaLocatpKi9)g;