diff options
-rw-r--r-- | libs/enet/CMakeLists.txt | 112 | ||||
-rw-r--r-- | libs/enet/ChangeLog | 61 | ||||
-rw-r--r-- | libs/enet/LICENSE | 2 | ||||
-rw-r--r-- | libs/enet/README | 2 | ||||
-rw-r--r-- | libs/enet/callbacks.c | 6 | ||||
-rw-r--r-- | libs/enet/design.txt | 117 | ||||
-rw-r--r-- | libs/enet/host.c | 108 | ||||
-rw-r--r-- | libs/enet/include/enet/enet.h | 80 | ||||
-rw-r--r-- | libs/enet/include/enet/protocol.h | 11 | ||||
-rw-r--r-- | libs/enet/include/enet/unix.h | 12 | ||||
-rw-r--r-- | libs/enet/include/enet/win32.h | 15 | ||||
-rw-r--r-- | libs/enet/packet.c | 14 | ||||
-rw-r--r-- | libs/enet/peer.c | 212 | ||||
-rw-r--r-- | libs/enet/protocol.c | 374 | ||||
-rw-r--r-- | libs/enet/unix.c | 149 | ||||
-rw-r--r-- | libs/enet/win32.c | 92 |
16 files changed, 895 insertions, 472 deletions
diff --git a/libs/enet/CMakeLists.txt b/libs/enet/CMakeLists.txt index 714d9c03..ce6dc8ff 100644 --- a/libs/enet/CMakeLists.txt +++ b/libs/enet/CMakeLists.txt @@ -1,55 +1,57 @@ -INCLUDE(CheckFunctionExists) -CHECK_FUNCTION_EXISTS(gethostbyaddr_r HAS_GETHOSTBYNAME_R) -IF(HAS_GETHOSTBYNAME_R EQUAL 1) - SET (FLAGS "${FLAGS} -DHAS_GETHOSTBYADDR_R") -ENDIF() - -CHECK_FUNCTION_EXISTS(poll HAS_POLL) -IF(HAS_POLL EQUAL 1) - SET (FLAGS "${FLAGS} -DHAS_POLL") -ENDIF() - -CHECK_FUNCTION_EXISTS(fcntl HAS_FCNTL) -IF(HAS_FCNTL) - SET (FLAGS "${FLAGS} -DHAS_FCNTL") -ENDIF() - -CHECK_FUNCTION_EXISTS(inet_pton HAS_INETPTON) -IF(HAS_INETPTON EQUAL 1) - SET (FLAGS "${FLAGS} -DHAS_INETPTON") -ENDIF() - -CHECK_FUNCTION_EXISTS(inet_ntop HAS_INETNTOP) -IF(HAS_INETNTOP EQUAL 1) - SET (FLAGS "${FLAGS} -DHAS_INETNTOP") -ENDIF() - -INCLUDE(CheckTypeSize) -SET (CMAKE_EXTRA_INCLUDE_FILES sys/socket.h) -CHECK_TYPE_SIZE(socklen_t SOCKLEN_T) -IF(HAVE_SOCKLEN_T) - SET (FLAGS "${FLAGS} -DHAS_SOCKLEN_T") -ENDIF() - -INCLUDE(CheckStructHasMember) -CHECK_STRUCT_HAS_MEMBER("struct msghdr" msg_flags sys/socket.h HAS_MSGHDR_FLAGS) -IF(HAS_MSGHDR_FLAGS EQUAL 1) - SET (FLAGS "${FLAGS} -DHAS_MSGHDR_FLAGS") -ENDIF() - -SET (SRCS - callbacks.c - compress.c - host.c - list.c - packet.c - peer.c - protocol.c - unix.c - win32.c - ) - -INCLUDE_DIRECTORIES("include") - -ADD_LIBRARY(enet STATIC ${SRCS}) -SET_TARGET_PROPERTIES(enet PROPERTIES COMPILE_FLAGS "${FLAGS}")
\ No newline at end of file +cmake_minimum_required(VERSION 2.6) + +project(enet) + +# The "configure" step. +include(CheckFunctionExists) +include(CheckStructHasMember) +include(CheckTypeSize) +check_function_exists("fcntl" HAS_FCNTL) +check_function_exists("poll" HAS_POLL) +check_function_exists("gethostbyname_r" HAS_GETHOSTBYNAME_R) +check_function_exists("gethostbyaddr_r" HAS_GETHOSTBYADDR_R) +check_function_exists("inet_pton" HAS_INET_PTON) +check_function_exists("inet_ntop" HAS_INET_NTOP) +check_struct_has_member("struct msghdr" "msg_flags" "sys/types.h;sys/socket.h" HAS_MSGHDR_FLAGS) +set(CMAKE_EXTRA_INCLUDE_FILES "sys/types.h" "sys/socket.h") +check_type_size("socklen_t" HAS_SOCKLEN_T BUILTIN_TYPES_ONLY) +unset(CMAKE_EXTRA_INCLUDE_FILES) + +if(HAS_FCNTL) + add_definitions(-DHAS_FCNTL=1) +endif() +if(HAS_POLL) + add_definitions(-DHAS_POLL=1) +endif() +if(HAS_GETHOSTBYNAME_R) + add_definitions(-DHAS_GETHOSTBYNAME_R=1) +endif() +if(HAS_GETHOSTBYADDR_R) + add_definitions(-DHAS_GETHOSTBYADDR_R=1) +endif() +if(HAS_INET_PTON) + add_definitions(-DHAS_INET_PTON=1) +endif() +if(HAS_INET_NTOP) + add_definitions(-DHAS_INET_NTOP=1) +endif() +if(HAS_MSGHDR_FLAGS) + add_definitions(-DHAS_MSGHDR_FLAGS=1) +endif() +if(HAS_SOCKLEN_T) + add_definitions(-DHAS_SOCKLEN_T=1) +endif() + +include_directories(${PROJECT_SOURCE_DIR}/include) + +add_library(enet STATIC + callbacks.c + compress.c + host.c + list.c + packet.c + peer.c + protocol.c + unix.c + win32.c + ) diff --git a/libs/enet/ChangeLog b/libs/enet/ChangeLog index 861d51f5..9386a01b 100644 --- a/libs/enet/ChangeLog +++ b/libs/enet/ChangeLog @@ -1,3 +1,64 @@ +ENet 1.3.13 (April 30, 2015): + +* miscellaneous bug fixes +* added premake and cmake support +* miscellaneous documentation cleanups + +ENet 1.3.12 (April 24, 2014): + +* added maximumPacketSize and maximumWaitingData fields to ENetHost to limit the amount of +data waiting to be delivered on a peer (beware that the default maximumPacketSize is +32MB and should be set higher if desired as should maximumWaitingData) + +ENet 1.3.11 (December 26, 2013): + +* allow an ENetHost to connect to itself +* fixed possible bug with disconnect notifications during connect attempts +* fixed some preprocessor definition bugs + +ENet 1.3.10 (October 23, 2013); + +* doubled maximum reliable window size +* fixed RCVTIMEO/SNDTIMEO socket options and also added NODELAY + +ENet 1.3.9 (August 19, 2013): + +* added duplicatePeers option to ENetHost which can limit the number of peers from duplicate IPs +* added enet_socket_get_option() and ENET_SOCKOPT_ERROR +* added enet_host_random_seed() platform stub + +ENet 1.3.8 (June 2, 2013): + +* added enet_linked_version() for checking the linked version +* added enet_socket_get_address() for querying the local address of a socket +* silenced some debugging prints unless ENET_DEBUG is defined during compilation +* handle EINTR in enet_socket_wait() so that enet_host_service() doesn't propagate errors from signals +* optimized enet_host_bandwidth_throttle() to be less expensive for large numbers of peers + +ENet 1.3.7 (March 6, 2013): + +* added ENET_PACKET_FLAG_SENT to indicate that a packet is being freed because it has been sent +* added userData field to ENetPacket +* changed how random seed is generated on Windows to avoid import warnings +* fixed case where disconnects could be generated with no preceding connect event + +ENet 1.3.6 (December 11, 2012): + +* added support for intercept callback in ENetHost that can be used to process raw packets before ENet +* added enet_socket_shutdown() for issuing shutdown on a socket +* fixed enet_socket_connect() to not error on non-blocking connects +* fixed bug in MTU negotiation during connections + +ENet 1.3.5 (July 31, 2012): + +* fixed bug in unreliable packet fragment queuing + +ENet 1.3.4 (May 29, 2012): + +* added enet_peer_ping_interval() for configuring per-peer ping intervals +* added enet_peer_timeout() for configuring per-peer timeouts +* added protocol packet size limits + ENet 1.3.3 (June 28, 2011): * fixed bug with simultaneous disconnects not dispatching events diff --git a/libs/enet/LICENSE b/libs/enet/LICENSE index 357a4e5c..436053ef 100644 --- a/libs/enet/LICENSE +++ b/libs/enet/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2002-2011 Lee Salzman +Copyright (c) 2002-2015 Lee Salzman Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: diff --git a/libs/enet/README b/libs/enet/README index 7f7a0ad0..54b2d213 100644 --- a/libs/enet/README +++ b/libs/enet/README @@ -1,7 +1,7 @@ Please visit the ENet homepage at http://enet.bespin.org for installation and usage instructions. -If you obtained this package from CVS, the quick description on how to build +If you obtained this package from github, the quick description on how to build is: # Generate the build system. diff --git a/libs/enet/callbacks.c b/libs/enet/callbacks.c index f9412825..b3990af1 100644 --- a/libs/enet/callbacks.c +++ b/libs/enet/callbacks.c @@ -27,6 +27,12 @@ enet_initialize_with_callbacks (ENetVersion version, const ENetCallbacks * inits return enet_initialize (); } + +ENetVersion +enet_linked_version (void) +{ + return ENET_VERSION; +} void * enet_malloc (size_t size) diff --git a/libs/enet/design.txt b/libs/enet/design.txt deleted file mode 100644 index 9a88dba9..00000000 --- a/libs/enet/design.txt +++ /dev/null @@ -1,117 +0,0 @@ -* Why ENet? - - ENet evolved specifically as a UDP networking layer for the multiplayer -first person shooter Cube. Cube necessitated low latency communcation with -data sent out very frequently, so TCP was an unsuitable choice due to its -high latency and stream orientation. UDP, however, lacks many sometimes -necessary features from TCP such as reliability, sequencing, unrestricted -packet sizes, and connection management. So UDP by itself was not suitable -as a network protocol either. No suitable freely available networking -libraries existed at the time of ENet's creation to fill this niche. - - UDP and TCP could have been used together in Cube to benefit somewhat -from both of their features, however, the resulting combinations of protocols -still leaves much to be desired. TCP lacks multiple streams of communication -without resorting to opening many sockets and complicates delineation of -packets due to its buffering behavior. UDP lacks sequencing, connection -management, management of bandwidth resources, and imposes limitations on -the size of packets. A significant investment is required to integrate these -two protocols, and the end result is worse off in features and performance -than the uniform protocol presented by ENet. - - ENet thus attempts to address these issues and provide a single, uniform -protocol layered over UDP to the developer with the best features of UDP and -TCP as well as some useful features neither provide, with a much cleaner -integration than any resulting from a mixture of UDP and TCP. - -* Connection management - - ENet provides a simple connection interface over which to communicate -with a foreign host. The liveness of the connection is actively monitored -by pinging the foreign host at frequent intervals, and also monitors the -network conditions from the local host to the foreign host such as the -mean round trip time and packet loss in this fashion. - -* Sequencing - - Rather than a single byte stream that complicates the delineation -of packets, ENet presents connections as multiple, properly sequenced packet -streams that simplify the transfer of various types of data. - - ENet provides sequencing for all packets by assigning to each sent -packet a sequence number that is incremented as packets are sent. ENet -guarentees that no packet with a higher sequence number will be delivered -before a packet with a lower sequence number, thus ensuring packets are -delivered exactly in the order they are sent. - - For unreliable packets, ENet will simply discard the lower sequence -number packet if a packet with a higher sequence number has already been -delivered. This allows the packets to be dispatched immediately as they -arrive, and reduce latency of unreliable packets to an absolute minimum. -For reliable packets, if a higher sequence number packet arrives, but the -preceding packets in the sequence have not yet arrived, ENet will stall -delivery of the higher sequence number packets until its predecessors -have arrived. - -* Channels - - Since ENet will stall delivery of reliable packets to ensure proper -sequencing, and consequently any packets of higher sequence number whether -reliable or unreliable, in the event the reliable packet's predecessors -have not yet arrived, this can introduce latency into the delivery of other -packets which may not need to be as strictly ordered with respect to the -packet that stalled their delivery. - - To combat this latency and reduce the ordering restrictions on packets, -ENet provides multiple channels of communication over a given connection. -Each channel is independently sequenced, and so the delivery status of -a packet in one channel will not stall the delivery of other packets -in another channel. - -* Reliability - - ENet provides optional reliability of packet delivery by ensuring the -foreign host acknowledges receipt of all reliable packets. ENet will attempt -to resend the packet up to a reasonable amount of times, if no acknowledgement -of the packet's receipt happens within a specified timeout. Retry timeouts -are progressive and become more lenient with every failed attempt to allow -for temporary turbulence in network conditions. - -* Fragmentation and reassembly - - ENet will send and deliver packets regardless of size. Large packets are -fragmented into many smaller packets of suitable size, and reassembled on -the foreign host to recover the original packet for delivery. The process -is entirely transparent to the developer. - -* Aggregation - - ENet aggregates all protocol commands, including acknowledgements and -packet transfer, into larger protocol packets to ensure the proper utilization -of the connection and to limit the opportunities for packet loss that might -otherwise result in further delivery latency. - -* Adaptability - - ENet provides an in-flight data window for reliable packets to ensure -connections are not overwhelmed by volumes of packets. It also provides a -static bandwidth allocation mechanism to ensure the total volume of packets -sent and received to a host don't exceed the host's capabilities. Further, -ENet also provides a dynamic throttle that responds to deviations from normal -network connections to rectify various types of network congestion by further -limiting the volume of packets sent. - -* Portability - - ENet works on Windows and any other Unix or Unix-like platform providing -a BSD sockets interface. The library has a small and stable code base that -can easily be extended to support other platforms and integrates easily. - -* Freedom - - ENet demands no royalties and doesn't carry a viral license that would -restrict you in how you might use it in your programs. ENet is licensed under -a short-and-sweet MIT-style license, which gives you the freedom to do anything -you want with it (well, almost anything). - - diff --git a/libs/enet/host.c b/libs/enet/host.c index c44f2ed3..3be6c092 100644 --- a/libs/enet/host.c +++ b/libs/enet/host.c @@ -4,7 +4,6 @@ */ #define ENET_BUILDING_LIB 1 #include <string.h> -#include <time.h> #include "enet/enet.h" /** @defgroup host ENet host functions @@ -38,6 +37,7 @@ enet_host_create (const ENetAddress * address, size_t peerCount, size_t channelL host = (ENetHost *) enet_malloc (sizeof (ENetHost)); if (host == NULL) return NULL; + memset (host, 0, sizeof (ENetHost)); host -> peers = (ENetPeer *) enet_malloc (peerCount * sizeof (ENetPeer)); if (host -> peers == NULL) @@ -65,7 +65,7 @@ enet_host_create (const ENetAddress * address, size_t peerCount, size_t channelL enet_socket_set_option (host -> socket, ENET_SOCKOPT_RCVBUF, ENET_HOST_RECEIVE_BUFFER_SIZE); enet_socket_set_option (host -> socket, ENET_SOCKOPT_SNDBUF, ENET_HOST_SEND_BUFFER_SIZE); - if (address != NULL) + if (address != NULL && enet_socket_get_address (host -> socket, & host -> address) < 0) host -> address = * address; if (! channelLimit || channelLimit > ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT) @@ -74,7 +74,8 @@ enet_host_create (const ENetAddress * address, size_t peerCount, size_t channelL if (channelLimit < ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT) channelLimit = ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT; - host -> randomSeed = (enet_uint32) time(NULL) + (enet_uint32) (size_t) host; + host -> randomSeed = (enet_uint32) (size_t) host; + host -> randomSeed += enet_host_random_seed (); host -> randomSeed = (host -> randomSeed << 16) | (host -> randomSeed >> 16); host -> channelLimit = channelLimit; host -> incomingBandwidth = incomingBandwidth; @@ -96,11 +97,19 @@ enet_host_create (const ENetAddress * address, size_t peerCount, size_t channelL host -> totalReceivedData = 0; host -> totalReceivedPackets = 0; + host -> connectedPeers = 0; + host -> bandwidthLimitedPeers = 0; + host -> duplicatePeers = ENET_PROTOCOL_MAXIMUM_PEER_ID; + host -> maximumPacketSize = ENET_HOST_DEFAULT_MAXIMUM_PACKET_SIZE; + host -> maximumWaitingData = ENET_HOST_DEFAULT_MAXIMUM_WAITING_DATA; + host -> compressor.context = NULL; host -> compressor.compress = NULL; host -> compressor.decompress = NULL; host -> compressor.destroy = NULL; + host -> intercept = NULL; + enet_list_clear (& host -> dispatchQueue); for (currentPeer = host -> peers; @@ -133,6 +142,9 @@ enet_host_destroy (ENetHost * host) { ENetPeer * currentPeer; + if (host == NULL) + return; + enet_socket_destroy (host -> socket); for (currentPeer = host -> peers; @@ -317,46 +329,44 @@ enet_host_bandwidth_throttle (ENetHost * host) { enet_uint32 timeCurrent = enet_time_get (), elapsedTime = timeCurrent - host -> bandwidthThrottleEpoch, - peersTotal = 0, - dataTotal = 0, - peersRemaining, - bandwidth, + peersRemaining = (enet_uint32) host -> connectedPeers, + dataTotal = ~0, + bandwidth = ~0, throttle = 0, bandwidthLimit = 0; - int needsAdjustment; + int needsAdjustment = host -> bandwidthLimitedPeers > 0 ? 1 : 0; ENetPeer * peer; ENetProtocol command; if (elapsedTime < ENET_HOST_BANDWIDTH_THROTTLE_INTERVAL) return; - for (peer = host -> peers; - peer < & host -> peers [host -> peerCount]; - ++ peer) - { - if (peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER) - continue; - - ++ peersTotal; - dataTotal += peer -> outgoingDataTotal; - } + host -> bandwidthThrottleEpoch = timeCurrent; - if (peersTotal == 0) + if (peersRemaining == 0) return; - peersRemaining = peersTotal; - needsAdjustment = 1; + if (host -> outgoingBandwidth != 0) + { + dataTotal = 0; + bandwidth = (host -> outgoingBandwidth * elapsedTime) / 1000; - if (host -> outgoingBandwidth == 0) - bandwidth = ~0; - else - bandwidth = (host -> outgoingBandwidth * elapsedTime) / 1000; + for (peer = host -> peers; + peer < & host -> peers [host -> peerCount]; + ++ peer) + { + if (peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER) + continue; + + dataTotal += peer -> outgoingDataTotal; + } + } while (peersRemaining > 0 && needsAdjustment != 0) { needsAdjustment = 0; - if (dataTotal < bandwidth) + if (dataTotal <= bandwidth) throttle = ENET_PEER_PACKET_THROTTLE_SCALE; else throttle = (bandwidth * ENET_PEER_PACKET_THROTTLE_SCALE) / dataTotal; @@ -387,7 +397,9 @@ enet_host_bandwidth_throttle (ENetHost * host) peer -> outgoingBandwidthThrottleEpoch = timeCurrent; - + peer -> incomingDataTotal = 0; + peer -> outgoingDataTotal = 0; + needsAdjustment = 1; -- peersRemaining; bandwidth -= peerBandwidth; @@ -396,25 +408,35 @@ enet_host_bandwidth_throttle (ENetHost * host) } if (peersRemaining > 0) - for (peer = host -> peers; - peer < & host -> peers [host -> peerCount]; - ++ peer) { - if ((peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER) || - peer -> outgoingBandwidthThrottleEpoch == timeCurrent) - continue; + if (dataTotal <= bandwidth) + throttle = ENET_PEER_PACKET_THROTTLE_SCALE; + else + throttle = (bandwidth * ENET_PEER_PACKET_THROTTLE_SCALE) / dataTotal; + + for (peer = host -> peers; + peer < & host -> peers [host -> peerCount]; + ++ peer) + { + if ((peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER) || + peer -> outgoingBandwidthThrottleEpoch == timeCurrent) + continue; - peer -> packetThrottleLimit = throttle; + peer -> packetThrottleLimit = throttle; - if (peer -> packetThrottle > peer -> packetThrottleLimit) - peer -> packetThrottle = peer -> packetThrottleLimit; + if (peer -> packetThrottle > peer -> packetThrottleLimit) + peer -> packetThrottle = peer -> packetThrottleLimit; + + peer -> incomingDataTotal = 0; + peer -> outgoingDataTotal = 0; + } } - + if (host -> recalculateBandwidthLimits) { host -> recalculateBandwidthLimits = 0; - peersRemaining = peersTotal; + peersRemaining = (enet_uint32) host -> connectedPeers; bandwidth = host -> incomingBandwidth; needsAdjustment = 1; @@ -465,16 +487,6 @@ enet_host_bandwidth_throttle (ENetHost * host) enet_peer_queue_outgoing_command (peer, & command, NULL, 0, 0); } } - - host -> bandwidthThrottleEpoch = timeCurrent; - - for (peer = host -> peers; - peer < & host -> peers [host -> peerCount]; - ++ peer) - { - peer -> incomingDataTotal = 0; - peer -> outgoingDataTotal = 0; - } } /** @} */ diff --git a/libs/enet/include/enet/enet.h b/libs/enet/include/enet/enet.h index 741e87b4..5e21ee8e 100644 --- a/libs/enet/include/enet/enet.h +++ b/libs/enet/include/enet/enet.h @@ -25,12 +25,19 @@ extern "C" #define ENET_VERSION_MAJOR 1 #define ENET_VERSION_MINOR 3 -#define ENET_VERSION_PATCH 3 +#define ENET_VERSION_PATCH 13 #define ENET_VERSION_CREATE(major, minor, patch) (((major)<<16) | ((minor)<<8) | (patch)) +#define ENET_VERSION_GET_MAJOR(version) (((version)>>16)&0xFF) +#define ENET_VERSION_GET_MINOR(version) (((version)>>8)&0xFF) +#define ENET_VERSION_GET_PATCH(version) ((version)&0xFF) #define ENET_VERSION ENET_VERSION_CREATE(ENET_VERSION_MAJOR, ENET_VERSION_MINOR, ENET_VERSION_PATCH) typedef enet_uint32 ENetVersion; +struct _ENetHost; +struct _ENetEvent; +struct _ENetPacket; + typedef enum _ENetSocketType { ENET_SOCKET_TYPE_STREAM = 1, @@ -39,9 +46,10 @@ typedef enum _ENetSocketType typedef enum _ENetSocketWait { - ENET_SOCKET_WAIT_NONE = 0, - ENET_SOCKET_WAIT_SEND = (1 << 0), - ENET_SOCKET_WAIT_RECEIVE = (1 << 1) + ENET_SOCKET_WAIT_NONE = 0, + ENET_SOCKET_WAIT_SEND = (1 << 0), + ENET_SOCKET_WAIT_RECEIVE = (1 << 1), + ENET_SOCKET_WAIT_INTERRUPT = (1 << 2) } ENetSocketWait; typedef enum _ENetSocketOption @@ -50,16 +58,23 @@ typedef enum _ENetSocketOption ENET_SOCKOPT_BROADCAST = 2, ENET_SOCKOPT_RCVBUF = 3, ENET_SOCKOPT_SNDBUF = 4, - ENET_SOCKOPT_REUSEADDR = 5 + ENET_SOCKOPT_REUSEADDR = 5, + ENET_SOCKOPT_RCVTIMEO = 6, + ENET_SOCKOPT_SNDTIMEO = 7, + ENET_SOCKOPT_ERROR = 8, + ENET_SOCKOPT_NODELAY = 9 } ENetSocketOption; -enum +typedef enum _ENetSocketShutdown { - ENET_HOST_ANY = 0, /**< specifies the default server host */ - ENET_HOST_BROADCAST = 0xFFFFFFFF, /**< specifies a subnet-wide broadcast */ + ENET_SOCKET_SHUTDOWN_READ = 0, + ENET_SOCKET_SHUTDOWN_WRITE = 1, + ENET_SOCKET_SHUTDOWN_READ_WRITE = 2 +} ENetSocketShutdown; - ENET_PORT_ANY = 0 /**< specifies that a port should be automatically chosen */ -}; +#define ENET_HOST_ANY 0 +#define ENET_HOST_BROADCAST 0xFFFFFFFFU +#define ENET_PORT_ANY 0 /** * Portable internet address structure. @@ -99,10 +114,12 @@ typedef enum _ENetPacketFlag 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) + ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT = (1 << 3), + + /** whether the packet has been sent from all queues it has been entered into */ + ENET_PACKET_FLAG_SENT = (1<<8) } ENetPacketFlag; -struct _ENetPacket; typedef void (ENET_CALLBACK * ENetPacketFreeCallback) (struct _ENetPacket *); /** @@ -131,6 +148,7 @@ typedef struct _ENetPacket enet_uint8 * data; /**< allocated data for packet */ size_t dataLength; /**< length of data */ ENetPacketFreeCallback freeCallback; /**< function to be called when the packet is no longer in use */ + void * userData; /**< application private data, may be freely modified */ } ENetPacket; typedef struct _ENetAcknowledgement @@ -191,6 +209,8 @@ enum ENET_HOST_SEND_BUFFER_SIZE = 256 * 1024, ENET_HOST_BANDWIDTH_THROTTLE_INTERVAL = 1000, ENET_HOST_DEFAULT_MTU = 1400, + ENET_HOST_DEFAULT_MAXIMUM_PACKET_SIZE = 32 * 1024 * 1024, + ENET_HOST_DEFAULT_MAXIMUM_WAITING_DATA = 32 * 1024 * 1024, ENET_PEER_DEFAULT_ROUND_TRIP_TIME = 500, ENET_PEER_DEFAULT_PACKET_THROTTLE = 32, @@ -267,6 +287,10 @@ typedef struct _ENetPeer enet_uint32 packetThrottleAcceleration; enet_uint32 packetThrottleDeceleration; enet_uint32 packetThrottleInterval; + enet_uint32 pingInterval; + enet_uint32 timeoutLimit; + enet_uint32 timeoutMinimum; + enet_uint32 timeoutMaximum; enet_uint32 lastRoundTripTime; enet_uint32 lowestRoundTripTime; enet_uint32 lastRoundTripTimeVariance; @@ -288,6 +312,7 @@ typedef struct _ENetPeer enet_uint16 outgoingUnsequencedGroup; enet_uint32 unsequencedWindow [ENET_PEER_UNSEQUENCED_WINDOW_SIZE / 32]; enet_uint32 eventData; + size_t totalWaitingData; } ENetPeer; /** An ENet packet compressor for compressing UDP packets before socket sends or receives. @@ -306,6 +331,9 @@ typedef struct _ENetCompressor /** Callback that computes the checksum of the data held in buffers[0:bufferCount-1] */ typedef enet_uint32 (ENET_CALLBACK * ENetChecksumCallback) (const ENetBuffer * buffers, size_t bufferCount); + +/** Callback for intercepting received raw UDP packets. Should return 1 to intercept, 0 to ignore, or -1 to propagate an error. */ +typedef int (ENET_CALLBACK * ENetInterceptCallback) (struct _ENetHost * host, struct _ENetEvent * event); /** An ENet host for communicating with peers. * @@ -355,6 +383,12 @@ typedef struct _ENetHost enet_uint32 totalSentPackets; /**< total UDP packets sent, user should reset to 0 as needed to prevent overflow */ enet_uint32 totalReceivedData; /**< total data received, user should reset to 0 as needed to prevent overflow */ enet_uint32 totalReceivedPackets; /**< total UDP packets received, user should reset to 0 as needed to prevent overflow */ + ENetInterceptCallback intercept; /**< callback the user can set to intercept received raw UDP packets */ + size_t connectedPeers; + size_t bandwidthLimitedPeers; + size_t duplicatePeers; /**< optional number of allowed peers from duplicate IPs, defaults to ENET_PROTOCOL_MAXIMUM_PEER_ID */ + size_t maximumPacketSize; /**< the maximum allowable packet size that may be sent or received on a peer */ + size_t maximumWaitingData; /**< the maximum aggregate amount of buffer space a peer may use waiting for packets to be delivered */ } ENetHost; /** @@ -417,7 +451,7 @@ ENET_API int enet_initialize (void); Initializes ENet globally and supplies user-overridden callbacks. Must be called prior to using any functions in ENet. Do not use enet_initialize() if you use this variant. Make sure the ENetCallbacks structure is zeroed out so that any additional callbacks added in future versions will be properly ignored. @param version the constant ENET_VERSION should be supplied so ENet knows which version of ENetCallbacks struct to use - @param inits user-overriden callbacks where any NULL callbacks will use ENet's defaults + @param inits user-overridden callbacks where any NULL callbacks will use ENet's defaults @returns 0 on success, < 0 on failure */ ENET_API int enet_initialize_with_callbacks (ENetVersion version, const ENetCallbacks * inits); @@ -428,6 +462,12 @@ ENET_API int enet_initialize_with_callbacks (ENetVersion version, const ENetCall */ ENET_API void enet_deinitialize (void); +/** + Gives the linked version of the ENet library. + @returns the version number +*/ +ENET_API ENetVersion enet_linked_version (void); + /** @} */ /** @defgroup private ENet private implementation functions */ @@ -447,6 +487,7 @@ ENET_API void enet_time_set (enet_uint32); */ ENET_API ENetSocket enet_socket_create (ENetSocketType); ENET_API int enet_socket_bind (ENetSocket, const ENetAddress *); +ENET_API int enet_socket_get_address (ENetSocket, ENetAddress *); ENET_API int enet_socket_listen (ENetSocket, int); ENET_API ENetSocket enet_socket_accept (ENetSocket, ENetAddress *); ENET_API int enet_socket_connect (ENetSocket, const ENetAddress *); @@ -454,6 +495,8 @@ ENET_API int enet_socket_send (ENetSocket, const ENetAddress *, const ENe ENET_API int enet_socket_receive (ENetSocket, ENetAddress *, ENetBuffer *, size_t); ENET_API int enet_socket_wait (ENetSocket, enet_uint32 *, enet_uint32); ENET_API int enet_socket_set_option (ENetSocket, ENetSocketOption, int); +ENET_API int enet_socket_get_option (ENetSocket, ENetSocketOption, int *); +ENET_API int enet_socket_shutdown (ENetSocket, ENetSocketShutdown); ENET_API void enet_socket_destroy (ENetSocket); ENET_API int enet_socketset_select (ENetSocket, ENetSocketSet *, ENetSocketSet *, enet_uint32); @@ -472,7 +515,7 @@ ENET_API int enet_socketset_select (ENetSocket, ENetSocketSet *, ENetSock */ ENET_API int enet_address_set_host (ENetAddress * address, const char * hostName); -/** Gives the printable form of the ip address specified in the address parameter. +/** Gives the printable form of the IP address specified in the address parameter. @param address address printed @param hostName destination for name, must not be NULL @param nameLength maximum length of hostName. @@ -497,7 +540,7 @@ ENET_API int enet_address_get_host (const ENetAddress * address, char * hostName 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 enet_uint32 enet_crc32 (const ENetBuffer *, size_t); ENET_API ENetHost * enet_host_create (const ENetAddress *, size_t, size_t, enet_uint32, enet_uint32); ENET_API void enet_host_destroy (ENetHost *); @@ -511,10 +554,13 @@ ENET_API int enet_host_compress_with_range_coder (ENetHost * host); ENET_API void enet_host_channel_limit (ENetHost *, size_t); ENET_API void enet_host_bandwidth_limit (ENetHost *, enet_uint32, enet_uint32); extern void enet_host_bandwidth_throttle (ENetHost *); +extern enet_uint32 enet_host_random_seed (void); ENET_API int enet_peer_send (ENetPeer *, enet_uint8, ENetPacket *); ENET_API ENetPacket * enet_peer_receive (ENetPeer *, enet_uint8 * channelID); ENET_API void enet_peer_ping (ENetPeer *); +ENET_API void enet_peer_ping_interval (ENetPeer *, enet_uint32); +ENET_API void enet_peer_timeout (ENetPeer *, enet_uint32, enet_uint32, enet_uint32); 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); @@ -524,10 +570,12 @@ extern int enet_peer_throttle (ENetPeer *, enet_uint32); extern void enet_peer_reset_queues (ENetPeer *); extern void enet_peer_setup_outgoing_command (ENetPeer *, ENetOutgoingCommand *); 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 ENetIncomingCommand * enet_peer_queue_incoming_command (ENetPeer *, const ENetProtocol *, const void *, size_t, enet_uint32, enet_uint32); extern ENetAcknowledgement * enet_peer_queue_acknowledgement (ENetPeer *, const ENetProtocol *, enet_uint16); extern void enet_peer_dispatch_incoming_unreliable_commands (ENetPeer *, ENetChannel *); extern void enet_peer_dispatch_incoming_reliable_commands (ENetPeer *, ENetChannel *); +extern void enet_peer_on_connect (ENetPeer *); +extern void enet_peer_on_disconnect (ENetPeer *); ENET_API void * enet_range_coder_create (void); ENET_API void enet_range_coder_destroy (void *); diff --git a/libs/enet/include/enet/protocol.h b/libs/enet/include/enet/protocol.h index faef9179..f8c73d8a 100644 --- a/libs/enet/include/enet/protocol.h +++ b/libs/enet/include/enet/protocol.h @@ -13,10 +13,11 @@ enum ENET_PROTOCOL_MAXIMUM_MTU = 4096, ENET_PROTOCOL_MAXIMUM_PACKET_COMMANDS = 32, ENET_PROTOCOL_MINIMUM_WINDOW_SIZE = 4096, - ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE = 32768, + ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE = 65536, ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT = 1, ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT = 255, - ENET_PROTOCOL_MAXIMUM_PEER_ID = 0xFFF + ENET_PROTOCOL_MAXIMUM_PEER_ID = 0xFFF, + ENET_PROTOCOL_MAXIMUM_FRAGMENT_COUNT = 1024 * 1024 }; typedef enum _ENetProtocolCommand @@ -52,10 +53,10 @@ typedef enum _ENetProtocolFlag ENET_PROTOCOL_HEADER_SESSION_SHIFT = 12 } ENetProtocolFlag; -#ifdef _MSC_VER_ +#ifdef _MSC_VER #pragma pack(push, 1) #define ENET_PACKED -#elif defined(__GNUC__) +#elif defined(__GNUC__) || defined(__clang__) #define ENET_PACKED __attribute__ ((packed)) #else #define ENET_PACKED @@ -189,7 +190,7 @@ typedef union _ENetProtocol ENetProtocolThrottleConfigure throttleConfigure; } ENET_PACKED ENetProtocol; -#ifdef _MSC_VER_ +#ifdef _MSC_VER #pragma pack(pop) #endif diff --git a/libs/enet/include/enet/unix.h b/libs/enet/include/enet/unix.h index 087015e5..a59e3406 100644 --- a/libs/enet/include/enet/unix.h +++ b/libs/enet/include/enet/unix.h @@ -8,15 +8,17 @@ #include <stdlib.h> #include <sys/time.h> #include <sys/types.h> +#include <sys/socket.h> #include <netinet/in.h> #include <unistd.h> +#ifdef MSG_MAXIOVLEN +#define ENET_BUFFER_MAXIMUM MSG_MAXIOVLEN +#endif + typedef int ENetSocket; -enum -{ - ENET_SOCKET_NULL = -1 -}; +#define ENET_SOCKET_NULL -1 #define ENET_HOST_TO_NET_16(value) (htons (value)) /**< macro that converts host to net byte-order of a 16-bit value */ #define ENET_HOST_TO_NET_32(value) (htonl (value)) /**< macro that converts host to net byte-order of a 32-bit value */ @@ -38,7 +40,7 @@ typedef fd_set ENetSocketSet; #define ENET_SOCKETSET_EMPTY(sockset) FD_ZERO (& (sockset)) #define ENET_SOCKETSET_ADD(sockset, socket) FD_SET (socket, & (sockset)) -#define ENET_SOCKETSET_REMOVE(sockset, socket) FD_CLEAR (socket, & (sockset)) +#define ENET_SOCKETSET_REMOVE(sockset, socket) FD_CLR (socket, & (sockset)) #define ENET_SOCKETSET_CHECK(sockset, socket) FD_ISSET (socket, & (sockset)) #endif /* __ENET_UNIX_H__ */ diff --git a/libs/enet/include/enet/win32.h b/libs/enet/include/enet/win32.h index 0e1cf0c5..e73ca9d0 100644 --- a/libs/enet/include/enet/win32.h +++ b/libs/enet/include/enet/win32.h @@ -5,11 +5,13 @@ #ifndef __ENET_WIN32_H__ #define __ENET_WIN32_H__ +#ifdef _MSC_VER #ifdef ENET_BUILDING_LIB -#pragma warning (disable: 4996) // 'strncpy' was declared deprecated #pragma warning (disable: 4267) // size_t to int conversion #pragma warning (disable: 4244) // 64bit to 32bit int #pragma warning (disable: 4018) // signed/unsigned mismatch +#pragma warning (disable: 4146) // unary minus operator applied to unsigned type +#endif #endif #include <stdlib.h> @@ -17,10 +19,7 @@ typedef SOCKET ENetSocket; -enum -{ - ENET_SOCKET_NULL = INVALID_SOCKET -}; +#define ENET_SOCKET_NULL INVALID_SOCKET #define ENET_HOST_TO_NET_16(value) (htons (value)) #define ENET_HOST_TO_NET_32(value) (htonl (value)) @@ -36,8 +35,8 @@ typedef struct #define ENET_CALLBACK __cdecl -#if defined ENET_DLL -#if defined ENET_BUILDING_LIB +#ifdef ENET_DLL +#ifdef ENET_BUILDING_LIB #define ENET_API __declspec( dllexport ) #else #define ENET_API __declspec( dllimport ) @@ -50,7 +49,7 @@ typedef fd_set ENetSocketSet; #define ENET_SOCKETSET_EMPTY(sockset) FD_ZERO (& (sockset)) #define ENET_SOCKETSET_ADD(sockset, socket) FD_SET (socket, & (sockset)) -#define ENET_SOCKETSET_REMOVE(sockset, socket) FD_CLEAR (socket, & (sockset)) +#define ENET_SOCKETSET_REMOVE(sockset, socket) FD_CLR (socket, & (sockset)) #define ENET_SOCKETSET_CHECK(sockset, socket) FD_ISSET (socket, & (sockset)) #endif /* __ENET_WIN32_H__ */ diff --git a/libs/enet/packet.c b/libs/enet/packet.c index 2fc9a10e..5fa78b28 100644 --- a/libs/enet/packet.c +++ b/libs/enet/packet.c @@ -11,7 +11,7 @@ */ /** Creates a packet that may be sent to a peer. - @param dataContents initial contents of the packet's data; the packet's data will remain uninitialized if dataContents is NULL. + @param data initial contents of the packet's data; the packet's data will remain uninitialized if data is NULL. @param dataLength size of the data allocated for this packet @param flags flags for this packet as described for the ENetPacket structure. @returns the packet on success, NULL on failure @@ -26,6 +26,9 @@ enet_packet_create (const void * data, size_t dataLength, enet_uint32 flags) if (flags & ENET_PACKET_FLAG_NO_ALLOCATE) packet -> data = (enet_uint8 *) data; else + if (dataLength <= 0) + packet -> data = NULL; + else { packet -> data = (enet_uint8 *) enet_malloc (dataLength); if (packet -> data == NULL) @@ -42,6 +45,7 @@ enet_packet_create (const void * data, size_t dataLength, enet_uint32 flags) packet -> flags = flags; packet -> dataLength = dataLength; packet -> freeCallback = NULL; + packet -> userData = NULL; return packet; } @@ -52,9 +56,13 @@ enet_packet_create (const void * data, size_t dataLength, enet_uint32 flags) void enet_packet_destroy (ENetPacket * packet) { + if (packet == NULL) + return; + if (packet -> freeCallback != NULL) (* packet -> freeCallback) (packet); - if (! (packet -> flags & ENET_PACKET_FLAG_NO_ALLOCATE)) + if (! (packet -> flags & ENET_PACKET_FLAG_NO_ALLOCATE) && + packet -> data != NULL) enet_free (packet -> data); enet_free (packet); } @@ -108,7 +116,7 @@ reflect_crc (int val, int bits) } static void -initialize_crc32 () +initialize_crc32 (void) { int byte; diff --git a/libs/enet/peer.c b/libs/enet/peer.c index 566f7978..e2d0872b 100644 --- a/libs/enet/peer.c +++ b/libs/enet/peer.c @@ -25,7 +25,7 @@ the mean round trip time measured over the interval, then the throttle probability is decreased to limit traffic by an amount specified in the deceleration parameter, which is a ratio to the ENET_PEER_PACKET_THROTTLE_SCALE constant. When the throttle has - a value of ENET_PEER_PACKET_THROTTLE_SCALE, on unreliable packets are dropped by + a value of ENET_PEER_PACKET_THROTTLE_SCALE, no unreliable packets are dropped by ENet, and so 100% of all unreliable packets will be sent. When the throttle has a value of 0, all unreliable packets are dropped by ENet, and so 0% of all unreliable packets will be sent. Intermediate values for the throttle represent intermediate @@ -104,7 +104,8 @@ enet_peer_send (ENetPeer * peer, enet_uint8 channelID, ENetPacket * packet) size_t fragmentLength; if (peer -> state != ENET_PEER_STATE_CONNECTED || - channelID >= peer -> channelCount) + channelID >= peer -> channelCount || + packet -> dataLength > peer -> host -> maximumPacketSize) return -1; fragmentLength = peer -> mtu - sizeof (ENetProtocolHeader) - sizeof (ENetProtocolSendFragment); @@ -113,7 +114,7 @@ enet_peer_send (ENetPeer * peer, enet_uint8 channelID, ENetPacket * packet) if (packet -> dataLength > fragmentLength) { - enet_uint32 fragmentCount = ENET_HOST_TO_NET_32 ((packet -> dataLength + fragmentLength - 1) / fragmentLength), + enet_uint32 fragmentCount = (packet -> dataLength + fragmentLength - 1) / fragmentLength, fragmentNumber, fragmentOffset; enet_uint8 commandNumber; @@ -121,6 +122,9 @@ enet_peer_send (ENetPeer * peer, enet_uint8 channelID, ENetPacket * packet) ENetList fragments; ENetOutgoingCommand * fragment; + if (fragmentCount > ENET_PROTOCOL_MAXIMUM_FRAGMENT_COUNT) + return -1; + if ((packet -> flags & (ENET_PACKET_FLAG_RELIABLE | ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT)) == ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT && channel -> outgoingUnreliableSequenceNumber < 0xFFFF) { @@ -164,7 +168,7 @@ enet_peer_send (ENetPeer * peer, enet_uint8 channelID, ENetPacket * packet) fragment -> command.header.channelID = channelID; fragment -> command.sendFragment.startSequenceNumber = startSequenceNumber; fragment -> command.sendFragment.dataLength = ENET_HOST_TO_NET_16 (fragmentLength); - fragment -> command.sendFragment.fragmentCount = fragmentCount; + fragment -> command.sendFragment.fragmentCount = ENET_HOST_TO_NET_32 (fragmentCount); fragment -> command.sendFragment.fragmentNumber = ENET_HOST_TO_NET_32 (fragmentNumber); fragment -> command.sendFragment.totalLength = ENET_HOST_TO_NET_32 (packet -> dataLength); fragment -> command.sendFragment.fragmentOffset = ENET_NET_TO_HOST_32 (fragmentOffset); @@ -237,6 +241,8 @@ enet_peer_receive (ENetPeer * peer, enet_uint8 * channelID) enet_free (incomingCommand); + peer -> totalWaitingData -= packet -> dataLength; + return packet; } @@ -292,7 +298,7 @@ enet_peer_remove_incoming_commands (ENetList * queue, ENetListIterator startComm static void enet_peer_reset_incoming_commands (ENetList * queue) { - enet_peer_remove_incoming_commands(queue, enet_list_begin (queue), enet_list_end(queue)); + enet_peer_remove_incoming_commands(queue, enet_list_begin (queue), enet_list_end (queue)); } void @@ -333,6 +339,30 @@ enet_peer_reset_queues (ENetPeer * peer) peer -> channelCount = 0; } +void +enet_peer_on_connect (ENetPeer * peer) +{ + if (peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER) + { + if (peer -> incomingBandwidth != 0) + ++ peer -> host -> bandwidthLimitedPeers; + + ++ peer -> host -> connectedPeers; + } +} + +void +enet_peer_on_disconnect (ENetPeer * peer) +{ + if (peer -> state == ENET_PEER_STATE_CONNECTED || peer -> state == ENET_PEER_STATE_DISCONNECT_LATER) + { + if (peer -> incomingBandwidth != 0) + -- peer -> host -> bandwidthLimitedPeers; + + -- peer -> host -> connectedPeers; + } +} + /** Forcefully disconnects a peer. @param peer peer to forcefully disconnect @remarks The foreign host represented by the peer is not notified of the disconnection and will timeout @@ -341,6 +371,8 @@ enet_peer_reset_queues (ENetPeer * peer) void enet_peer_reset (ENetPeer * peer) { + enet_peer_on_disconnect (peer); + peer -> outgoingPeerID = ENET_PROTOCOL_MAXIMUM_PEER_ID; peer -> connectID = 0; @@ -368,6 +400,10 @@ enet_peer_reset (ENetPeer * peer) peer -> packetThrottleAcceleration = ENET_PEER_PACKET_THROTTLE_ACCELERATION; peer -> packetThrottleDeceleration = ENET_PEER_PACKET_THROTTLE_DECELERATION; peer -> packetThrottleInterval = ENET_PEER_PACKET_THROTTLE_INTERVAL; + peer -> pingInterval = ENET_PEER_PING_INTERVAL; + peer -> timeoutLimit = ENET_PEER_TIMEOUT_LIMIT; + peer -> timeoutMinimum = ENET_PEER_TIMEOUT_MINIMUM; + peer -> timeoutMaximum = ENET_PEER_TIMEOUT_MAXIMUM; peer -> lastRoundTripTime = ENET_PEER_DEFAULT_ROUND_TRIP_TIME; peer -> lowestRoundTripTime = ENET_PEER_DEFAULT_ROUND_TRIP_TIME; peer -> lastRoundTripTimeVariance = 0; @@ -381,6 +417,7 @@ enet_peer_reset (ENetPeer * peer) peer -> incomingUnsequencedGroup = 0; peer -> outgoingUnsequencedGroup = 0; peer -> eventData = 0; + peer -> totalWaitingData = 0; memset (peer -> unsequencedWindow, 0, sizeof (peer -> unsequencedWindow)); @@ -390,7 +427,7 @@ enet_peer_reset (ENetPeer * peer) /** Sends a ping request to a peer. @param peer destination for the ping request @remarks ping requests factor into the mean round trip time as designated by the - roundTripTime field in the ENetPeer structure. Enet automatically pings all connected + roundTripTime field in the ENetPeer structure. ENet automatically pings all connected peers at regular intervals, however, this function may be called to ensure more frequent ping requests. */ @@ -408,11 +445,51 @@ enet_peer_ping (ENetPeer * peer) enet_peer_queue_outgoing_command (peer, & command, NULL, 0, 0); } +/** Sets the interval at which pings will be sent to a peer. + + Pings are used both to monitor the liveness of the connection and also to dynamically + adjust the throttle during periods of low traffic so that the throttle has reasonable + responsiveness during traffic spikes. + + @param peer the peer to adjust + @param pingInterval the interval at which to send pings; defaults to ENET_PEER_PING_INTERVAL if 0 +*/ +void +enet_peer_ping_interval (ENetPeer * peer, enet_uint32 pingInterval) +{ + peer -> pingInterval = pingInterval ? pingInterval : ENET_PEER_PING_INTERVAL; +} + +/** Sets the timeout parameters for a peer. + + The timeout parameter control how and when a peer will timeout from a failure to acknowledge + reliable traffic. Timeout values use an exponential backoff mechanism, where if a reliable + packet is not acknowledge within some multiple of the average RTT plus a variance tolerance, + the timeout will be doubled until it reaches a set limit. If the timeout is thus at this + limit and reliable packets have been sent but not acknowledged within a certain minimum time + period, the peer will be disconnected. Alternatively, if reliable packets have been sent + but not acknowledged for a certain maximum time period, the peer will be disconnected regardless + of the current timeout limit value. + + @param peer the peer to adjust + @param timeoutLimit the timeout limit; defaults to ENET_PEER_TIMEOUT_LIMIT if 0 + @param timeoutMinimum the timeout minimum; defaults to ENET_PEER_TIMEOUT_MINIMUM if 0 + @param timeoutMaximum the timeout maximum; defaults to ENET_PEER_TIMEOUT_MAXIMUM if 0 +*/ + +void +enet_peer_timeout (ENetPeer * peer, enet_uint32 timeoutLimit, enet_uint32 timeoutMinimum, enet_uint32 timeoutMaximum) +{ + peer -> timeoutLimit = timeoutLimit ? timeoutLimit : ENET_PEER_TIMEOUT_LIMIT; + peer -> timeoutMinimum = timeoutMinimum ? timeoutMinimum : ENET_PEER_TIMEOUT_MINIMUM; + peer -> timeoutMaximum = timeoutMaximum ? timeoutMaximum : ENET_PEER_TIMEOUT_MAXIMUM; +} + /** Force an immediate disconnection from a peer. @param peer peer to disconnect @param data data describing the disconnection @remarks No ENET_EVENT_DISCONNECT event will be generated. The foreign peer is not - guarenteed to receive the disconnect notification, and is reset immediately upon + guaranteed to receive the disconnect notification, and is reset immediately upon return from this function. */ void @@ -471,7 +548,11 @@ enet_peer_disconnect (ENetPeer * peer, enet_uint32 data) enet_peer_queue_outgoing_command (peer, & command, NULL, 0, 0); if (peer -> state == ENET_PEER_STATE_CONNECTED || peer -> state == ENET_PEER_STATE_DISCONNECT_LATER) - peer -> state = ENET_PEER_STATE_DISCONNECTING; + { + enet_peer_on_disconnect (peer); + + peer -> state = ENET_PEER_STATE_DISCONNECTING; + } else { enet_host_flush (peer -> host); @@ -536,7 +617,7 @@ void enet_peer_setup_outgoing_command (ENetPeer * peer, ENetOutgoingCommand * outgoingCommand) { ENetChannel * channel = & peer -> channels [outgoingCommand -> command.header.channelID]; - + peer -> outgoingDataTotal += enet_protocol_command_size (outgoingCommand -> command.header.command) + outgoingCommand -> fragmentLength; if (outgoingCommand -> command.header.channelID == 0xFF) @@ -630,42 +711,71 @@ enet_peer_dispatch_incoming_unreliable_commands (ENetPeer * peer, ENetChannel * 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 + + if (incomingCommand -> reliableSequenceNumber == channel -> incomingReliableSequenceNumber) { - enet_list_move (enet_list_end (& peer -> dispatchedCommands), startCommand, enet_list_previous (currentCommand)); + if (incomingCommand -> fragmentsRemaining <= 0) + { + channel -> incomingUnreliableSequenceNumber = incomingCommand -> unreliableSequenceNumber; + continue; + } - if (! peer -> needsDispatch) - { + if (startCommand != currentCommand) + { + 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 = currentCommand; + } + else + if (droppedCommand != currentCommand) + droppedCommand = enet_list_previous (currentCommand); + } + else + { + enet_uint16 reliableWindow = incomingCommand -> reliableSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE, + currentWindow = channel -> incomingReliableSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE; + if (incomingCommand -> reliableSequenceNumber < channel -> incomingReliableSequenceNumber) + reliableWindow += ENET_PEER_RELIABLE_WINDOWS; + if (reliableWindow >= currentWindow && reliableWindow < currentWindow + ENET_PEER_FREE_RELIABLE_WINDOWS - 1) + break; + + droppedCommand = enet_list_next (currentCommand); - droppedCommand = startCommand = enet_list_next (currentCommand); + if (startCommand != currentCommand) + { + 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; + } + } } + + startCommand = enet_list_next (currentCommand); } if (startCommand != currentCommand) { - enet_list_move (enet_list_end (& peer -> dispatchedCommands), startCommand, enet_list_previous (currentCommand)); + 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); + if (! peer -> needsDispatch) + { + enet_list_insert (enet_list_end (& peer -> host -> dispatchQueue), & peer -> dispatchList); - peer -> needsDispatch = 1; - } + peer -> needsDispatch = 1; + } - droppedCommand = startCommand = enet_list_next (currentCommand); + droppedCommand = currentCommand; } enet_peer_remove_incoming_commands (& channel -> incomingUnreliableCommands, enet_list_begin (& channel -> incomingUnreliableCommands), droppedCommand); @@ -706,22 +816,24 @@ enet_peer_dispatch_incoming_reliable_commands (ENetPeer * peer, ENetChannel * ch peer -> needsDispatch = 1; } - enet_peer_dispatch_incoming_unreliable_commands (peer, channel); + if (! enet_list_empty (& channel -> incomingUnreliableCommands)) + enet_peer_dispatch_incoming_unreliable_commands (peer, channel); } ENetIncomingCommand * -enet_peer_queue_incoming_command (ENetPeer * peer, const ENetProtocol * command, ENetPacket * packet, enet_uint32 fragmentCount) +enet_peer_queue_incoming_command (ENetPeer * peer, const ENetProtocol * command, const void * data, size_t dataLength, enet_uint32 flags, enet_uint32 fragmentCount) { static ENetIncomingCommand dummyCommand; ENetChannel * channel = & peer -> channels [command -> header.channelID]; - enet_uint32 unreliableSequenceNumber = 0, reliableSequenceNumber; + enet_uint32 unreliableSequenceNumber = 0, reliableSequenceNumber = 0; enet_uint16 reliableWindow, currentWindow; ENetIncomingCommand * incomingCommand; ENetListIterator currentCommand; + ENetPacket * packet = NULL; if (peer -> state == ENET_PEER_STATE_DISCONNECT_LATER) - goto freePacket; + goto discardCommand; if ((command -> header.command & ENET_PROTOCOL_COMMAND_MASK) != ENET_PROTOCOL_COMMAND_SEND_UNSEQUENCED) { @@ -733,7 +845,7 @@ enet_peer_queue_incoming_command (ENetPeer * peer, const ENetProtocol * command, reliableWindow += ENET_PEER_RELIABLE_WINDOWS; if (reliableWindow < currentWindow || reliableWindow >= currentWindow + ENET_PEER_FREE_RELIABLE_WINDOWS - 1) - goto freePacket; + goto discardCommand; } switch (command -> header.command & ENET_PROTOCOL_COMMAND_MASK) @@ -741,7 +853,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 discardCommand; for (currentCommand = enet_list_previous (enet_list_end (& channel -> incomingReliableCommands)); currentCommand != enet_list_end (& channel -> incomingReliableCommands); @@ -763,7 +875,7 @@ enet_peer_queue_incoming_command (ENetPeer * peer, const ENetProtocol * command, if (incomingCommand -> reliableSequenceNumber < reliableSequenceNumber) break; - goto freePacket; + goto discardCommand; } } break; @@ -774,7 +886,7 @@ enet_peer_queue_incoming_command (ENetPeer * peer, const ENetProtocol * command, if (reliableSequenceNumber == channel -> incomingReliableSequenceNumber && unreliableSequenceNumber <= channel -> incomingUnreliableSequenceNumber) - goto freePacket; + goto discardCommand; for (currentCommand = enet_list_previous (enet_list_end (& channel -> incomingUnreliableCommands)); currentCommand != enet_list_end (& channel -> incomingUnreliableCommands); @@ -805,7 +917,7 @@ enet_peer_queue_incoming_command (ENetPeer * peer, const ENetProtocol * command, if (incomingCommand -> unreliableSequenceNumber < unreliableSequenceNumber) break; - goto freePacket; + goto discardCommand; } } break; @@ -815,9 +927,16 @@ enet_peer_queue_incoming_command (ENetPeer * peer, const ENetProtocol * command, break; default: - goto freePacket; + goto discardCommand; } + if (peer -> totalWaitingData >= peer -> host -> maximumWaitingData) + goto notifyError; + + packet = enet_packet_create (data, dataLength, flags); + if (packet == NULL) + goto notifyError; + incomingCommand = (ENetIncomingCommand *) enet_malloc (sizeof (ENetIncomingCommand)); if (incomingCommand == NULL) goto notifyError; @@ -832,7 +951,8 @@ enet_peer_queue_incoming_command (ENetPeer * peer, const ENetProtocol * command, if (fragmentCount > 0) { - incomingCommand -> fragments = (enet_uint32 *) enet_malloc ((fragmentCount + 31) / 32 * sizeof (enet_uint32)); + if (fragmentCount <= ENET_PROTOCOL_MAXIMUM_FRAGMENT_COUNT) + incomingCommand -> fragments = (enet_uint32 *) enet_malloc ((fragmentCount + 31) / 32 * sizeof (enet_uint32)); if (incomingCommand -> fragments == NULL) { enet_free (incomingCommand); @@ -843,7 +963,11 @@ enet_peer_queue_incoming_command (ENetPeer * peer, const ENetProtocol * command, } if (packet != NULL) - ++ packet -> referenceCount; + { + ++ packet -> referenceCount; + + peer -> totalWaitingData += packet -> dataLength; + } enet_list_insert (enet_list_next (currentCommand), incomingCommand); @@ -861,7 +985,7 @@ enet_peer_queue_incoming_command (ENetPeer * peer, const ENetProtocol * command, return incomingCommand; -freePacket: +discardCommand: if (fragmentCount > 0) goto notifyError; diff --git a/libs/enet/protocol.c b/libs/enet/protocol.c index da64e915..29d64873 100644 --- a/libs/enet/protocol.c +++ b/libs/enet/protocol.c @@ -32,6 +32,30 @@ enet_protocol_command_size (enet_uint8 commandNumber) return commandSizes [commandNumber & ENET_PROTOCOL_COMMAND_MASK]; } +static void +enet_protocol_change_state (ENetHost * host, ENetPeer * peer, ENetPeerState state) +{ + if (state == ENET_PEER_STATE_CONNECTED || state == ENET_PEER_STATE_DISCONNECT_LATER) + enet_peer_on_connect (peer); + else + enet_peer_on_disconnect (peer); + + peer -> state = state; +} + +static void +enet_protocol_dispatch_state (ENetHost * host, ENetPeer * peer, ENetPeerState state) +{ + enet_protocol_change_state (host, peer, state); + + if (! peer -> needsDispatch) + { + enet_list_insert (enet_list_end (& host -> dispatchQueue), & peer -> dispatchList); + + peer -> needsDispatch = 1; + } +} + static int enet_protocol_dispatch_incoming_commands (ENetHost * host, ENetEvent * event) { @@ -45,7 +69,7 @@ enet_protocol_dispatch_incoming_commands (ENetHost * host, ENetEvent * event) { case ENET_PEER_STATE_CONNECTION_PENDING: case ENET_PEER_STATE_CONNECTION_SUCCEEDED: - peer -> state = ENET_PEER_STATE_CONNECTED; + enet_protocol_change_state (host, peer, ENET_PEER_STATE_CONNECTED); event -> type = ENET_EVENT_TYPE_CONNECT; event -> peer = peer; @@ -83,6 +107,9 @@ enet_protocol_dispatch_incoming_commands (ENetHost * host, ENetEvent * event) } return 1; + + default: + break; } } @@ -90,26 +117,13 @@ enet_protocol_dispatch_incoming_commands (ENetHost * host, ENetEvent * event) } static void -enet_protocol_dispatch_state (ENetHost * host, ENetPeer * peer, ENetPeerState state) -{ - peer -> state = state; - - if (! peer -> needsDispatch) - { - enet_list_insert (enet_list_end (& host -> dispatchQueue), & peer -> dispatchList); - - peer -> needsDispatch = 1; - } -} - -static void enet_protocol_notify_connect (ENetHost * host, ENetPeer * peer, ENetEvent * event) { host -> recalculateBandwidthLimits = 1; if (event != NULL) { - peer -> state = ENET_PEER_STATE_CONNECTED; + enet_protocol_change_state (host, peer, ENET_PEER_STATE_CONNECTED); event -> type = ENET_EVENT_TYPE_CONNECT; event -> peer = peer; @@ -160,7 +174,11 @@ enet_protocol_remove_sent_unreliable_commands (ENetPeer * peer) -- outgoingCommand -> packet -> referenceCount; if (outgoingCommand -> packet -> referenceCount == 0) - enet_packet_destroy (outgoingCommand -> packet); + { + outgoingCommand -> packet -> flags |= ENET_PACKET_FLAG_SENT; + + enet_packet_destroy (outgoingCommand -> packet); + } } enet_free (outgoingCommand); @@ -170,7 +188,7 @@ enet_protocol_remove_sent_unreliable_commands (ENetPeer * peer) static ENetProtocolCommand enet_protocol_remove_sent_reliable_command (ENetPeer * peer, enet_uint16 reliableSequenceNumber, enet_uint8 channelID) { - ENetOutgoingCommand * outgoingCommand; + ENetOutgoingCommand * outgoingCommand = NULL; ENetListIterator currentCommand; ENetProtocolCommand commandNumber; int wasSent = 1; @@ -207,6 +225,9 @@ enet_protocol_remove_sent_reliable_command (ENetPeer * peer, enet_uint16 reliabl wasSent = 0; } + if (outgoingCommand == NULL) + return ENET_PROTOCOL_COMMAND_NONE; + if (channelID < peer -> channelCount) { ENetChannel * channel = & peer -> channels [channelID]; @@ -231,7 +252,11 @@ enet_protocol_remove_sent_reliable_command (ENetPeer * peer, enet_uint16 reliabl -- outgoingCommand -> packet -> referenceCount; if (outgoingCommand -> packet -> referenceCount == 0) - enet_packet_destroy (outgoingCommand -> packet); + { + outgoingCommand -> packet -> flags |= ENET_PACKET_FLAG_SENT; + + enet_packet_destroy (outgoingCommand -> packet); + } } enet_free (outgoingCommand); @@ -252,8 +277,8 @@ enet_protocol_handle_connect (ENetHost * host, ENetProtocolHeader * header, ENet enet_uint8 incomingSessionID, outgoingSessionID; enet_uint32 mtu, windowSize; ENetChannel * channel; - size_t channelCount; - ENetPeer * currentPeer; + size_t channelCount, duplicatePeers = 0; + ENetPeer * currentPeer, * peer = NULL; ENetProtocol verifyCommand; channelCount = ENET_NET_TO_HOST_32 (command -> connect.channelCount); @@ -266,55 +291,57 @@ enet_protocol_handle_connect (ENetHost * host, ENetProtocolHeader * header, ENet currentPeer < & host -> peers [host -> peerCount]; ++ currentPeer) { - if (currentPeer -> state != ENET_PEER_STATE_DISCONNECTED && - currentPeer -> address.host == host -> receivedAddress.host && - currentPeer -> address.port == host -> receivedAddress.port && - currentPeer -> connectID == command -> connect.connectID) - return NULL; - } - - for (currentPeer = host -> peers; - currentPeer < & host -> peers [host -> peerCount]; - ++ currentPeer) - { if (currentPeer -> state == ENET_PEER_STATE_DISCONNECTED) - break; + { + if (peer == NULL) + peer = currentPeer; + } + else + if (currentPeer -> state != ENET_PEER_STATE_CONNECTING && + currentPeer -> address.host == host -> receivedAddress.host) + { + if (currentPeer -> address.port == host -> receivedAddress.port && + currentPeer -> connectID == command -> connect.connectID) + return NULL; + + ++ duplicatePeers; + } } - if (currentPeer >= & host -> peers [host -> peerCount]) + if (peer == NULL || duplicatePeers >= host -> duplicatePeers) return NULL; if (channelCount > host -> channelLimit) channelCount = host -> channelLimit; - currentPeer -> channels = (ENetChannel *) enet_malloc (channelCount * sizeof (ENetChannel)); - if (currentPeer -> channels == NULL) + peer -> channels = (ENetChannel *) enet_malloc (channelCount * sizeof (ENetChannel)); + if (peer -> channels == NULL) return NULL; - currentPeer -> channelCount = channelCount; - currentPeer -> state = ENET_PEER_STATE_ACKNOWLEDGING_CONNECT; - currentPeer -> connectID = command -> connect.connectID; - currentPeer -> address = host -> receivedAddress; - currentPeer -> outgoingPeerID = ENET_NET_TO_HOST_16 (command -> connect.outgoingPeerID); - currentPeer -> incomingBandwidth = ENET_NET_TO_HOST_32 (command -> connect.incomingBandwidth); - currentPeer -> outgoingBandwidth = ENET_NET_TO_HOST_32 (command -> connect.outgoingBandwidth); - currentPeer -> packetThrottleInterval = ENET_NET_TO_HOST_32 (command -> connect.packetThrottleInterval); - currentPeer -> packetThrottleAcceleration = ENET_NET_TO_HOST_32 (command -> connect.packetThrottleAcceleration); - currentPeer -> packetThrottleDeceleration = ENET_NET_TO_HOST_32 (command -> connect.packetThrottleDeceleration); - currentPeer -> eventData = ENET_NET_TO_HOST_32 (command -> connect.data); - - incomingSessionID = command -> connect.incomingSessionID == 0xFF ? currentPeer -> outgoingSessionID : command -> connect.incomingSessionID; + peer -> channelCount = channelCount; + peer -> state = ENET_PEER_STATE_ACKNOWLEDGING_CONNECT; + peer -> connectID = command -> connect.connectID; + peer -> address = host -> receivedAddress; + peer -> outgoingPeerID = ENET_NET_TO_HOST_16 (command -> connect.outgoingPeerID); + peer -> incomingBandwidth = ENET_NET_TO_HOST_32 (command -> connect.incomingBandwidth); + peer -> outgoingBandwidth = ENET_NET_TO_HOST_32 (command -> connect.outgoingBandwidth); + peer -> packetThrottleInterval = ENET_NET_TO_HOST_32 (command -> connect.packetThrottleInterval); + peer -> packetThrottleAcceleration = ENET_NET_TO_HOST_32 (command -> connect.packetThrottleAcceleration); + peer -> packetThrottleDeceleration = ENET_NET_TO_HOST_32 (command -> connect.packetThrottleDeceleration); + peer -> eventData = ENET_NET_TO_HOST_32 (command -> connect.data); + + incomingSessionID = command -> connect.incomingSessionID == 0xFF ? peer -> outgoingSessionID : command -> connect.incomingSessionID; incomingSessionID = (incomingSessionID + 1) & (ENET_PROTOCOL_HEADER_SESSION_MASK >> ENET_PROTOCOL_HEADER_SESSION_SHIFT); - if (incomingSessionID == currentPeer -> outgoingSessionID) + if (incomingSessionID == peer -> outgoingSessionID) incomingSessionID = (incomingSessionID + 1) & (ENET_PROTOCOL_HEADER_SESSION_MASK >> ENET_PROTOCOL_HEADER_SESSION_SHIFT); - currentPeer -> outgoingSessionID = incomingSessionID; + peer -> outgoingSessionID = incomingSessionID; - outgoingSessionID = command -> connect.outgoingSessionID == 0xFF ? currentPeer -> incomingSessionID : command -> connect.outgoingSessionID; + outgoingSessionID = command -> connect.outgoingSessionID == 0xFF ? peer -> incomingSessionID : command -> connect.outgoingSessionID; outgoingSessionID = (outgoingSessionID + 1) & (ENET_PROTOCOL_HEADER_SESSION_MASK >> ENET_PROTOCOL_HEADER_SESSION_SHIFT); - if (outgoingSessionID == currentPeer -> incomingSessionID) + if (outgoingSessionID == peer -> incomingSessionID) outgoingSessionID = (outgoingSessionID + 1) & (ENET_PROTOCOL_HEADER_SESSION_MASK >> ENET_PROTOCOL_HEADER_SESSION_SHIFT); - currentPeer -> incomingSessionID = outgoingSessionID; + peer -> incomingSessionID = outgoingSessionID; - for (channel = currentPeer -> channels; - channel < & currentPeer -> channels [channelCount]; + for (channel = peer -> channels; + channel < & peer -> channels [channelCount]; ++ channel) { channel -> outgoingReliableSequenceNumber = 0; @@ -337,27 +364,27 @@ enet_protocol_handle_connect (ENetHost * host, ENetProtocolHeader * header, ENet if (mtu > ENET_PROTOCOL_MAXIMUM_MTU) mtu = ENET_PROTOCOL_MAXIMUM_MTU; - currentPeer -> mtu = mtu; + peer -> mtu = mtu; if (host -> outgoingBandwidth == 0 && - currentPeer -> incomingBandwidth == 0) - currentPeer -> windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE; + peer -> incomingBandwidth == 0) + peer -> windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE; else if (host -> outgoingBandwidth == 0 || - currentPeer -> incomingBandwidth == 0) - currentPeer -> windowSize = (ENET_MAX (host -> outgoingBandwidth, currentPeer -> incomingBandwidth) / + peer -> incomingBandwidth == 0) + peer -> windowSize = (ENET_MAX (host -> outgoingBandwidth, peer -> incomingBandwidth) / ENET_PEER_WINDOW_SIZE_SCALE) * ENET_PROTOCOL_MINIMUM_WINDOW_SIZE; else - currentPeer -> windowSize = (ENET_MIN (host -> outgoingBandwidth, currentPeer -> incomingBandwidth) / + peer -> windowSize = (ENET_MIN (host -> outgoingBandwidth, peer -> incomingBandwidth) / ENET_PEER_WINDOW_SIZE_SCALE) * ENET_PROTOCOL_MINIMUM_WINDOW_SIZE; - if (currentPeer -> windowSize < ENET_PROTOCOL_MINIMUM_WINDOW_SIZE) - currentPeer -> windowSize = ENET_PROTOCOL_MINIMUM_WINDOW_SIZE; + if (peer -> windowSize < ENET_PROTOCOL_MINIMUM_WINDOW_SIZE) + peer -> windowSize = ENET_PROTOCOL_MINIMUM_WINDOW_SIZE; else - if (currentPeer -> windowSize > ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE) - currentPeer -> windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE; + if (peer -> windowSize > ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE) + peer -> windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE; if (host -> incomingBandwidth == 0) windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE; @@ -376,28 +403,27 @@ enet_protocol_handle_connect (ENetHost * host, ENetProtocolHeader * header, ENet verifyCommand.header.command = ENET_PROTOCOL_COMMAND_VERIFY_CONNECT | ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE; verifyCommand.header.channelID = 0xFF; - verifyCommand.verifyConnect.outgoingPeerID = ENET_HOST_TO_NET_16 (currentPeer -> incomingPeerID); + verifyCommand.verifyConnect.outgoingPeerID = ENET_HOST_TO_NET_16 (peer -> incomingPeerID); verifyCommand.verifyConnect.incomingSessionID = incomingSessionID; verifyCommand.verifyConnect.outgoingSessionID = outgoingSessionID; - verifyCommand.verifyConnect.mtu = ENET_HOST_TO_NET_16 (currentPeer -> mtu); + verifyCommand.verifyConnect.mtu = ENET_HOST_TO_NET_32 (peer -> mtu); verifyCommand.verifyConnect.windowSize = ENET_HOST_TO_NET_32 (windowSize); verifyCommand.verifyConnect.channelCount = ENET_HOST_TO_NET_32 (channelCount); verifyCommand.verifyConnect.incomingBandwidth = ENET_HOST_TO_NET_32 (host -> incomingBandwidth); verifyCommand.verifyConnect.outgoingBandwidth = ENET_HOST_TO_NET_32 (host -> outgoingBandwidth); - verifyCommand.verifyConnect.packetThrottleInterval = ENET_HOST_TO_NET_32 (currentPeer -> packetThrottleInterval); - verifyCommand.verifyConnect.packetThrottleAcceleration = ENET_HOST_TO_NET_32 (currentPeer -> packetThrottleAcceleration); - verifyCommand.verifyConnect.packetThrottleDeceleration = ENET_HOST_TO_NET_32 (currentPeer -> packetThrottleDeceleration); - verifyCommand.verifyConnect.connectID = currentPeer -> connectID; + verifyCommand.verifyConnect.packetThrottleInterval = ENET_HOST_TO_NET_32 (peer -> packetThrottleInterval); + verifyCommand.verifyConnect.packetThrottleAcceleration = ENET_HOST_TO_NET_32 (peer -> packetThrottleAcceleration); + verifyCommand.verifyConnect.packetThrottleDeceleration = ENET_HOST_TO_NET_32 (peer -> packetThrottleDeceleration); + verifyCommand.verifyConnect.connectID = peer -> connectID; - enet_peer_queue_outgoing_command (currentPeer, & verifyCommand, NULL, 0, 0); + enet_peer_queue_outgoing_command (peer, & verifyCommand, NULL, 0, 0); - return currentPeer; + return peer; } 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.channelID >= peer -> channelCount || @@ -406,14 +432,12 @@ enet_protocol_handle_send_reliable (ENetHost * host, ENetPeer * peer, const ENet dataLength = ENET_NET_TO_HOST_16 (command -> sendReliable.dataLength); * currentData += dataLength; - if (* currentData > & host -> receivedData [host -> receivedDataLength]) + if (dataLength > host -> maximumPacketSize || + * currentData < host -> receivedData || + * currentData > & host -> receivedData [host -> receivedDataLength]) return -1; - packet = enet_packet_create ((const enet_uint8 *) command + sizeof (ENetProtocolSendReliable), - dataLength, - ENET_PACKET_FLAG_RELIABLE); - if (packet == NULL || - enet_peer_queue_incoming_command (peer, command, packet, 0) == NULL) + if (enet_peer_queue_incoming_command (peer, command, (const enet_uint8 *) command + sizeof (ENetProtocolSendReliable), dataLength, ENET_PACKET_FLAG_RELIABLE, 0) == NULL) return -1; return 0; @@ -422,7 +446,6 @@ enet_protocol_handle_send_reliable (ENetHost * host, ENetPeer * peer, const ENet 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; @@ -432,7 +455,9 @@ enet_protocol_handle_send_unsequenced (ENetHost * host, ENetPeer * peer, const E dataLength = ENET_NET_TO_HOST_16 (command -> sendUnsequenced.dataLength); * currentData += dataLength; - if (* currentData > & host -> receivedData [host -> receivedDataLength]) + if (dataLength > host -> maximumPacketSize || + * currentData < host -> receivedData || + * currentData > & host -> receivedData [host -> receivedDataLength]) return -1; unsequencedGroup = ENET_NET_TO_HOST_16 (command -> sendUnsequenced.unsequencedGroup); @@ -456,11 +481,7 @@ enet_protocol_handle_send_unsequenced (ENetHost * host, ENetPeer * peer, const E if (peer -> unsequencedWindow [index / 32] & (1 << (index % 32))) return 0; - packet = enet_packet_create ((const enet_uint8 *) command + sizeof (ENetProtocolSendUnsequenced), - dataLength, - ENET_PACKET_FLAG_UNSEQUENCED); - if (packet == NULL || - enet_peer_queue_incoming_command (peer, command, packet, 0) == NULL) + if (enet_peer_queue_incoming_command (peer, command, (const enet_uint8 *) command + sizeof (ENetProtocolSendUnsequenced), dataLength, ENET_PACKET_FLAG_UNSEQUENCED, 0) == NULL) return -1; peer -> unsequencedWindow [index / 32] |= 1 << (index % 32); @@ -471,7 +492,6 @@ enet_protocol_handle_send_unsequenced (ENetHost * host, ENetPeer * peer, const E 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.channelID >= peer -> channelCount || @@ -480,14 +500,12 @@ enet_protocol_handle_send_unreliable (ENetHost * host, ENetPeer * peer, const EN dataLength = ENET_NET_TO_HOST_16 (command -> sendUnreliable.dataLength); * currentData += dataLength; - if (* currentData > & host -> receivedData [host -> receivedDataLength]) + if (dataLength > host -> maximumPacketSize || + * currentData < host -> receivedData || + * currentData > & host -> receivedData [host -> receivedDataLength]) return -1; - packet = enet_packet_create ((const enet_uint8 *) command + sizeof (ENetProtocolSendUnreliable), - dataLength, - 0); - if (packet == NULL || - enet_peer_queue_incoming_command (peer, command, packet, 0) == NULL) + if (enet_peer_queue_incoming_command (peer, command, (const enet_uint8 *) command + sizeof (ENetProtocolSendUnreliable), dataLength, 0, 0) == NULL) return -1; return 0; @@ -513,7 +531,9 @@ enet_protocol_handle_send_fragment (ENetHost * host, ENetPeer * peer, const ENet fragmentLength = ENET_NET_TO_HOST_16 (command -> sendFragment.dataLength); * currentData += fragmentLength; - if (* currentData > & host -> receivedData [host -> receivedDataLength]) + if (fragmentLength > host -> maximumPacketSize || + * currentData < host -> receivedData || + * currentData > & host -> receivedData [host -> receivedDataLength]) return -1; channel = & peer -> channels [command -> header.channelID]; @@ -532,9 +552,11 @@ enet_protocol_handle_send_fragment (ENetHost * host, ENetPeer * peer, const ENet 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) + if (fragmentCount > ENET_PROTOCOL_MAXIMUM_FRAGMENT_COUNT || + fragmentNumber >= fragmentCount || + totalLength > host -> maximumPacketSize || + fragmentOffset >= totalLength || + fragmentLength > totalLength - fragmentOffset) return -1; for (currentCommand = enet_list_previous (enet_list_end (& channel -> incomingReliableCommands)); @@ -570,13 +592,10 @@ enet_protocol_handle_send_fragment (ENetHost * host, ENetPeer * peer, const ENet if (startCommand == NULL) { ENetProtocol hostCommand = * command; - ENetPacket * packet = enet_packet_create (NULL, totalLength, ENET_PACKET_FLAG_RELIABLE); - if (packet == NULL) - return -1; hostCommand.header.reliableSequenceNumber = startSequenceNumber; - startCommand = enet_peer_queue_incoming_command (peer, & hostCommand, packet, fragmentCount); + startCommand = enet_peer_queue_incoming_command (peer, & hostCommand, NULL, totalLength, ENET_PACKET_FLAG_RELIABLE, fragmentCount); if (startCommand == NULL) return -1; } @@ -622,7 +641,9 @@ enet_protocol_handle_send_unreliable_fragment (ENetHost * host, ENetPeer * peer, fragmentLength = ENET_NET_TO_HOST_16 (command -> sendFragment.dataLength); * currentData += fragmentLength; - if (* currentData > & host -> receivedData [host -> receivedDataLength]) + if (fragmentLength > host -> maximumPacketSize || + * currentData < host -> receivedData || + * currentData > & host -> receivedData [host -> receivedDataLength]) return -1; channel = & peer -> channels [command -> header.channelID]; @@ -647,9 +668,11 @@ enet_protocol_handle_send_unreliable_fragment (ENetHost * host, ENetPeer * peer, 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) + if (fragmentCount > ENET_PROTOCOL_MAXIMUM_FRAGMENT_COUNT || + fragmentNumber >= fragmentCount || + totalLength > host -> maximumPacketSize || + fragmentOffset >= totalLength || + fragmentLength > totalLength - fragmentOffset) return -1; for (currentCommand = enet_list_previous (enet_list_end (& channel -> incomingUnreliableCommands)); @@ -690,11 +713,7 @@ enet_protocol_handle_send_unreliable_fragment (ENetHost * host, ENetPeer * peer, 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); + startCommand = enet_peer_queue_incoming_command (peer, command, NULL, totalLength, ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT, fragmentCount); if (startCommand == NULL) return -1; } @@ -722,18 +741,34 @@ enet_protocol_handle_send_unreliable_fragment (ENetHost * host, ENetPeer * peer, static int enet_protocol_handle_ping (ENetHost * host, ENetPeer * peer, const ENetProtocol * command) { + if (peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER) + return -1; + return 0; } static int enet_protocol_handle_bandwidth_limit (ENetHost * host, ENetPeer * peer, const ENetProtocol * command) { + if (peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER) + return -1; + + if (peer -> incomingBandwidth != 0) + -- host -> bandwidthLimitedPeers; + 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 -> bandwidthLimitedPeers; + if (peer -> incomingBandwidth == 0 && host -> outgoingBandwidth == 0) peer -> windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE; else + if (peer -> incomingBandwidth == 0 || host -> outgoingBandwidth == 0) + peer -> windowSize = (ENET_MAX (peer -> incomingBandwidth, host -> outgoingBandwidth) / + ENET_PEER_WINDOW_SIZE_SCALE) * ENET_PROTOCOL_MINIMUM_WINDOW_SIZE; + else peer -> windowSize = (ENET_MIN (peer -> incomingBandwidth, host -> outgoingBandwidth) / ENET_PEER_WINDOW_SIZE_SCALE) * ENET_PROTOCOL_MINIMUM_WINDOW_SIZE; @@ -749,6 +784,9 @@ enet_protocol_handle_bandwidth_limit (ENetHost * host, ENetPeer * peer, const EN static int enet_protocol_handle_throttle_configure (ENetHost * host, ENetPeer * peer, const ENetProtocol * command) { + if (peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER) + return -1; + 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); @@ -759,12 +797,12 @@ enet_protocol_handle_throttle_configure (ENetHost * host, ENetPeer * peer, const static int enet_protocol_handle_disconnect (ENetHost * host, ENetPeer * peer, const ENetProtocol * command) { - if (peer -> state == ENET_PEER_STATE_ZOMBIE || peer -> state == ENET_PEER_STATE_ACKNOWLEDGING_DISCONNECT) + if (peer -> state == ENET_PEER_STATE_DISCONNECTED || peer -> state == ENET_PEER_STATE_ZOMBIE || peer -> state == ENET_PEER_STATE_ACKNOWLEDGING_DISCONNECT) return 0; enet_peer_reset_queues (peer); - if (peer -> state == ENET_PEER_STATE_CONNECTION_SUCCEEDED || peer -> state == ENET_PEER_STATE_DISCONNECTING) + if (peer -> state == ENET_PEER_STATE_CONNECTION_SUCCEEDED || peer -> state == ENET_PEER_STATE_DISCONNECTING || peer -> state == ENET_PEER_STATE_CONNECTING) enet_protocol_dispatch_state (host, peer, ENET_PEER_STATE_ZOMBIE); else if (peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER) @@ -775,7 +813,7 @@ enet_protocol_handle_disconnect (ENetHost * host, ENetPeer * peer, const ENetPro } else if (command -> header.command & ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE) - peer -> state = ENET_PEER_STATE_ACKNOWLEDGING_DISCONNECT; + enet_protocol_change_state (host, peer, ENET_PEER_STATE_ACKNOWLEDGING_DISCONNECT); else enet_protocol_dispatch_state (host, peer, ENET_PEER_STATE_ZOMBIE); @@ -793,6 +831,9 @@ enet_protocol_handle_acknowledge (ENetHost * host, ENetEvent * event, ENetPeer * receivedReliableSequenceNumber; ENetProtocolCommand commandNumber; + if (peer -> state == ENET_PEER_STATE_DISCONNECTED || peer -> state == ENET_PEER_STATE_ZOMBIE) + return 0; + receivedSentTime = ENET_NET_TO_HOST_16 (command -> acknowledge.receivedSentTime); receivedSentTime |= host -> serviceTime & 0xFFFF0000; if ((receivedSentTime & 0x8000) > (host -> serviceTime & 0x8000)) @@ -863,6 +904,9 @@ enet_protocol_handle_acknowledge (ENetHost * host, ENetEvent * event, ENetPeer * enet_list_empty (& peer -> sentReliableCommands)) enet_peer_disconnect (peer, peer -> eventData); break; + + default: + break; } return 0; @@ -1042,7 +1086,7 @@ enet_protocol_handle_incoming_commands (ENetHost * host, ENetEvent * event) command -> header.reliableSequenceNumber = ENET_NET_TO_HOST_16 (command -> header.reliableSequenceNumber); - switch (command -> header.command & ENET_PROTOCOL_COMMAND_MASK) + switch (commandNumber) { case ENET_PROTOCOL_COMMAND_ACKNOWLEDGE: if (enet_protocol_handle_acknowledge (host, event, peer, command)) @@ -1050,6 +1094,8 @@ enet_protocol_handle_incoming_commands (ENetHost * host, ENetEvent * event) break; case ENET_PROTOCOL_COMMAND_CONNECT: + if (peer != NULL) + goto commandError; peer = enet_protocol_handle_connect (host, header, command); if (peer == NULL) goto commandError; @@ -1123,6 +1169,8 @@ enet_protocol_handle_incoming_commands (ENetHost * host, ENetEvent * event) { case ENET_PEER_STATE_DISCONNECTING: case ENET_PEER_STATE_ACKNOWLEDGING_CONNECT: + case ENET_PEER_STATE_DISCONNECTED: + case ENET_PEER_STATE_ZOMBIE: break; case ENET_PEER_STATE_ACKNOWLEDGING_DISCONNECT: @@ -1147,7 +1195,9 @@ commandError: static int enet_protocol_receive_incoming_commands (ENetHost * host, ENetEvent * event) { - for (;;) + int packets; + + for (packets = 0; packets < 256; ++ packets) { int receivedLength; ENetBuffer buffer; @@ -1171,7 +1221,25 @@ enet_protocol_receive_incoming_commands (ENetHost * host, ENetEvent * event) host -> totalReceivedData += receivedLength; host -> totalReceivedPackets ++; - + + if (host -> intercept != NULL) + { + switch (host -> intercept (host, event)) + { + case 1: + if (event != NULL && event -> type != ENET_EVENT_TYPE_NONE) + return 1; + + continue; + + case -1: + return -1; + + default: + break; + } + } + switch (enet_protocol_handle_incoming_commands (host, event)) { case 1: @@ -1195,7 +1263,8 @@ enet_protocol_send_acknowledgements (ENetHost * host, ENetPeer * peer) ENetBuffer * buffer = & host -> buffers [host -> bufferCount]; ENetAcknowledgement * acknowledgement; ENetListIterator currentAcknowledgement; - + enet_uint16 reliableSequenceNumber; + currentAcknowledgement = enet_list_begin (& peer -> acknowledgements); while (currentAcknowledgement != enet_list_end (& peer -> acknowledgements)) @@ -1217,10 +1286,13 @@ enet_protocol_send_acknowledgements (ENetHost * host, ENetPeer * peer) buffer -> dataLength = sizeof (ENetProtocolAcknowledge); host -> packetSize += buffer -> dataLength; - + + reliableSequenceNumber = ENET_HOST_TO_NET_16 (acknowledgement -> command.header.reliableSequenceNumber); + command -> header.command = ENET_PROTOCOL_COMMAND_ACKNOWLEDGE; command -> header.channelID = acknowledgement -> command.header.channelID; - command -> acknowledge.receivedReliableSequenceNumber = ENET_HOST_TO_NET_16 (acknowledgement -> command.header.reliableSequenceNumber); + command -> header.reliableSequenceNumber = reliableSequenceNumber; + command -> acknowledge.receivedReliableSequenceNumber = reliableSequenceNumber; command -> acknowledge.receivedSentTime = ENET_HOST_TO_NET_16 (acknowledgement -> sentTime); if ((acknowledgement -> command.header.command & ENET_PROTOCOL_COMMAND_MASK) == ENET_PROTOCOL_COMMAND_DISCONNECT) @@ -1361,9 +1433,9 @@ enet_protocol_check_timeouts (ENetHost * host, ENetPeer * peer, ENetEvent * even peer -> earliestTimeout = outgoingCommand -> sentTime; if (peer -> earliestTimeout != 0 && - (ENET_TIME_DIFFERENCE (host -> serviceTime, peer -> earliestTimeout) >= ENET_PEER_TIMEOUT_MAXIMUM || + (ENET_TIME_DIFFERENCE (host -> serviceTime, peer -> earliestTimeout) >= peer -> timeoutMaximum || (outgoingCommand -> roundTripTimeout >= outgoingCommand -> roundTripTimeoutLimit && - ENET_TIME_DIFFERENCE (host -> serviceTime, peer -> earliestTimeout) >= ENET_PEER_TIMEOUT_MINIMUM))) + ENET_TIME_DIFFERENCE (host -> serviceTime, peer -> earliestTimeout) >= peer -> timeoutMinimum))) { enet_protocol_notify_disconnect (host, peer, event); @@ -1418,7 +1490,7 @@ enet_protocol_send_reliable_outgoing_commands (ENetHost * host, ENetPeer * peer) ! (outgoingCommand -> reliableSequenceNumber % ENET_PEER_RELIABLE_WINDOW_SIZE) && (channel -> reliableWindows [(reliableWindow + ENET_PEER_RELIABLE_WINDOWS - 1) % ENET_PEER_RELIABLE_WINDOWS] >= ENET_PEER_RELIABLE_WINDOW_SIZE || channel -> usedReliableWindows & ((((1 << ENET_PEER_FREE_RELIABLE_WINDOWS) - 1) << reliableWindow) | - (((1 << ENET_PEER_FREE_RELIABLE_WINDOWS) - 1) >> (ENET_PEER_RELIABLE_WINDOW_SIZE - reliableWindow))))) + (((1 << ENET_PEER_FREE_RELIABLE_WINDOWS) - 1) >> (ENET_PEER_RELIABLE_WINDOWS - reliableWindow))))) windowWrap = 1; if (windowWrap) { @@ -1472,7 +1544,7 @@ enet_protocol_send_reliable_outgoing_commands (ENetHost * host, ENetPeer * peer) if (outgoingCommand -> roundTripTimeout == 0) { outgoingCommand -> roundTripTimeout = peer -> roundTripTime + 4 * peer -> roundTripTimeVariance; - outgoingCommand -> roundTripTimeoutLimit = ENET_PEER_TIMEOUT_LIMIT * outgoingCommand -> roundTripTimeout; + outgoingCommand -> roundTripTimeoutLimit = peer -> timeoutLimit * outgoingCommand -> roundTripTimeout; } if (enet_list_empty (& peer -> sentReliableCommands)) @@ -1548,12 +1620,17 @@ enet_protocol_send_outgoing_commands (ENetHost * host, ENetEvent * event, int ch ! enet_list_empty (& currentPeer -> sentReliableCommands) && ENET_TIME_GREATER_EQUAL (host -> serviceTime, currentPeer -> nextTimeout) && enet_protocol_check_timeouts (host, currentPeer, event) == 1) - return 1; + { + if (event != NULL && event -> type != ENET_EVENT_TYPE_NONE) + return 1; + else + continue; + } if ((enet_list_empty (& currentPeer -> outgoingReliableCommands) || enet_protocol_send_reliable_outgoing_commands (host, currentPeer)) && enet_list_empty (& currentPeer -> sentReliableCommands) && - ENET_TIME_DIFFERENCE (host -> serviceTime, currentPeer -> lastReceiveTime) >= ENET_PEER_PING_INTERVAL && + ENET_TIME_DIFFERENCE (host -> serviceTime, currentPeer -> lastReceiveTime) >= currentPeer -> pingInterval && currentPeer -> mtu - host -> packetSize >= sizeof (ENetProtocolPing)) { enet_peer_ping (currentPeer); @@ -1575,12 +1652,7 @@ enet_protocol_send_outgoing_commands (ENetHost * host, ENetEvent * event, int ch enet_uint32 packetLoss = currentPeer -> packetsLost * ENET_PEER_PACKET_LOSS_SCALE / currentPeer -> packetsSent; #ifdef ENET_DEBUG -#ifdef WIN32 - printf ( -#else - fprintf (stderr, -#endif - "peer %u: %f%%+-%f%% packet loss, %u+-%u ms round trip time, %f%% throttle, %u/%u outgoing, %u/%u incoming\n", currentPeer -> incomingPeerID, currentPeer -> packetLoss / (float) ENET_PEER_PACKET_LOSS_SCALE, currentPeer -> packetLossVariance / (float) ENET_PEER_PACKET_LOSS_SCALE, currentPeer -> roundTripTime, currentPeer -> roundTripTimeVariance, currentPeer -> packetThrottle / (float) ENET_PEER_PACKET_THROTTLE_SCALE, enet_list_size (& currentPeer -> outgoingReliableCommands), enet_list_size (& currentPeer -> outgoingUnreliableCommands), currentPeer -> channels != NULL ? enet_list_size (& currentPeer -> channels -> incomingReliableCommands) : 0, currentPeer -> channels != NULL ? enet_list_size (& currentPeer -> channels -> incomingUnreliableCommands) : 0); + printf ("peer %u: %f%%+-%f%% packet loss, %u+-%u ms round trip time, %f%% throttle, %u/%u outgoing, %u/%u incoming\n", currentPeer -> incomingPeerID, currentPeer -> packetLoss / (float) ENET_PEER_PACKET_LOSS_SCALE, currentPeer -> packetLossVariance / (float) ENET_PEER_PACKET_LOSS_SCALE, currentPeer -> roundTripTime, currentPeer -> roundTripTimeVariance, currentPeer -> packetThrottle / (float) ENET_PEER_PACKET_THROTTLE_SCALE, enet_list_size (& currentPeer -> outgoingReliableCommands), enet_list_size (& currentPeer -> outgoingUnreliableCommands), currentPeer -> channels != NULL ? enet_list_size (& currentPeer -> channels -> incomingReliableCommands) : 0, currentPeer -> channels != NULL ? enet_list_size (& currentPeer -> channels -> incomingUnreliableCommands) : 0); #endif currentPeer -> packetLossVariance -= currentPeer -> packetLossVariance / 4; @@ -1625,12 +1697,7 @@ enet_protocol_send_outgoing_commands (ENetHost * host, ENetEvent * event, int ch host -> headerFlags |= ENET_PROTOCOL_HEADER_FLAG_COMPRESSED; shouldCompress = compressedSize; #ifdef ENET_DEBUG_COMPRESS -#ifdef WIN32 - printf ( -#else - fprintf (stderr, -#endif - "peer %u: compressed %u -> %u (%u%%)\n", currentPeer -> incomingPeerID, originalSize, compressedSize, (compressedSize * 100) / originalSize); + printf ("peer %u: compressed %u -> %u (%u%%)\n", currentPeer -> incomingPeerID, originalSize, compressedSize, (compressedSize * 100) / originalSize); #endif } } @@ -1734,7 +1801,9 @@ enet_host_service (ENetHost * host, ENetEvent * event, enet_uint32 timeout) return 1; case -1: +#ifdef ENET_DEBUG perror ("Error dispatching incoming packets"); +#endif return -1; @@ -1758,7 +1827,9 @@ enet_host_service (ENetHost * host, ENetEvent * event, enet_uint32 timeout) return 1; case -1: +#ifdef ENET_DEBUG perror ("Error sending outgoing packets"); +#endif return -1; @@ -1772,7 +1843,9 @@ enet_host_service (ENetHost * host, ENetEvent * event, enet_uint32 timeout) return 1; case -1: +#ifdef ENET_DEBUG perror ("Error receiving incoming packets"); +#endif return -1; @@ -1786,7 +1859,9 @@ enet_host_service (ENetHost * host, ENetEvent * event, enet_uint32 timeout) return 1; case -1: +#ifdef ENET_DEBUG perror ("Error sending outgoing packets"); +#endif return -1; @@ -1802,7 +1877,9 @@ enet_host_service (ENetHost * host, ENetEvent * event, enet_uint32 timeout) return 1; case -1: +#ifdef ENET_DEBUG perror ("Error dispatching incoming packets"); +#endif return -1; @@ -1811,18 +1888,25 @@ enet_host_service (ENetHost * host, ENetEvent * event, enet_uint32 timeout) } } - host -> serviceTime = enet_time_get (); - if (ENET_TIME_GREATER_EQUAL (host -> serviceTime, timeout)) return 0; - waitCondition = ENET_SOCKET_WAIT_RECEIVE; + do + { + host -> serviceTime = enet_time_get (); + + if (ENET_TIME_GREATER_EQUAL (host -> serviceTime, timeout)) + return 0; + + waitCondition = ENET_SOCKET_WAIT_RECEIVE | ENET_SOCKET_WAIT_INTERRUPT; + + if (enet_socket_wait (host -> socket, & waitCondition, ENET_TIME_DIFFERENCE (timeout, host -> serviceTime)) != 0) + return -1; + } + while (waitCondition & ENET_SOCKET_WAIT_INTERRUPT); - if (enet_socket_wait (host -> socket, & waitCondition, ENET_TIME_DIFFERENCE (timeout, host -> serviceTime)) != 0) - return -1; - host -> serviceTime = enet_time_get (); - } while (waitCondition == ENET_SOCKET_WAIT_RECEIVE); + } while (waitCondition & ENET_SOCKET_WAIT_RECEIVE); return 0; } diff --git a/libs/enet/unix.c b/libs/enet/unix.c index 69715413..19ee76f3 100644 --- a/libs/enet/unix.c +++ b/libs/enet/unix.c @@ -2,13 +2,14 @@ @file unix.c @brief ENet Unix system specific functions */ -#ifndef WIN32 +#ifndef _WIN32 #include <sys/types.h> #include <sys/socket.h> #include <sys/ioctl.h> #include <sys/time.h> #include <arpa/inet.h> +#include <netinet/tcp.h> #include <netdb.h> #include <unistd.h> #include <string.h> @@ -18,13 +19,30 @@ #define ENET_BUILDING_LIB 1 #include "enet/enet.h" -#ifdef HAS_FCNTL -#include <fcntl.h> -#endif - #ifdef __APPLE__ +#ifdef HAS_POLL #undef HAS_POLL #endif +#ifndef HAS_FCNTL +#define HAS_FCNTL 1 +#endif +#ifndef HAS_INET_PTON +#define HAS_INET_PTON 1 +#endif +#ifndef HAS_INET_NTOP +#define HAS_INET_NTOP 1 +#endif +#ifndef HAS_MSGHDR_FLAGS +#define HAS_MSGHDR_FLAGS 1 +#endif +#ifndef HAS_SOCKLEN_T +#define HAS_SOCKLEN_T 1 +#endif +#endif + +#ifdef HAS_FCNTL +#include <fcntl.h> +#endif #ifdef HAS_POLL #include <sys/poll.h> @@ -52,6 +70,12 @@ enet_deinitialize (void) } enet_uint32 +enet_host_random_seed (void) +{ + return (enet_uint32) time (NULL); +} + +enet_uint32 enet_time_get (void) { struct timeval timeVal; @@ -80,7 +104,7 @@ enet_address_set_host (ENetAddress * address, const char * name) char buffer [2048]; int errnum; -#if defined(linux) || defined(__linux) || defined(__linux__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) +#if defined(linux) || defined(__linux) || defined(__linux__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__) gethostbyname_r (name, & hostData, buffer, sizeof (buffer), & hostEntry, & errnum); #else hostEntry = gethostbyname_r (name, & hostData, buffer, sizeof (buffer), & errnum); @@ -114,7 +138,12 @@ enet_address_get_host_ip (const ENetAddress * address, char * name, size_t nameL #else char * addr = inet_ntoa (* (struct in_addr *) & address -> host); if (addr != NULL) - strncpy (name, addr, nameLength); + { + size_t addrLen = strlen(addr); + if (addrLen >= nameLength) + return -1; + memcpy (name, addr, addrLen + 1); + } else #endif return -1; @@ -133,7 +162,7 @@ enet_address_get_host (const ENetAddress * address, char * name, size_t nameLeng in.s_addr = address -> host; -#if defined(linux) || defined(__linux) || defined(__linux__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) +#if defined(linux) || defined(__linux) || defined(__linux__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__) 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); @@ -146,8 +175,13 @@ enet_address_get_host (const ENetAddress * address, char * name, size_t nameLeng if (hostEntry == NULL) return enet_address_get_host_ip (address, name, nameLength); - - strncpy (name, hostEntry -> h_name, nameLength); + else + { + size_t hostLen = strlen (hostEntry -> h_name); + if (hostLen >= nameLength) + return -1; + memcpy (name, hostEntry -> h_name, hostLen + 1); + } return 0; } @@ -177,6 +211,21 @@ enet_socket_bind (ENetSocket socket, const ENetAddress * address) sizeof (struct sockaddr_in)); } +int +enet_socket_get_address (ENetSocket socket, ENetAddress * address) +{ + struct sockaddr_in sin; + socklen_t sinLength = sizeof (struct sockaddr_in); + + if (getsockname (socket, (struct sockaddr *) & sin, & sinLength) == -1) + return -1; + + address -> host = (enet_uint32) sin.sin_addr.s_addr; + address -> port = ENET_NET_TO_HOST_16 (sin.sin_port); + + return 0; +} + int enet_socket_listen (ENetSocket socket, int backlog) { @@ -197,7 +246,7 @@ enet_socket_set_option (ENetSocket socket, ENetSocketOption option, int value) { case ENET_SOCKOPT_NONBLOCK: #ifdef HAS_FCNTL - result = fcntl (socket, F_SETFL, O_NONBLOCK | fcntl (socket, F_GETFL)); + result = fcntl (socket, F_SETFL, (value ? O_NONBLOCK : 0) | (fcntl (socket, F_GETFL) & ~O_NONBLOCK)); #else result = ioctl (socket, FIONBIO, & value); #endif @@ -219,6 +268,46 @@ enet_socket_set_option (ENetSocket socket, ENetSocketOption option, int value) result = setsockopt (socket, SOL_SOCKET, SO_SNDBUF, (char *) & value, sizeof (int)); break; + case ENET_SOCKOPT_RCVTIMEO: + { + struct timeval timeVal; + timeVal.tv_sec = value / 1000; + timeVal.tv_usec = (value % 1000) * 1000; + result = setsockopt (socket, SOL_SOCKET, SO_RCVTIMEO, (char *) & timeVal, sizeof (struct timeval)); + break; + } + + case ENET_SOCKOPT_SNDTIMEO: + { + struct timeval timeVal; + timeVal.tv_sec = value / 1000; + timeVal.tv_usec = (value % 1000) * 1000; + result = setsockopt (socket, SOL_SOCKET, SO_SNDTIMEO, (char *) & timeVal, sizeof (struct timeval)); + break; + } + + case ENET_SOCKOPT_NODELAY: + result = setsockopt (socket, IPPROTO_TCP, TCP_NODELAY, (char *) & value, sizeof (int)); + break; + + default: + break; + } + return result == -1 ? -1 : 0; +} + +int +enet_socket_get_option (ENetSocket socket, ENetSocketOption option, int * value) +{ + int result = -1; + socklen_t len; + switch (option) + { + case ENET_SOCKOPT_ERROR: + len = sizeof (int); + result = getsockopt (socket, SOL_SOCKET, SO_ERROR, value, & len); + break; + default: break; } @@ -229,6 +318,7 @@ int enet_socket_connect (ENetSocket socket, const ENetAddress * address) { struct sockaddr_in sin; + int result; memset (& sin, 0, sizeof (struct sockaddr_in)); @@ -236,7 +326,11 @@ enet_socket_connect (ENetSocket socket, const ENetAddress * address) sin.sin_port = ENET_HOST_TO_NET_16 (address -> port); sin.sin_addr.s_addr = address -> host; - return connect (socket, (struct sockaddr *) & sin, sizeof (struct sockaddr_in)); + result = connect (socket, (struct sockaddr *) & sin, sizeof (struct sockaddr_in)); + if (result == -1 && errno == EINPROGRESS) + return 0; + + return result; } ENetSocket @@ -262,10 +356,17 @@ enet_socket_accept (ENetSocket socket, ENetAddress * address) return result; } +int +enet_socket_shutdown (ENetSocket socket, ENetSocketShutdown how) +{ + return shutdown (socket, (int) how); +} + void enet_socket_destroy (ENetSocket socket) { - close (socket); + if (socket != -1) + close (socket); } int @@ -383,7 +484,16 @@ enet_socket_wait (ENetSocket socket, enet_uint32 * condition, enet_uint32 timeou pollCount = poll (& pollSocket, 1, timeout); if (pollCount < 0) - return -1; + { + if (errno == EINTR && * condition & ENET_SOCKET_WAIT_INTERRUPT) + { + * condition = ENET_SOCKET_WAIT_INTERRUPT; + + return 0; + } + + return -1; + } * condition = ENET_SOCKET_WAIT_NONE; @@ -417,7 +527,16 @@ enet_socket_wait (ENetSocket socket, enet_uint32 * condition, enet_uint32 timeou selectCount = select (socket + 1, & readSet, & writeSet, NULL, & timeVal); if (selectCount < 0) - return -1; + { + if (errno == EINTR && * condition & ENET_SOCKET_WAIT_INTERRUPT) + { + * condition = ENET_SOCKET_WAIT_INTERRUPT; + + return 0; + } + + return -1; + } * condition = ENET_SOCKET_WAIT_NONE; diff --git a/libs/enet/win32.c b/libs/enet/win32.c index e1fae233..5cc16799 100644 --- a/libs/enet/win32.c +++ b/libs/enet/win32.c @@ -2,11 +2,12 @@ @file win32.c @brief ENet Win32 system specific functions */ -#ifdef WIN32 +#ifdef _WIN32 -#include <time.h> #define ENET_BUILDING_LIB 1 #include "enet/enet.h" +#include <windows.h> +#include <mmsystem.h> static enet_uint32 timeBase = 0; @@ -41,6 +42,12 @@ enet_deinitialize (void) } enet_uint32 +enet_host_random_seed (void) +{ + return (enet_uint32) timeGetTime (); +} + +enet_uint32 enet_time_get (void) { return (enet_uint32) timeGetTime () - timeBase; @@ -79,7 +86,13 @@ enet_address_get_host_ip (const ENetAddress * address, char * name, size_t nameL char * addr = inet_ntoa (* (struct in_addr *) & address -> host); if (addr == NULL) return -1; - strncpy (name, addr, nameLength); + else + { + size_t addrLen = strlen(addr); + if (addrLen >= nameLength) + return -1; + memcpy (name, addr, addrLen + 1); + } return 0; } @@ -88,14 +101,19 @@ enet_address_get_host (const ENetAddress * address, char * name, size_t nameLeng { struct in_addr in; struct hostent * hostEntry; - + in.s_addr = address -> host; hostEntry = gethostbyaddr ((char *) & in, sizeof (struct in_addr), AF_INET); if (hostEntry == NULL) return enet_address_get_host_ip (address, name, nameLength); - - strncpy (name, hostEntry -> h_name, nameLength); + else + { + size_t hostLen = strlen (hostEntry -> h_name); + if (hostLen >= nameLength) + return -1; + memcpy (name, hostEntry -> h_name, hostLen + 1); + } return 0; } @@ -126,6 +144,21 @@ enet_socket_bind (ENetSocket socket, const ENetAddress * address) } int +enet_socket_get_address (ENetSocket socket, ENetAddress * address) +{ + struct sockaddr_in sin; + int sinLength = sizeof (struct sockaddr_in); + + if (getsockname (socket, (struct sockaddr *) & sin, & sinLength) == -1) + return -1; + + address -> host = (enet_uint32) sin.sin_addr.s_addr; + address -> port = ENET_NET_TO_HOST_16 (sin.sin_port); + + return 0; +} + +int enet_socket_listen (ENetSocket socket, int backlog) { return listen (socket, backlog < 0 ? SOMAXCONN : backlog) == SOCKET_ERROR ? -1 : 0; @@ -166,6 +199,35 @@ enet_socket_set_option (ENetSocket socket, ENetSocketOption option, int value) result = setsockopt (socket, SOL_SOCKET, SO_SNDBUF, (char *) & value, sizeof (int)); break; + case ENET_SOCKOPT_RCVTIMEO: + result = setsockopt (socket, SOL_SOCKET, SO_RCVTIMEO, (char *) & value, sizeof (int)); + break; + + case ENET_SOCKOPT_SNDTIMEO: + result = setsockopt (socket, SOL_SOCKET, SO_SNDTIMEO, (char *) & value, sizeof (int)); + break; + + case ENET_SOCKOPT_NODELAY: + result = setsockopt (socket, IPPROTO_TCP, TCP_NODELAY, (char *) & value, sizeof (int)); + break; + + default: + break; + } + return result == SOCKET_ERROR ? -1 : 0; +} + +int +enet_socket_get_option (ENetSocket socket, ENetSocketOption option, int * value) +{ + int result = SOCKET_ERROR, len; + switch (option) + { + case ENET_SOCKOPT_ERROR: + len = sizeof(int); + result = getsockopt (socket, SOL_SOCKET, SO_ERROR, (char *) value, & len); + break; + default: break; } @@ -176,6 +238,7 @@ int enet_socket_connect (ENetSocket socket, const ENetAddress * address) { struct sockaddr_in sin; + int result; memset (& sin, 0, sizeof (struct sockaddr_in)); @@ -183,7 +246,11 @@ enet_socket_connect (ENetSocket socket, const ENetAddress * address) sin.sin_port = ENET_HOST_TO_NET_16 (address -> port); sin.sin_addr.s_addr = address -> host; - return connect (socket, (struct sockaddr *) & sin, sizeof (struct sockaddr_in)) == SOCKET_ERROR ? -1 : 0; + result = connect (socket, (struct sockaddr *) & sin, sizeof (struct sockaddr_in)); + if (result == SOCKET_ERROR && WSAGetLastError () != WSAEWOULDBLOCK) + return -1; + + return 0; } ENetSocket @@ -209,10 +276,17 @@ enet_socket_accept (ENetSocket socket, ENetAddress * address) return result; } +int +enet_socket_shutdown (ENetSocket socket, ENetSocketShutdown how) +{ + return shutdown (socket, (int) how) == SOCKET_ERROR ? -1 : 0; +} + void enet_socket_destroy (ENetSocket socket) { - closesocket (socket); + if (socket != INVALID_SOCKET) + closesocket (socket); } int @@ -238,7 +312,7 @@ enet_socket_send (ENetSocket socket, (DWORD) bufferCount, & sentLength, 0, - address != NULL ? (struct sockaddr *) & sin : 0, + address != NULL ? (struct sockaddr *) & sin : NULL, address != NULL ? sizeof (struct sockaddr_in) : 0, NULL, NULL) == SOCKET_ERROR) |