1 Commits

Author SHA1 Message Date
Cameron Gutman 299ab267c9 Enable ECN/L4S on UNIX
Since this is enabled as a QoS option, it will benefit from the opportunistic
disablement code when ECN-intolerant networks are encountered.
2024-02-03 14:32:25 -06:00
22 changed files with 580 additions and 1400 deletions
-21
View File
@@ -1,21 +0,0 @@
on: [push, pull_request]
name: CMake
jobs:
cmake-build:
name: CMake ${{ matrix.os }} ${{ matrix.build_type }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: ["ubuntu-latest", "windows-latest", "macos-latest"]
build_type: ["Debug", "Release"]
steps:
- uses: actions/checkout@v3
- name: Configure CMake
run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{ matrix.build_type }}
- name: Build
run: cmake --build ${{github.workspace}}/build --config ${{ matrix.build_type }}
+14 -66
View File
@@ -1,9 +1,7 @@
cmake_minimum_required(VERSION 2.8.12...3.20)
cmake_minimum_required(VERSION 2.6)
project(enet)
option(ENET_NO_INSTALL "Disable installation of headers and libraries" OFF)
# The "configure" step.
include(CheckFunctionExists)
include(CheckStructHasMember)
@@ -21,16 +19,7 @@ check_struct_has_member("struct msghdr" "msg_flags" "sys/types.h;sys/socket.h" H
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)
set(CMAKE_EXTRA_INCLUDE_FILES "winsock2.h;qos2.h")
check_type_size("QOS_FLOWID" HAS_QOS_FLOWID BUILTIN_TYPES_ONLY)
check_type_size("PQOS_FLOWID" HAS_PQOS_FLOWID BUILTIN_TYPES_ONLY)
unset(CMAKE_EXTRA_INCLUDE_FILES)
if(MSVC)
add_definitions(-W3)
else()
add_definitions(-Wno-error)
endif()
if(HAS_FCNTL)
add_definitions(-DHAS_FCNTL=1)
endif()
@@ -64,58 +53,17 @@ endif()
if(HAS_SOCKLEN_T)
add_definitions(-DHAS_SOCKLEN_T=1)
endif()
if(HAS_QOS_FLOWID)
add_definitions(-DHAS_QOS_FLOWID=1)
endif()
if(HAS_PQOS_FLOWID)
add_definitions(-DHAS_PQOS_FLOWID=1)
endif()
include_directories(${PROJECT_SOURCE_DIR}/include)
set(INCLUDE_FILES_PREFIX include/enet)
set(INCLUDE_FILES
${INCLUDE_FILES_PREFIX}/callbacks.h
${INCLUDE_FILES_PREFIX}/enet.h
${INCLUDE_FILES_PREFIX}/list.h
${INCLUDE_FILES_PREFIX}/protocol.h
${INCLUDE_FILES_PREFIX}/time.h
${INCLUDE_FILES_PREFIX}/types.h
${INCLUDE_FILES_PREFIX}/unix.h
${INCLUDE_FILES_PREFIX}/utility.h
${INCLUDE_FILES_PREFIX}/win32.h
)
set(SOURCE_FILES
callbacks.c
compress.c
host.c
list.c
packet.c
peer.c
protocol.c
unix.c
win32.c)
source_group(include FILES ${INCLUDE_FILES})
source_group(source FILES ${SOURCE_FILES})
add_library(enet STATIC
${INCLUDE_FILES}
${SOURCE_FILES}
)
target_include_directories(enet SYSTEM PUBLIC include)
if (MINGW)
target_link_libraries(enet winmm ws2_32)
endif()
if(NOT ENET_NO_INSTALL)
install(TARGETS enet
RUNTIME DESTINATION bin
ARCHIVE DESTINATION lib/static
LIBRARY DESTINATION lib)
install(DIRECTORY include/
DESTINATION include)
endif()
callbacks.c
compress.c
host.c
list.c
packet.c
peer.c
protocol.c
unix.c
win32.c
)
-21
View File
@@ -1,25 +1,4 @@
ENet 1.3.17 (November 15, 2020):
* fixes for sender getting too far ahead of receiver that can cause instability with reliable packets
ENet 1.3.16 (September 8, 2020):
* fix bug in unreliable fragment queuing
* use single output queue for reliable and unreliable packets for saner ordering
* revert experimental throttle changes that were less stable than prior algorithm
ENet 1.3.15 (April 20, 2020):
* quicker RTT initialization
* use fractional precision for RTT calculations
* fixes for packet throttle with low RTT variance
* miscellaneous socket bug fixes
ENet 1.3.14 (January 27, 2019):
* bug fix for enet_peer_disconnect_later()
* use getaddrinfo and getnameinfo where available
* miscellaneous cleanups
ENet 1.3.13 (April 30, 2015):
+1 -1
View File
@@ -38,7 +38,7 @@ PROJECT_NAME = "ENet"
# could be handy for archiving the generated documentation or if some version
# control system is used.
PROJECT_NUMBER = v1.3.17
PROJECT_NUMBER = v1.3.13
# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a
+1 -1
View File
@@ -1,4 +1,4 @@
Copyright (c) 2002-2020 Lee Salzman
Copyright (c) 2002-2016 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:
+1 -1
View File
@@ -16,7 +16,7 @@ enetinclude_HEADERS = \
lib_LTLIBRARIES = libenet.la
libenet_la_SOURCES = callbacks.c compress.c host.c list.c packet.c peer.c protocol.c unix.c win32.c
# see info '(libtool) Updating version info' before making a release
libenet_la_LDFLAGS = $(AM_LDFLAGS) -version-info 7:5:0
libenet_la_LDFLAGS = $(AM_LDFLAGS) -version-info 7:1:0
AM_CPPFLAGS = -I$(top_srcdir)/include
ACLOCAL_AMFLAGS = -Im4
+1 -1
View File
@@ -1,4 +1,4 @@
Please visit the ENet homepage at http://sauerbraten.org/enet/ for installation
Please visit the ENet homepage at http://enet.bespin.org for installation
and usage instructions.
If you obtained this package from github, the quick description on how to build
+1 -1
View File
@@ -1,4 +1,4 @@
AC_INIT([libenet], [1.3.17])
AC_INIT([libenet], [1.3.13])
AC_CONFIG_SRCDIR([include/enet/enet.h])
AM_INIT_AUTOMAKE([foreign])
+1 -1
View File
@@ -1,7 +1,7 @@
/**
@page License License
Copyright (c) 2002-2020 Lee Salzman
Copyright (c) 2002-2016 Lee Salzman
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
+2 -2
View File
@@ -36,7 +36,7 @@ portable, and easily embeddable.
You can retrieve the source to ENet by downloading it in either .tar.gz form
or accessing the github distribution directly.
The most recent stable release (1.3.17) can be downloaded <a class="el" href="download/enet-1.3.17.tar.gz">here</a>.
The most recent stable release (1.3.13) can be downloaded <a class="el" href="download/enet-1.3.13.tar.gz">here</a>.
The last release that is protocol compatible with the 1.2 series or earlier (1.2.5) can be downloaded <a class="el" href="download/enet-1.2.5.tar.gz">here</a>.
You can find the most recent ENet source at <a class="el" href="https://github.com/lsalzman/enet">the github repository</a>.
@@ -53,7 +53,7 @@ The <a class="el" href="http://lists.cubik.org/mailman/listinfo/enet-discuss">en
/**
@page IRCChannel IRC Channel
Join the \#enet channel on the <a class="el" href="https://libera.chat">Libera Chat IRC network (irc.libera.chat)</a> for real-time discussion about the ENet library.
Join the \#enet channel on the <a class="el" href="http://freenode.net">freenode IRC network (irc.freenode.net)</a> for real-time discussion about the ENet library.
*/
+2 -2
View File
@@ -102,8 +102,8 @@ may be simultaneously open.
client = enet_host_create (NULL /* create a client host */,
1 /* only allow 1 outgoing connection */,
2 /* allow up 2 channels to be used, 0 and 1 */,
0 /* assume any amount of incoming bandwidth */,
0 /* assume any amount of outgoing bandwidth */);
57600 / 8 /* 56K modem with 56 Kbps downstream bandwidth */,
14400 / 8 /* 56K modem with 14 Kbps upstream bandwidth */);
if (client == NULL)
{
+6 -19
View File
@@ -61,11 +61,10 @@ enet_host_create (int addressFamily, const ENetAddress * address, size_t peerCou
return NULL;
}
host -> wildcardBind = address && enet_address_wildcard (address);
enet_socket_set_option (host -> socket, ENET_SOCKOPT_NONBLOCK, 1);
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);
enet_socket_set_option (host -> socket, ENET_SOCKOPT_QOS, 1);
if (address != NULL && enet_socket_get_address (host -> socket, & host -> address) < 0)
host -> address = * address;
@@ -89,8 +88,7 @@ enet_host_create (int addressFamily, const ENetAddress * address, size_t peerCou
host -> commandCount = 0;
host -> bufferCount = 0;
host -> checksum = NULL;
memset(& host -> receivedPeerAddress, 0, sizeof (host -> receivedPeerAddress));
memset(& host -> receivedLocalAddress, 0, sizeof (host -> receivedLocalAddress));
memset(& host -> receivedAddress, 0, sizeof (host -> receivedAddress));
host -> receivedData = NULL;
host -> receivedDataLength = 0;
@@ -98,7 +96,6 @@ enet_host_create (int addressFamily, const ENetAddress * address, size_t peerCou
host -> totalSentPackets = 0;
host -> totalReceivedData = 0;
host -> totalReceivedPackets = 0;
host -> totalQueued = 0;
host -> connectedPeers = 0;
host -> bandwidthLimitedPeers = 0;
@@ -126,8 +123,9 @@ enet_host_create (int addressFamily, const ENetAddress * address, size_t peerCou
enet_list_clear (& currentPeer -> acknowledgements);
enet_list_clear (& currentPeer -> sentReliableCommands);
enet_list_clear (& currentPeer -> outgoingCommands);
enet_list_clear (& currentPeer -> outgoingSendReliableCommands);
enet_list_clear (& currentPeer -> sentUnreliableCommands);
enet_list_clear (& currentPeer -> outgoingReliableCommands);
enet_list_clear (& currentPeer -> outgoingUnreliableCommands);
enet_list_clear (& currentPeer -> dispatchedCommands);
enet_peer_reset (currentPeer);
@@ -163,16 +161,6 @@ enet_host_destroy (ENetHost * host)
enet_free (host);
}
enet_uint32
enet_host_random (ENetHost * host)
{
/* Mulberry32 by Tommy Ettinger */
enet_uint32 n = (host -> randomSeed += 0x6D2B79F5U);
n = (n ^ (n >> 15)) * (n | 1U);
n ^= n + (n ^ (n >> 7)) * (n | 61U);
return n ^ (n >> 14);
}
/** Initiates a connection to a foreign host.
@param host host seeking the connection
@param address destination for the connection
@@ -212,8 +200,7 @@ enet_host_connect (ENetHost * host, const ENetAddress * address, size_t channelC
currentPeer -> channelCount = channelCount;
currentPeer -> state = ENET_PEER_STATE_CONNECTING;
currentPeer -> address = * address;
currentPeer -> connectID = enet_host_random (host);
currentPeer -> mtu = host -> mtu;
currentPeer -> connectID = ++ host -> randomSeed;
if (host -> outgoingBandwidth == 0)
currentPeer -> windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE;
+56 -79
View File
@@ -1,4 +1,4 @@
/**
/**
@file enet.h
@brief ENet public header file
*/
@@ -12,7 +12,7 @@ extern "C"
#include <stdlib.h>
#if defined(_WIN32) && !defined(NXDK)
#ifdef _WIN32
#include "enet/win32.h"
#else
#include "enet/unix.h"
@@ -25,7 +25,7 @@ extern "C"
#define ENET_VERSION_MAJOR 1
#define ENET_VERSION_MINOR 3
#define ENET_VERSION_PATCH 17
#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)
@@ -55,16 +55,14 @@ typedef enum _ENetSocketWait
typedef enum _ENetSocketOption
{
ENET_SOCKOPT_NONBLOCK = 1,
ENET_SOCKOPT_BROADCAST = 2,
ENET_SOCKOPT_RCVBUF = 3,
ENET_SOCKOPT_SNDBUF = 4,
ENET_SOCKOPT_REUSEADDR = 5,
ENET_SOCKOPT_RCVTIMEO = 6,
ENET_SOCKOPT_SNDTIMEO = 7,
ENET_SOCKOPT_ERROR = 8,
ENET_SOCKOPT_NODELAY = 9,
ENET_SOCKOPT_TTL = 10,
ENET_SOCKOPT_QOS = 11,
ENET_SOCKOPT_RCVBUF,
ENET_SOCKOPT_SNDBUF,
ENET_SOCKOPT_REUSEADDR,
ENET_SOCKOPT_RCVTIMEO,
ENET_SOCKOPT_SNDTIMEO,
ENET_SOCKOPT_ERROR,
ENET_SOCKOPT_NODELAY,
ENET_SOCKOPT_QOS,
} ENetSocketOption;
typedef enum _ENetSocketShutdown
@@ -75,7 +73,7 @@ typedef enum _ENetSocketShutdown
} ENetSocketShutdown;
/**
* Portable internet address structure.
* Portable internet address structure.
*/
typedef struct _ENetAddress
{
@@ -89,7 +87,7 @@ typedef struct _ENetAddress
* The host must be specified in network byte-order, and the port must be in
* host byte-order. The constant ENET_HOST_ANY may be used to specify the
* default server host.
@sa ENetPacket
*/
typedef enum _ENetPacketFlag
@@ -116,16 +114,16 @@ typedef void (ENET_CALLBACK * ENetPacketFreeCallback) (struct _ENetPacket *);
/**
* ENet packet structure.
*
* An ENet data packet that may be sent to or received from a peer. The shown
* fields should only be read and never modified. The data field contains the
* allocated data for the packet. The dataLength fields specifies the length
* of the allocated data. The flags field is either 0 (specifying no flags),
* An ENet data packet that may be sent to or received from a peer. The shown
* fields should only be read and never modified. The data field contains the
* allocated data for the packet. The dataLength fields specifies the length
* of the allocated data. The flags field is either 0 (specifying no flags),
* or a bitwise-or of any combination of the following flags:
*
* ENET_PACKET_FLAG_RELIABLE - packet must be received by the target peer
* and resend attempts should be made until the packet is delivered
*
* ENET_PACKET_FLAG_UNSEQUENCED - packet will not be sequenced with other packets
* ENET_PACKET_FLAG_UNSEQUENCED - packet will not be sequenced with other packets
* (not supported for reliable packets)
*
* ENET_PACKET_FLAG_NO_ALLOCATE - packet will not allocate data, and user must supply it instead
@@ -160,7 +158,7 @@ typedef struct _ENetOutgoingCommand
enet_uint16 unreliableSequenceNumber;
enet_uint32 sentTime;
enet_uint32 roundTripTimeout;
enet_uint32 queueTime;
enet_uint32 roundTripTimeoutLimit;
enet_uint32 fragmentOffset;
enet_uint16 fragmentLength;
enet_uint16 sendAttempts;
@@ -169,7 +167,7 @@ typedef struct _ENetOutgoingCommand
} ENetOutgoingCommand;
typedef struct _ENetIncomingCommand
{
{
ENetListNode incomingCommandList;
enet_uint16 reliableSequenceNumber;
enet_uint16 unreliableSequenceNumber;
@@ -191,7 +189,7 @@ typedef enum _ENetPeerState
ENET_PEER_STATE_DISCONNECT_LATER = 6,
ENET_PEER_STATE_DISCONNECTING = 7,
ENET_PEER_STATE_ACKNOWLEDGING_DISCONNECT = 8,
ENET_PEER_STATE_ZOMBIE = 9
ENET_PEER_STATE_ZOMBIE = 9
} ENetPeerState;
#ifndef ENET_BUFFER_MAXIMUM
@@ -200,17 +198,8 @@ typedef enum _ENetPeerState
enum
{
#if defined(__WIIU__)
ENET_HOST_RECEIVE_BUFFER_SIZE = 256 * 1024,
// Send buffer size is limited since it cannot use userbuffers
ENET_HOST_SEND_BUFFER_SIZE = 0x10000 - 1,
#elif defined(__3DS__)
ENET_HOST_RECEIVE_BUFFER_SIZE = 0x20000,
ENET_HOST_SEND_BUFFER_SIZE = 0x20000,
#else
ENET_HOST_RECEIVE_BUFFER_SIZE = 256 * 1024,
ENET_HOST_SEND_BUFFER_SIZE = 256 * 1024,
#endif
ENET_HOST_BANDWIDTH_THROTTLE_INTERVAL = 1000,
ENET_HOST_DEFAULT_MTU = 900,
ENET_HOST_DEFAULT_MAXIMUM_PACKET_SIZE = 32 * 1024 * 1024,
@@ -219,7 +208,7 @@ enum
ENET_PEER_DEFAULT_ROUND_TRIP_TIME = 500,
ENET_PEER_DEFAULT_PACKET_THROTTLE = 32,
ENET_PEER_PACKET_THROTTLE_SCALE = 32,
ENET_PEER_PACKET_THROTTLE_COUNTER = 7,
ENET_PEER_PACKET_THROTTLE_COUNTER = 7,
ENET_PEER_PACKET_THROTTLE_ACCELERATION = 2,
ENET_PEER_PACKET_THROTTLE_DECELERATION = 2,
ENET_PEER_PACKET_THROTTLE_INTERVAL = 5000,
@@ -250,19 +239,13 @@ typedef struct _ENetChannel
ENetList incomingUnreliableCommands;
} ENetChannel;
typedef enum _ENetPeerFlag
{
ENET_PEER_FLAG_NEEDS_DISPATCH = (1 << 0),
ENET_PEER_FLAG_CONTINUE_SENDING = (1 << 1)
} ENetPeerFlag;
/**
* An ENet peer which data packets may be sent or received from.
* An ENet peer which data packets may be sent or received from.
*
* No fields should be modified unless otherwise specified.
* No fields should be modified unless otherwise specified.
*/
typedef struct _ENetPeer
{
{
ENetListNode dispatchList;
struct _ENetHost * host;
enet_uint16 outgoingPeerID;
@@ -271,7 +254,6 @@ typedef struct _ENetPeer
enet_uint8 outgoingSessionID;
enet_uint8 incomingSessionID;
ENetAddress address; /**< Internet address of the peer */
ENetAddress localAddress;
void * data; /**< Application private data, may be freely modified */
ENetPeerState state;
ENetChannel * channels;
@@ -314,14 +296,14 @@ typedef struct _ENetPeer
enet_uint16 outgoingReliableSequenceNumber;
ENetList acknowledgements;
ENetList sentReliableCommands;
ENetList outgoingSendReliableCommands;
ENetList outgoingCommands;
ENetList sentUnreliableCommands;
ENetList outgoingReliableCommands;
ENetList outgoingUnreliableCommands;
ENetList dispatchedCommands;
enet_uint16 flags;
enet_uint16 reserved;
int needsDispatch;
enet_uint16 incomingUnsequencedGroup;
enet_uint16 outgoingUnsequencedGroup;
enet_uint32 unsequencedWindow [ENET_PEER_UNSEQUENCED_WINDOW_SIZE / 32];
enet_uint32 unsequencedWindow [ENET_PEER_UNSEQUENCED_WINDOW_SIZE / 32];
enet_uint32 eventData;
size_t totalWaitingData;
} ENetPeer;
@@ -345,7 +327,7 @@ typedef enet_uint32 (ENET_CALLBACK * ENetChecksumCallback) (const ENetBuffer * b
/** 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.
*
* No fields should be modified unless otherwise stated.
@@ -364,7 +346,6 @@ typedef int (ENET_CALLBACK * ENetInterceptCallback) (struct _ENetHost * host, st
typedef struct _ENetHost
{
ENetSocket socket;
int wildcardBind;
ENetAddress address; /**< Internet address of the host */
enet_uint32 incomingBandwidth; /**< downstream bandwidth of the host */
enet_uint32 outgoingBandwidth; /**< upstream bandwidth of the host */
@@ -377,7 +358,7 @@ typedef struct _ENetHost
size_t channelLimit; /**< maximum number of channels allowed for connected peers */
enet_uint32 serviceTime;
ENetList dispatchQueue;
enet_uint32 totalQueued;
int continueSending;
size_t packetSize;
enet_uint16 headerFlags;
ENetProtocol commands [ENET_PROTOCOL_MAXIMUM_PACKET_COMMANDS];
@@ -387,8 +368,7 @@ typedef struct _ENetHost
ENetChecksumCallback checksum; /**< callback the user can set to enable packet checksums for this host */
ENetCompressor compressor;
enet_uint8 packetData [2][ENET_PROTOCOL_MAXIMUM_MTU];
ENetAddress receivedPeerAddress;
ENetAddress receivedLocalAddress;
ENetAddress receivedAddress;
enet_uint8 * receivedData;
size_t receivedDataLength;
enet_uint32 totalSentData; /**< total data sent, user should reset to 0 as needed to prevent overflow */
@@ -409,21 +389,21 @@ typedef struct _ENetHost
typedef enum _ENetEventType
{
/** no event occurred within the specified time limit */
ENET_EVENT_TYPE_NONE = 0,
ENET_EVENT_TYPE_NONE = 0,
/** a connection request initiated by enet_host_connect has completed.
* The peer field contains the peer which successfully connected.
/** a connection request initiated by enet_host_connect has completed.
* The peer field contains the peer which successfully connected.
*/
ENET_EVENT_TYPE_CONNECT = 1,
ENET_EVENT_TYPE_CONNECT = 1,
/** a peer has disconnected. This event is generated on a successful
* completion of a disconnect initiated by enet_peer_disconnect, if
* a peer has timed out, or if a connection request intialized by
* enet_host_connect has timed out. The peer field contains the peer
* which disconnected. The data field contains user supplied data
/** a peer has disconnected. This event is generated on a successful
* completion of a disconnect initiated by enet_peer_disconnect, if
* a peer has timed out, or if a connection request intialized by
* enet_host_connect has timed out. The peer field contains the peer
* which disconnected. The data field contains user supplied data
* describing the disconnection, or 0, if none is available.
*/
ENET_EVENT_TYPE_DISCONNECT = 2,
ENET_EVENT_TYPE_DISCONNECT = 2,
/** a packet has been received from a peer. The peer field specifies the
* peer which sent the packet. The channelID field specifies the channel
@@ -436,10 +416,10 @@ typedef enum _ENetEventType
/**
* An ENet event as returned by enet_host_service().
@sa enet_host_service
*/
typedef struct _ENetEvent
typedef struct _ENetEvent
{
ENetEventType type; /**< type of the event */
ENetPeer * peer; /**< peer that generated a connect, disconnect or receive event */
@@ -449,17 +429,17 @@ typedef struct _ENetEvent
} ENetEvent;
/** @defgroup global ENet global functions
@{
@{
*/
/**
/**
Initializes ENet globally. Must be called prior to using any functions in
ENet.
@returns 0 on success, < 0 on failure
*/
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
@@ -468,7 +448,7 @@ ENET_API int enet_initialize (void);
*/
ENET_API int enet_initialize_with_callbacks (ENetVersion version, const ENetCallbacks * inits);
/**
/**
Shuts down ENet globally. Should be called when a program that has
initialized ENet exits.
*/
@@ -476,7 +456,7 @@ ENET_API void enet_deinitialize (void);
/**
Gives the linked version of the ENet library.
@returns the version number
@returns the version number
*/
ENET_API ENetVersion enet_linked_version (void);
@@ -503,8 +483,8 @@ 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 *);
ENET_API int enet_socket_send (ENetSocket, const ENetAddress *, const ENetAddress *, const ENetBuffer *, size_t);
ENET_API int enet_socket_receive (ENetSocket, ENetAddress *, ENetAddress *, ENetBuffer *, size_t);
ENET_API int enet_socket_send (ENetSocket, const ENetAddress *, const ENetBuffer *, size_t);
ENET_API int enet_socket_receive (ENetSocket, ENetAddress *, ENetBuffer *, size_t);
ENET_API int enet_socket_wait (ENetSocket, enet_uint32 *, enet_uint32);
ENET_API int enet_socket_set_option (ENetSocket, ENetSocketOption, int);
ENET_API int enet_socket_get_option (ENetSocket, ENetSocketOption, int *);
@@ -528,7 +508,6 @@ ENET_API int enet_socketset_select (ENetSocket, ENetSocketSet *, ENetSock
ENET_API int enet_address_set_host (ENetAddress * address, const char * hostName);
ENET_API int enet_address_set_address (ENetAddress * address, struct sockaddr * addr, socklen_t addrlen);
ENET_API int enet_address_set_port (ENetAddress * address, enet_uint16 port);
ENET_API int enet_address_wildcard (const ENetAddress * address);
ENET_API int enet_address_equal (ENetAddress * address1, ENetAddress * address2);
/** @} */
@@ -537,7 +516,7 @@ 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);
ENET_API enet_uint32 enet_crc32 (const ENetBuffer *, size_t);
ENET_API ENetHost * enet_host_create (int, const ENetAddress *, size_t, size_t, enet_uint32, enet_uint32);
ENET_API void enet_host_destroy (ENetHost *);
ENET_API ENetPeer * enet_host_connect (ENetHost *, const ENetAddress *, size_t, enet_uint32);
@@ -550,7 +529,6 @@ 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);
extern enet_uint32 enet_host_random (ENetHost *);
ENET_API int enet_peer_send (ENetPeer *, enet_uint8, ENetPacket *);
ENET_API ENetPacket * enet_peer_receive (ENetPeer *, enet_uint8 * channelID);
@@ -564,13 +542,12 @@ ENET_API void enet_peer_disconnect_later (ENetPeer *, enet_uint32
ENET_API void enet_peer_throttle_configure (ENetPeer *, enet_uint32, enet_uint32, enet_uint32);
extern int enet_peer_throttle (ENetPeer *, enet_uint32);
extern void enet_peer_reset_queues (ENetPeer *);
extern int enet_peer_has_outgoing_commands (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 *, 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 *, ENetIncomingCommand *);
extern void enet_peer_dispatch_incoming_reliable_commands (ENetPeer *, ENetChannel *, ENetIncomingCommand *);
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 *);
@@ -578,7 +555,7 @@ ENET_API void * enet_range_coder_create (void);
ENET_API void enet_range_coder_destroy (void *);
ENET_API size_t enet_range_coder_compress (void *, const ENetBuffer *, size_t, size_t, enet_uint8 *, size_t);
ENET_API size_t enet_range_coder_decompress (void *, const enet_uint8 *, size_t, enet_uint8 *, size_t);
extern size_t enet_protocol_command_size (enet_uint8);
#ifdef __cplusplus
+1 -5
View File
@@ -1,4 +1,4 @@
/**
/**
@file protocol.h
@brief ENet protocol
*/
@@ -10,11 +10,7 @@
enum
{
ENET_PROTOCOL_MINIMUM_MTU = 576,
#if defined(__WIIU__) || defined(__3DS__)
ENET_PROTOCOL_MAXIMUM_MTU = 1400,
#else
ENET_PROTOCOL_MAXIMUM_MTU = 4096,
#endif
ENET_PROTOCOL_MAXIMUM_PACKET_COMMANDS = 32,
ENET_PROTOCOL_MINIMUM_WINDOW_SIZE = 4096,
ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE = 65536,
-1
View File
@@ -9,7 +9,6 @@
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <unistd.h>
-1
View File
@@ -7,7 +7,6 @@
#define ENET_MAX(x, y) ((x) > (y) ? (x) : (y))
#define ENET_MIN(x, y) ((x) < (y) ? (x) : (y))
#define ENET_DIFFERENCE(x, y) ((x) < (y) ? (y) - (x) : (x) - (y))
#endif /* __ENET_UTILITY_H__ */
+1 -3
View File
@@ -11,14 +11,12 @@
#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
#define _CRT_SECURE_NO_DEPRECATE
#define _CRT_SECURE_NO_WARNINGS
#endif
#endif
#include <stdlib.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <Ws2tcpip.h>
typedef SOCKET ENetSocket;
+43 -36
View File
@@ -98,46 +98,53 @@ enet_packet_resize (ENetPacket * packet, size_t dataLength)
return 0;
}
static const enet_uint32 crcTable [256] =
{
0, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x5005713,
0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0xBDBDF21,
0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
};
static int initializedCRC32 = 0;
static enet_uint32 crcTable [256];
static enet_uint32
reflect_crc (int val, int bits)
{
int result = 0, bit;
for (bit = 0; bit < bits; bit ++)
{
if(val & 1) result |= 1 << (bits - 1 - bit);
val >>= 1;
}
return result;
}
static void
initialize_crc32 (void)
{
int byte;
for (byte = 0; byte < 256; ++ byte)
{
enet_uint32 crc = reflect_crc (byte, 8) << 24;
int offset;
for(offset = 0; offset < 8; ++ offset)
{
if (crc & 0x80000000)
crc = (crc << 1) ^ 0x04c11db7;
else
crc <<= 1;
}
crcTable [byte] = reflect_crc (crc, 32);
}
initializedCRC32 = 1;
}
enet_uint32
enet_crc32 (const ENetBuffer * buffers, size_t bufferCount)
{
enet_uint32 crc = 0xFFFFFFFF;
if (! initializedCRC32) initialize_crc32 ();
while (bufferCount -- > 0)
{
@@ -146,7 +153,7 @@ enet_crc32 (const ENetBuffer * buffers, size_t bufferCount)
while (data < dataEnd)
{
crc = (crc >> 8) ^ crcTable [(crc & 0xFF) ^ *data++];
crc = (crc >> 8) ^ crcTable [(crc & 0xFF) ^ *data++];
}
++ buffers;
+54 -77
View File
@@ -66,7 +66,7 @@ enet_peer_throttle (ENetPeer * peer, enet_uint32 rtt)
peer -> packetThrottle = peer -> packetThrottleLimit;
}
else
if (rtt <= peer -> lastRoundTripTime)
if (rtt < peer -> lastRoundTripTime)
{
peer -> packetThrottle += peer -> packetThrottleAcceleration;
@@ -90,13 +90,6 @@ enet_peer_throttle (ENetPeer * peer, enet_uint32 rtt)
}
/** Queues a packet to be sent.
On success, ENet will assume ownership of the packet, and so enet_packet_destroy
should not be called on it thereafter. On failure, the caller still must destroy
the packet on its own as ENet has not queued the packet. The caller can also
check the packet's referenceCount field after sending to check if ENet queued
the packet and thus incremented the referenceCount.
@param peer destination for the packet
@param channelID channel on which to send
@param packet packet to send
@@ -106,7 +99,7 @@ enet_peer_throttle (ENetPeer * peer, enet_uint32 rtt)
int
enet_peer_send (ENetPeer * peer, enet_uint8 channelID, ENetPacket * packet)
{
ENetChannel * channel;
ENetChannel * channel = & peer -> channels [channelID];
ENetProtocol command;
size_t fragmentLength;
@@ -115,7 +108,6 @@ enet_peer_send (ENetPeer * peer, enet_uint8 channelID, ENetPacket * packet)
packet -> dataLength > peer -> host -> maximumPacketSize)
return -1;
channel = & peer -> channels [channelID];
fragmentLength = peer -> mtu - sizeof (ENetProtocolHeader) - sizeof (ENetProtocolSendFragment);
if (peer -> host -> checksum != NULL)
fragmentLength -= sizeof(enet_uint32);
@@ -276,7 +268,7 @@ enet_peer_reset_outgoing_commands (ENetList * queue)
}
static void
enet_peer_remove_incoming_commands (ENetList * queue, ENetListIterator startCommand, ENetListIterator endCommand, ENetIncomingCommand * excludeCommand)
enet_peer_remove_incoming_commands (ENetList * queue, ENetListIterator startCommand, ENetListIterator endCommand)
{
ENetListIterator currentCommand;
@@ -286,9 +278,6 @@ enet_peer_remove_incoming_commands (ENetList * queue, ENetListIterator startComm
currentCommand = enet_list_next (currentCommand);
if (incomingCommand == excludeCommand)
continue;
enet_list_remove (& incomingCommand -> incomingCommandList);
if (incomingCommand -> packet != NULL)
@@ -309,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), NULL);
enet_peer_remove_incoming_commands(queue, enet_list_begin (queue), enet_list_end (queue));
}
void
@@ -317,19 +306,20 @@ enet_peer_reset_queues (ENetPeer * peer)
{
ENetChannel * channel;
if (peer -> flags & ENET_PEER_FLAG_NEEDS_DISPATCH)
if (peer -> needsDispatch)
{
enet_list_remove (& peer -> dispatchList);
peer -> flags &= ~ ENET_PEER_FLAG_NEEDS_DISPATCH;
peer -> needsDispatch = 0;
}
while (! enet_list_empty (& peer -> acknowledgements))
enet_free (enet_list_remove (enet_list_begin (& peer -> acknowledgements)));
enet_peer_reset_outgoing_commands (& peer -> sentReliableCommands);
enet_peer_reset_outgoing_commands (& peer -> outgoingCommands);
enet_peer_reset_outgoing_commands (& peer -> outgoingSendReliableCommands);
enet_peer_reset_outgoing_commands (& peer -> sentUnreliableCommands);
enet_peer_reset_outgoing_commands (& peer -> outgoingReliableCommands);
enet_peer_reset_outgoing_commands (& peer -> outgoingUnreliableCommands);
enet_peer_reset_incoming_commands (& peer -> dispatchedCommands);
if (peer -> channels != NULL && peer -> channelCount > 0)
@@ -428,7 +418,6 @@ enet_peer_reset (ENetPeer * peer)
peer -> outgoingUnsequencedGroup = 0;
peer -> eventData = 0;
peer -> totalWaitingData = 0;
peer -> flags = 0;
memset (peer -> unsequencedWindow, 0, sizeof (peer -> unsequencedWindow));
@@ -571,17 +560,6 @@ enet_peer_disconnect (ENetPeer * peer, enet_uint32 data)
}
}
int
enet_peer_has_outgoing_commands (ENetPeer * peer)
{
if (enet_list_empty (& peer -> outgoingCommands) &&
enet_list_empty (& peer -> outgoingSendReliableCommands) &&
enet_list_empty (& peer -> sentReliableCommands))
return 0;
return 1;
}
/** Request a disconnection from a peer, but only after all queued outgoing packets are sent.
@param peer peer to request a disconnection
@param data data describing the disconnection
@@ -592,7 +570,9 @@ void
enet_peer_disconnect_later (ENetPeer * peer, enet_uint32 data)
{
if ((peer -> state == ENET_PEER_STATE_CONNECTED || peer -> state == ENET_PEER_STATE_DISCONNECT_LATER) &&
enet_peer_has_outgoing_commands (peer))
! (enet_list_empty (& peer -> outgoingReliableCommands) &&
enet_list_empty (& peer -> outgoingUnreliableCommands) &&
enet_list_empty (& peer -> sentReliableCommands)))
{
peer -> state = ENET_PEER_STATE_DISCONNECT_LATER;
peer -> eventData = data;
@@ -636,6 +616,8 @@ enet_peer_queue_acknowledgement (ENetPeer * peer, const ENetProtocol * command,
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)
@@ -646,40 +628,36 @@ enet_peer_setup_outgoing_command (ENetPeer * peer, ENetOutgoingCommand * outgoin
outgoingCommand -> unreliableSequenceNumber = 0;
}
else
if (outgoingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE)
{
ENetChannel * channel = & peer -> channels [outgoingCommand -> command.header.channelID];
++ channel -> outgoingReliableSequenceNumber;
channel -> outgoingUnreliableSequenceNumber = 0;
if (outgoingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE)
{
++ channel -> outgoingReliableSequenceNumber;
channel -> outgoingUnreliableSequenceNumber = 0;
outgoingCommand -> reliableSequenceNumber = channel -> outgoingReliableSequenceNumber;
outgoingCommand -> unreliableSequenceNumber = 0;
}
else
if (outgoingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_FLAG_UNSEQUENCED)
{
++ peer -> outgoingUnsequencedGroup;
outgoingCommand -> reliableSequenceNumber = 0;
outgoingCommand -> unreliableSequenceNumber = 0;
}
else
{
if (outgoingCommand -> fragmentOffset == 0)
++ channel -> outgoingUnreliableSequenceNumber;
outgoingCommand -> reliableSequenceNumber = channel -> outgoingReliableSequenceNumber;
outgoingCommand -> unreliableSequenceNumber = channel -> outgoingUnreliableSequenceNumber;
}
outgoingCommand -> reliableSequenceNumber = channel -> outgoingReliableSequenceNumber;
outgoingCommand -> unreliableSequenceNumber = 0;
}
else
if (outgoingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_FLAG_UNSEQUENCED)
{
++ peer -> outgoingUnsequencedGroup;
outgoingCommand -> reliableSequenceNumber = 0;
outgoingCommand -> unreliableSequenceNumber = 0;
}
else
{
if (outgoingCommand -> fragmentOffset == 0)
++ channel -> outgoingUnreliableSequenceNumber;
outgoingCommand -> reliableSequenceNumber = channel -> outgoingReliableSequenceNumber;
outgoingCommand -> unreliableSequenceNumber = channel -> outgoingUnreliableSequenceNumber;
}
outgoingCommand -> sendAttempts = 0;
outgoingCommand -> sentTime = 0;
outgoingCommand -> roundTripTimeout = 0;
outgoingCommand -> roundTripTimeoutLimit = 0;
outgoingCommand -> command.header.reliableSequenceNumber = ENET_HOST_TO_NET_16 (outgoingCommand -> reliableSequenceNumber);
outgoingCommand -> queueTime = ++ peer -> host -> totalQueued;
switch (outgoingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_MASK)
{
@@ -690,16 +668,15 @@ enet_peer_setup_outgoing_command (ENetPeer * peer, ENetOutgoingCommand * outgoin
case ENET_PROTOCOL_COMMAND_SEND_UNSEQUENCED:
outgoingCommand -> command.sendUnsequenced.unsequencedGroup = ENET_HOST_TO_NET_16 (peer -> outgoingUnsequencedGroup);
break;
default:
break;
}
if ((outgoingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE) != 0 &&
outgoingCommand -> packet != NULL)
enet_list_insert (enet_list_end (& peer -> outgoingSendReliableCommands), outgoingCommand);
if (outgoingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE)
enet_list_insert (enet_list_end (& peer -> outgoingReliableCommands), outgoingCommand);
else
enet_list_insert (enet_list_end (& peer -> outgoingCommands), outgoingCommand);
enet_list_insert (enet_list_end (& peer -> outgoingUnreliableCommands), outgoingCommand);
}
ENetOutgoingCommand *
@@ -722,7 +699,7 @@ enet_peer_queue_outgoing_command (ENetPeer * peer, const ENetProtocol * command,
}
void
enet_peer_dispatch_incoming_unreliable_commands (ENetPeer * peer, ENetChannel * channel, ENetIncomingCommand * queuedCommand)
enet_peer_dispatch_incoming_unreliable_commands (ENetPeer * peer, ENetChannel * channel)
{
ENetListIterator droppedCommand, startCommand, currentCommand;
@@ -747,11 +724,11 @@ enet_peer_dispatch_incoming_unreliable_commands (ENetPeer * peer, ENetChannel *
{
enet_list_move (enet_list_end (& peer -> dispatchedCommands), startCommand, enet_list_previous (currentCommand));
if (! (peer -> flags & ENET_PEER_FLAG_NEEDS_DISPATCH))
if (! peer -> needsDispatch)
{
enet_list_insert (enet_list_end (& peer -> host -> dispatchQueue), & peer -> dispatchList);
peer -> flags |= ENET_PEER_FLAG_NEEDS_DISPATCH;
peer -> needsDispatch = 1;
}
droppedCommand = currentCommand;
@@ -775,11 +752,11 @@ enet_peer_dispatch_incoming_unreliable_commands (ENetPeer * peer, ENetChannel *
{
enet_list_move (enet_list_end (& peer -> dispatchedCommands), startCommand, enet_list_previous (currentCommand));
if (! (peer -> flags & ENET_PEER_FLAG_NEEDS_DISPATCH))
if (! peer -> needsDispatch)
{
enet_list_insert (enet_list_end (& peer -> host -> dispatchQueue), & peer -> dispatchList);
peer -> flags |= ENET_PEER_FLAG_NEEDS_DISPATCH;
peer -> needsDispatch = 1;
}
}
}
@@ -791,21 +768,21 @@ enet_peer_dispatch_incoming_unreliable_commands (ENetPeer * peer, ENetChannel *
{
enet_list_move (enet_list_end (& peer -> dispatchedCommands), startCommand, enet_list_previous (currentCommand));
if (! (peer -> flags & ENET_PEER_FLAG_NEEDS_DISPATCH))
if (! peer -> needsDispatch)
{
enet_list_insert (enet_list_end (& peer -> host -> dispatchQueue), & peer -> dispatchList);
peer -> flags |= ENET_PEER_FLAG_NEEDS_DISPATCH;
peer -> needsDispatch = 1;
}
droppedCommand = currentCommand;
}
enet_peer_remove_incoming_commands (& channel -> incomingUnreliableCommands, enet_list_begin (& channel -> incomingUnreliableCommands), droppedCommand, queuedCommand);
enet_peer_remove_incoming_commands (& channel -> incomingUnreliableCommands, enet_list_begin (& channel -> incomingUnreliableCommands), droppedCommand);
}
void
enet_peer_dispatch_incoming_reliable_commands (ENetPeer * peer, ENetChannel * channel, ENetIncomingCommand * queuedCommand)
enet_peer_dispatch_incoming_reliable_commands (ENetPeer * peer, ENetChannel * channel)
{
ENetListIterator currentCommand;
@@ -832,15 +809,15 @@ enet_peer_dispatch_incoming_reliable_commands (ENetPeer * peer, ENetChannel * ch
enet_list_move (enet_list_end (& peer -> dispatchedCommands), enet_list_begin (& channel -> incomingReliableCommands), enet_list_previous (currentCommand));
if (! (peer -> flags & ENET_PEER_FLAG_NEEDS_DISPATCH))
if (! peer -> needsDispatch)
{
enet_list_insert (enet_list_end (& peer -> host -> dispatchQueue), & peer -> dispatchList);
peer -> flags |= ENET_PEER_FLAG_NEEDS_DISPATCH;
peer -> needsDispatch = 1;
}
if (! enet_list_empty (& channel -> incomingUnreliableCommands))
enet_peer_dispatch_incoming_unreliable_commands (peer, channel, queuedCommand);
enet_peer_dispatch_incoming_unreliable_commands (peer, channel);
}
ENetIncomingCommand *
@@ -998,11 +975,11 @@ enet_peer_queue_incoming_command (ENetPeer * peer, const ENetProtocol * command,
{
case ENET_PROTOCOL_COMMAND_SEND_FRAGMENT:
case ENET_PROTOCOL_COMMAND_SEND_RELIABLE:
enet_peer_dispatch_incoming_reliable_commands (peer, channel, incomingCommand);
enet_peer_dispatch_incoming_reliable_commands (peer, channel);
break;
default:
enet_peer_dispatch_incoming_unreliable_commands (peer, channel, incomingCommand);
enet_peer_dispatch_incoming_unreliable_commands (peer, channel);
break;
}
+254 -302
View File
@@ -9,7 +9,7 @@
#include "enet/time.h"
#include "enet/enet.h"
static const size_t commandSizes [ENET_PROTOCOL_COMMAND_COUNT] =
static size_t commandSizes [ENET_PROTOCOL_COMMAND_COUNT] =
{
0,
sizeof (ENetProtocolAcknowledge),
@@ -48,11 +48,11 @@ enet_protocol_dispatch_state (ENetHost * host, ENetPeer * peer, ENetPeerState st
{
enet_protocol_change_state (host, peer, state);
if (! (peer -> flags & ENET_PEER_FLAG_NEEDS_DISPATCH))
if (! peer -> needsDispatch)
{
enet_list_insert (enet_list_end (& host -> dispatchQueue), & peer -> dispatchList);
peer -> flags |= ENET_PEER_FLAG_NEEDS_DISPATCH;
peer -> needsDispatch = 1;
}
}
@@ -63,7 +63,7 @@ enet_protocol_dispatch_incoming_commands (ENetHost * host, ENetEvent * event)
{
ENetPeer * peer = (ENetPeer *) enet_list_remove (enet_list_begin (& host -> dispatchQueue));
peer -> flags &= ~ ENET_PEER_FLAG_NEEDS_DISPATCH;
peer -> needsDispatch = 0;
switch (peer -> state)
{
@@ -101,7 +101,7 @@ enet_protocol_dispatch_incoming_commands (ENetHost * host, ENetEvent * event)
if (! enet_list_empty (& peer -> dispatchedCommands))
{
peer -> flags |= ENET_PEER_FLAG_NEEDS_DISPATCH;
peer -> needsDispatch = 1;
enet_list_insert (enet_list_end (& host -> dispatchQueue), & peer -> dispatchList);
}
@@ -159,16 +159,13 @@ enet_protocol_notify_disconnect (ENetHost * host, ENetPeer * peer, ENetEvent * e
}
static void
enet_protocol_remove_sent_unreliable_commands (ENetPeer * peer, ENetList * sentUnreliableCommands)
enet_protocol_remove_sent_unreliable_commands (ENetPeer * peer)
{
ENetOutgoingCommand * outgoingCommand;
if (enet_list_empty (sentUnreliableCommands))
return;
do
while (! enet_list_empty (& peer -> sentUnreliableCommands))
{
outgoingCommand = (ENetOutgoingCommand *) enet_list_front (sentUnreliableCommands);
outgoingCommand = (ENetOutgoingCommand *) enet_list_front (& peer -> sentUnreliableCommands);
enet_list_remove (& outgoingCommand -> outgoingCommandList);
@@ -185,36 +182,7 @@ enet_protocol_remove_sent_unreliable_commands (ENetPeer * peer, ENetList * sentU
}
enet_free (outgoingCommand);
} while (! enet_list_empty (sentUnreliableCommands));
if (peer -> state == ENET_PEER_STATE_DISCONNECT_LATER &&
! enet_peer_has_outgoing_commands (peer))
enet_peer_disconnect (peer, peer -> eventData);
}
static ENetOutgoingCommand *
enet_protocol_find_sent_reliable_command (ENetList * list, enet_uint16 reliableSequenceNumber, enet_uint8 channelID)
{
ENetListIterator currentCommand;
for (currentCommand = enet_list_begin (list);
currentCommand != enet_list_end (list);
currentCommand = enet_list_next (currentCommand))
{
ENetOutgoingCommand * outgoingCommand = (ENetOutgoingCommand *) currentCommand;
if (! (outgoingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE))
continue;
if (outgoingCommand -> sendAttempts < 1)
break;
if (outgoingCommand -> reliableSequenceNumber == reliableSequenceNumber &&
outgoingCommand -> command.header.channelID == channelID)
return outgoingCommand;
}
return NULL;
}
static ENetProtocolCommand
@@ -238,9 +206,21 @@ enet_protocol_remove_sent_reliable_command (ENetPeer * peer, enet_uint16 reliabl
if (currentCommand == enet_list_end (& peer -> sentReliableCommands))
{
outgoingCommand = enet_protocol_find_sent_reliable_command (& peer -> outgoingCommands, reliableSequenceNumber, channelID);
if (outgoingCommand == NULL)
outgoingCommand = enet_protocol_find_sent_reliable_command (& peer -> outgoingSendReliableCommands, reliableSequenceNumber, channelID);
for (currentCommand = enet_list_begin (& peer -> outgoingReliableCommands);
currentCommand != enet_list_end (& peer -> outgoingReliableCommands);
currentCommand = enet_list_next (currentCommand))
{
outgoingCommand = (ENetOutgoingCommand *) currentCommand;
if (outgoingCommand -> sendAttempts < 1) return ENET_PROTOCOL_COMMAND_NONE;
if (outgoingCommand -> reliableSequenceNumber == reliableSequenceNumber &&
outgoingCommand -> command.header.channelID == channelID)
break;
}
if (currentCommand == enet_list_end (& peer -> outgoingReliableCommands))
return ENET_PROTOCOL_COMMAND_NONE;
wasSent = 0;
}
@@ -318,7 +298,7 @@ enet_protocol_handle_connect (ENetHost * host, ENetProtocolHeader * header, ENet
}
else
if (currentPeer -> state != ENET_PEER_STATE_CONNECTING &&
enet_address_equal (& currentPeer -> address, & host -> receivedPeerAddress))
enet_address_equal (& currentPeer -> address, & host -> receivedAddress))
{
if (currentPeer -> connectID == command -> connect.connectID)
return NULL;
@@ -338,9 +318,7 @@ enet_protocol_handle_connect (ENetHost * host, ENetProtocolHeader * header, ENet
peer -> channelCount = channelCount;
peer -> state = ENET_PEER_STATE_ACKNOWLEDGING_CONNECT;
peer -> connectID = command -> connect.connectID;
peer -> address = host -> receivedPeerAddress;
peer -> localAddress = host -> receivedLocalAddress;
peer -> mtu = host -> mtu;
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);
@@ -385,8 +363,7 @@ enet_protocol_handle_connect (ENetHost * host, ENetProtocolHeader * header, ENet
if (mtu > ENET_PROTOCOL_MAXIMUM_MTU)
mtu = ENET_PROTOCOL_MAXIMUM_MTU;
if (mtu < peer -> mtu)
peer -> mtu = mtu;
peer -> mtu = mtu;
if (host -> outgoingBandwidth == 0 &&
peer -> incomingBandwidth == 0)
@@ -553,8 +530,7 @@ enet_protocol_handle_send_fragment (ENetHost * host, ENetPeer * peer, const ENet
fragmentLength = ENET_NET_TO_HOST_16 (command -> sendFragment.dataLength);
* currentData += fragmentLength;
if (fragmentLength <= 0 ||
fragmentLength > host -> maximumPacketSize ||
if (fragmentLength > host -> maximumPacketSize ||
* currentData < host -> receivedData ||
* currentData > & host -> receivedData [host -> receivedDataLength])
return -1;
@@ -578,7 +554,6 @@ enet_protocol_handle_send_fragment (ENetHost * host, ENetPeer * peer, const ENet
if (fragmentCount > ENET_PROTOCOL_MAXIMUM_FRAGMENT_COUNT ||
fragmentNumber >= fragmentCount ||
totalLength > host -> maximumPacketSize ||
totalLength < fragmentCount ||
fragmentOffset >= totalLength ||
fragmentLength > totalLength - fragmentOffset)
return -1;
@@ -638,7 +613,7 @@ enet_protocol_handle_send_fragment (ENetHost * host, ENetPeer * peer, const ENet
fragmentLength);
if (startCommand -> fragmentsRemaining <= 0)
enet_peer_dispatch_incoming_reliable_commands (peer, channel, NULL);
enet_peer_dispatch_incoming_reliable_commands (peer, channel);
}
return 0;
@@ -756,7 +731,7 @@ enet_protocol_handle_send_unreliable_fragment (ENetHost * host, ENetPeer * peer,
fragmentLength);
if (startCommand -> fragmentsRemaining <= 0)
enet_peer_dispatch_incoming_unreliable_commands (peer, channel, NULL);
enet_peer_dispatch_incoming_unreliable_commands (peer, channel);
}
return 0;
@@ -866,53 +841,42 @@ enet_protocol_handle_acknowledge (ENetHost * host, ENetEvent * event, ENetPeer *
if (ENET_TIME_LESS (host -> serviceTime, receivedSentTime))
return 0;
peer -> lastReceiveTime = host -> serviceTime;
peer -> earliestTimeout = 0;
roundTripTime = ENET_TIME_DIFFERENCE (host -> serviceTime, receivedSentTime);
roundTripTime = ENET_MAX (roundTripTime, 1);
if (peer -> lastReceiveTime > 0)
enet_peer_throttle (peer, roundTripTime);
peer -> roundTripTimeVariance -= peer -> roundTripTimeVariance / 4;
if (roundTripTime >= peer -> roundTripTime)
{
enet_peer_throttle (peer, roundTripTime);
peer -> roundTripTimeVariance -= (peer -> roundTripTimeVariance + 3) / 4;
if (roundTripTime >= peer -> roundTripTime)
{
enet_uint32 diff = roundTripTime - peer -> roundTripTime;
peer -> roundTripTimeVariance += (diff + 3) / 4;
peer -> roundTripTime += (diff + 7) / 8;
}
else
{
enet_uint32 diff = peer -> roundTripTime - roundTripTime;
peer -> roundTripTimeVariance += (diff + 3) / 4;
peer -> roundTripTime -= (diff + 7) / 8;
}
peer -> roundTripTime += (roundTripTime - peer -> roundTripTime) / 8;
peer -> roundTripTimeVariance += (roundTripTime - peer -> roundTripTime) / 4;
}
else
{
peer -> roundTripTime = roundTripTime;
peer -> roundTripTimeVariance = (roundTripTime + 1) / 2;
peer -> roundTripTime -= (peer -> roundTripTime - roundTripTime) / 8;
peer -> roundTripTimeVariance += (peer -> roundTripTime - roundTripTime) / 4;
}
if (peer -> roundTripTime < peer -> lowestRoundTripTime)
peer -> lowestRoundTripTime = peer -> roundTripTime;
if (peer -> roundTripTimeVariance > peer -> highestRoundTripTimeVariance)
if (peer -> roundTripTimeVariance > peer -> highestRoundTripTimeVariance)
peer -> highestRoundTripTimeVariance = peer -> roundTripTimeVariance;
if (peer -> packetThrottleEpoch == 0 ||
ENET_TIME_DIFFERENCE (host -> serviceTime, peer -> packetThrottleEpoch) >= peer -> packetThrottleInterval)
{
peer -> lastRoundTripTime = peer -> lowestRoundTripTime;
peer -> lastRoundTripTimeVariance = ENET_MAX (peer -> highestRoundTripTimeVariance, 1);
peer -> lastRoundTripTimeVariance = peer -> highestRoundTripTimeVariance;
peer -> lowestRoundTripTime = peer -> roundTripTime;
peer -> highestRoundTripTimeVariance = peer -> roundTripTimeVariance;
peer -> packetThrottleEpoch = host -> serviceTime;
}
peer -> lastReceiveTime = ENET_MAX (host -> serviceTime, 1);
peer -> earliestTimeout = 0;
receivedReliableSequenceNumber = ENET_NET_TO_HOST_16 (command -> acknowledge.receivedReliableSequenceNumber);
commandNumber = enet_protocol_remove_sent_reliable_command (peer, receivedReliableSequenceNumber, command -> header.channelID);
@@ -934,7 +898,9 @@ enet_protocol_handle_acknowledge (ENetHost * host, ENetEvent * event, ENetPeer *
break;
case ENET_PEER_STATE_DISCONNECT_LATER:
if (! enet_peer_has_outgoing_commands (peer))
if (enet_list_empty (& peer -> outgoingReliableCommands) &&
enet_list_empty (& peer -> outgoingUnreliableCommands) &&
enet_list_empty (& peer -> sentReliableCommands))
enet_peer_disconnect (peer, peer -> eventData);
break;
@@ -1085,8 +1051,7 @@ enet_protocol_handle_incoming_commands (ENetHost * host, ENetEvent * event)
if (peer != NULL)
{
memcpy(& peer -> address, & host -> receivedPeerAddress, sizeof (host -> receivedPeerAddress));
memcpy(& peer -> localAddress, & host -> receivedLocalAddress, sizeof (host -> receivedLocalAddress));
memcpy(& peer -> address, & host -> receivedAddress, sizeof (host -> receivedAddress));
peer -> incomingDataTotal += host -> receivedDataLength;
}
@@ -1237,14 +1202,10 @@ enet_protocol_receive_incoming_commands (ENetHost * host, ENetEvent * event)
buffer.dataLength = sizeof (host -> packetData [0]);
receivedLength = enet_socket_receive (host -> socket,
& host -> receivedPeerAddress,
& host -> receivedLocalAddress,
& host -> receivedAddress,
& buffer,
1);
if (receivedLength == -2)
continue;
if (receivedLength < 0)
return -1;
@@ -1288,7 +1249,7 @@ enet_protocol_receive_incoming_commands (ENetHost * host, ENetEvent * event)
}
}
return 0;
return -1;
}
static void
@@ -1308,7 +1269,7 @@ enet_protocol_send_acknowledgements (ENetHost * host, ENetPeer * peer)
buffer >= & host -> buffers [sizeof (host -> buffers) / sizeof (ENetBuffer)] ||
peer -> mtu - host -> packetSize < sizeof (ENetProtocolAcknowledge))
{
peer -> flags |= ENET_PEER_FLAG_CONTINUE_SENDING;
host -> continueSending = 1;
break;
}
@@ -1344,16 +1305,115 @@ enet_protocol_send_acknowledgements (ENetHost * host, ENetPeer * peer)
host -> bufferCount = buffer - host -> buffers;
}
static void
enet_protocol_send_unreliable_outgoing_commands (ENetHost * host, ENetPeer * peer)
{
ENetProtocol * command = & host -> commands [host -> commandCount];
ENetBuffer * buffer = & host -> buffers [host -> bufferCount];
ENetOutgoingCommand * outgoingCommand;
ENetListIterator currentCommand;
currentCommand = enet_list_begin (& peer -> outgoingUnreliableCommands);
while (currentCommand != enet_list_end (& peer -> outgoingUnreliableCommands))
{
size_t commandSize;
outgoingCommand = (ENetOutgoingCommand *) currentCommand;
commandSize = commandSizes [outgoingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_MASK];
if (command >= & host -> commands [sizeof (host -> commands) / sizeof (ENetProtocol)] ||
buffer + 1 >= & host -> buffers [sizeof (host -> buffers) / sizeof (ENetBuffer)] ||
peer -> mtu - host -> packetSize < commandSize ||
(outgoingCommand -> packet != NULL &&
peer -> mtu - host -> packetSize < commandSize + outgoingCommand -> fragmentLength))
{
host -> continueSending = 1;
break;
}
currentCommand = enet_list_next (currentCommand);
if (outgoingCommand -> packet != NULL && outgoingCommand -> fragmentOffset == 0)
{
peer -> packetThrottleCounter += ENET_PEER_PACKET_THROTTLE_COUNTER;
peer -> packetThrottleCounter %= ENET_PEER_PACKET_THROTTLE_SCALE;
if (peer -> packetThrottleCounter > peer -> packetThrottle)
{
enet_uint16 reliableSequenceNumber = outgoingCommand -> reliableSequenceNumber,
unreliableSequenceNumber = outgoingCommand -> unreliableSequenceNumber;
for (;;)
{
-- outgoingCommand -> packet -> referenceCount;
if (outgoingCommand -> packet -> referenceCount == 0)
enet_packet_destroy (outgoingCommand -> packet);
enet_list_remove (& outgoingCommand -> outgoingCommandList);
enet_free (outgoingCommand);
if (currentCommand == enet_list_end (& peer -> outgoingUnreliableCommands))
break;
outgoingCommand = (ENetOutgoingCommand *) currentCommand;
if (outgoingCommand -> reliableSequenceNumber != reliableSequenceNumber ||
outgoingCommand -> unreliableSequenceNumber != unreliableSequenceNumber)
break;
currentCommand = enet_list_next (currentCommand);
}
continue;
}
}
buffer -> data = command;
buffer -> dataLength = commandSize;
host -> packetSize += buffer -> dataLength;
* command = outgoingCommand -> command;
enet_list_remove (& outgoingCommand -> outgoingCommandList);
if (outgoingCommand -> packet != NULL)
{
++ buffer;
buffer -> data = outgoingCommand -> packet -> data + outgoingCommand -> fragmentOffset;
buffer -> dataLength = outgoingCommand -> fragmentLength;
host -> packetSize += buffer -> dataLength;
enet_list_insert (enet_list_end (& peer -> sentUnreliableCommands), outgoingCommand);
}
else
enet_free (outgoingCommand);
++ command;
++ buffer;
}
host -> commandCount = command - host -> commands;
host -> bufferCount = buffer - host -> buffers;
if (peer -> state == ENET_PEER_STATE_DISCONNECT_LATER &&
enet_list_empty (& peer -> outgoingReliableCommands) &&
enet_list_empty (& peer -> outgoingUnreliableCommands) &&
enet_list_empty (& peer -> sentReliableCommands))
enet_peer_disconnect (peer, peer -> eventData);
}
static int
enet_protocol_check_timeouts (ENetHost * host, ENetPeer * peer, ENetEvent * event)
{
ENetOutgoingCommand * outgoingCommand;
ENetListIterator currentCommand, insertPosition, insertSendReliablePosition;
enet_uint32 roundTripTimeout;
ENetListIterator currentCommand, insertPosition;
currentCommand = enet_list_begin (& peer -> sentReliableCommands);
insertPosition = enet_list_begin (& peer -> outgoingCommands);
insertSendReliablePosition = enet_list_begin (& peer -> outgoingSendReliableCommands);
insertPosition = enet_list_begin (& peer -> outgoingReliableCommands);
while (currentCommand != enet_list_end (& peer -> sentReliableCommands))
{
@@ -1370,7 +1430,7 @@ enet_protocol_check_timeouts (ENetHost * host, ENetPeer * peer, ENetEvent * even
if (peer -> earliestTimeout != 0 &&
(ENET_TIME_DIFFERENCE (host -> serviceTime, peer -> earliestTimeout) >= peer -> timeoutMaximum ||
((1U << (outgoingCommand -> sendAttempts - 1)) >= peer -> timeoutLimit &&
(outgoingCommand -> roundTripTimeout >= outgoingCommand -> roundTripTimeoutLimit &&
ENET_TIME_DIFFERENCE (host -> serviceTime, peer -> earliestTimeout) >= peer -> timeoutMinimum)))
{
enet_protocol_notify_disconnect (host, peer, event);
@@ -1378,23 +1438,14 @@ enet_protocol_check_timeouts (ENetHost * host, ENetPeer * peer, ENetEvent * even
return 1;
}
if (outgoingCommand -> packet != NULL)
peer -> reliableDataInTransit -= outgoingCommand -> fragmentLength;
++ peer -> packetsLost;
roundTripTimeout = peer -> roundTripTime + ENET_MIN (peer -> roundTripTime, 4 * ENET_MAX (1, peer -> roundTripTimeVariance));
roundTripTimeout = ENET_MIN (roundTripTimeout, peer->timeoutMaximum / 5);
if (outgoingCommand -> sendAttempts < peer -> timeoutLimit)
outgoingCommand -> roundTripTimeout = roundTripTimeout * ENET_MAX (1, outgoingCommand -> sendAttempts);
else
outgoingCommand -> roundTripTimeout = roundTripTimeout * peer -> timeoutLimit;
outgoingCommand -> roundTripTimeout *= 2;
if (outgoingCommand -> packet != NULL)
{
peer -> reliableDataInTransit -= outgoingCommand -> fragmentLength;
enet_list_insert (insertSendReliablePosition, enet_list_remove (& outgoingCommand -> outgoingCommandList));
}
else
enet_list_insert (insertPosition, enet_list_remove (& outgoingCommand -> outgoingCommandList));
enet_list_insert (insertPosition, enet_list_remove (& outgoingCommand -> outgoingCommandList));
if (currentCommand == enet_list_begin (& peer -> sentReliableCommands) &&
! enet_list_empty (& peer -> sentReliableCommands))
@@ -1409,79 +1460,61 @@ enet_protocol_check_timeouts (ENetHost * host, ENetPeer * peer, ENetEvent * even
}
static int
enet_protocol_check_outgoing_commands (ENetHost * host, ENetPeer * peer, ENetList * sentUnreliableCommands)
enet_protocol_send_reliable_outgoing_commands (ENetHost * host, ENetPeer * peer)
{
ENetProtocol * command = & host -> commands [host -> commandCount];
ENetBuffer * buffer = & host -> buffers [host -> bufferCount];
ENetOutgoingCommand * outgoingCommand;
ENetListIterator currentCommand, currentSendReliableCommand;
ENetChannel *channel = NULL;
enet_uint16 reliableWindow = 0;
ENetListIterator currentCommand;
ENetChannel *channel;
enet_uint16 reliableWindow;
size_t commandSize;
int windowWrap = 0, canPing = 1;
int windowExceeded = 0, windowWrap = 0, canPing = 1;
currentCommand = enet_list_begin (& peer -> outgoingCommands);
currentSendReliableCommand = enet_list_begin (& peer -> outgoingSendReliableCommands);
for (;;)
currentCommand = enet_list_begin (& peer -> outgoingReliableCommands);
while (currentCommand != enet_list_end (& peer -> outgoingReliableCommands))
{
if (currentCommand != enet_list_end (& peer -> outgoingCommands))
{
outgoingCommand = (ENetOutgoingCommand *) currentCommand;
outgoingCommand = (ENetOutgoingCommand *) currentCommand;
if (currentSendReliableCommand != enet_list_end (& peer -> outgoingSendReliableCommands) &&
ENET_TIME_LESS (((ENetOutgoingCommand *) currentSendReliableCommand) -> queueTime, outgoingCommand -> queueTime))
goto useSendReliableCommand;
currentCommand = enet_list_next (currentCommand);
}
else
if (currentSendReliableCommand != enet_list_end (& peer -> outgoingSendReliableCommands))
channel = outgoingCommand -> command.header.channelID < peer -> channelCount ? & peer -> channels [outgoingCommand -> command.header.channelID] : NULL;
reliableWindow = outgoingCommand -> reliableSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE;
if (channel != NULL)
{
useSendReliableCommand:
outgoingCommand = (ENetOutgoingCommand *) currentSendReliableCommand;
currentSendReliableCommand = enet_list_next (currentSendReliableCommand);
}
else
break;
if (outgoingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE)
{
channel = outgoingCommand -> command.header.channelID < peer -> channelCount ? & peer -> channels [outgoingCommand -> command.header.channelID] : NULL;
reliableWindow = outgoingCommand -> reliableSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE;
if (channel != NULL)
if (! windowWrap &&
outgoingCommand -> sendAttempts < 1 &&
! (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_WINDOWS - reliableWindow)))))
windowWrap = 1;
if (windowWrap)
{
if (windowWrap)
continue;
else
if (outgoingCommand -> sendAttempts < 1 &&
! (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 + 2)) - 1) << reliableWindow) |
(((1 << (ENET_PEER_FREE_RELIABLE_WINDOWS + 2)) - 1) >> (ENET_PEER_RELIABLE_WINDOWS - reliableWindow)))))
{
windowWrap = 1;
currentSendReliableCommand = enet_list_end (& peer -> outgoingSendReliableCommands);
continue;
}
currentCommand = enet_list_next (currentCommand);
continue;
}
if (outgoingCommand -> packet != NULL)
}
if (outgoingCommand -> packet != NULL)
{
if (! windowExceeded)
{
enet_uint32 windowSize = (peer -> packetThrottle * peer -> windowSize) / ENET_PEER_PACKET_THROTTLE_SCALE;
if (peer -> reliableDataInTransit + outgoingCommand -> fragmentLength > ENET_MAX (windowSize, peer -> mtu))
{
currentSendReliableCommand = enet_list_end (& peer -> outgoingSendReliableCommands);
continue;
}
windowExceeded = 1;
}
if (windowExceeded)
{
currentCommand = enet_list_next (currentCommand);
canPing = 0;
continue;
}
}
canPing = 0;
commandSize = commandSizes [outgoingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_MASK];
if (command >= & host -> commands [sizeof (host -> commands) / sizeof (ENetProtocol)] ||
buffer + 1 >= & host -> buffers [sizeof (host -> buffers) / sizeof (ENetBuffer)] ||
@@ -1489,84 +1522,40 @@ enet_protocol_check_outgoing_commands (ENetHost * host, ENetPeer * peer, ENetLis
(outgoingCommand -> packet != NULL &&
(enet_uint16) (peer -> mtu - host -> packetSize) < (enet_uint16) (commandSize + outgoingCommand -> fragmentLength)))
{
peer -> flags |= ENET_PEER_FLAG_CONTINUE_SENDING;
host -> continueSending = 1;
break;
}
if (outgoingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE)
currentCommand = enet_list_next (currentCommand);
if (channel != NULL && outgoingCommand -> sendAttempts < 1)
{
if (channel != NULL && outgoingCommand -> sendAttempts < 1)
{
channel -> usedReliableWindows |= 1 << reliableWindow;
++ channel -> reliableWindows [reliableWindow];
}
++ outgoingCommand -> sendAttempts;
if (outgoingCommand -> roundTripTimeout == 0) {
outgoingCommand -> roundTripTimeout = peer -> roundTripTime + ENET_MIN (peer -> roundTripTime, 4 * ENET_MAX (1, peer -> roundTripTimeVariance));
outgoingCommand -> roundTripTimeout = ENET_MIN (outgoingCommand -> roundTripTimeout, peer->timeoutMaximum / 5);
}
if (enet_list_empty (& peer -> sentReliableCommands))
peer -> nextTimeout = host -> serviceTime + outgoingCommand -> roundTripTimeout;
enet_list_insert (enet_list_end (& peer -> sentReliableCommands),
enet_list_remove (& outgoingCommand -> outgoingCommandList));
outgoingCommand -> sentTime = host -> serviceTime;
host -> headerFlags |= ENET_PROTOCOL_HEADER_FLAG_SENT_TIME;
peer -> reliableDataInTransit += outgoingCommand -> fragmentLength;
channel -> usedReliableWindows |= 1 << reliableWindow;
++ channel -> reliableWindows [reliableWindow];
}
else
++ outgoingCommand -> sendAttempts;
if (outgoingCommand -> roundTripTimeout == 0)
{
if (outgoingCommand -> packet != NULL && outgoingCommand -> fragmentOffset == 0)
{
peer -> packetThrottleCounter += ENET_PEER_PACKET_THROTTLE_COUNTER;
peer -> packetThrottleCounter %= ENET_PEER_PACKET_THROTTLE_SCALE;
if (peer -> packetThrottleCounter > peer -> packetThrottle)
{
enet_uint16 reliableSequenceNumber = outgoingCommand -> reliableSequenceNumber,
unreliableSequenceNumber = outgoingCommand -> unreliableSequenceNumber;
for (;;)
{
-- outgoingCommand -> packet -> referenceCount;
if (outgoingCommand -> packet -> referenceCount == 0)
enet_packet_destroy (outgoingCommand -> packet);
enet_list_remove (& outgoingCommand -> outgoingCommandList);
enet_free (outgoingCommand);
if (currentCommand == enet_list_end (& peer -> outgoingCommands))
break;
outgoingCommand = (ENetOutgoingCommand *) currentCommand;
if (outgoingCommand -> reliableSequenceNumber != reliableSequenceNumber ||
outgoingCommand -> unreliableSequenceNumber != unreliableSequenceNumber)
break;
currentCommand = enet_list_next (currentCommand);
}
continue;
}
}
enet_list_remove (& outgoingCommand -> outgoingCommandList);
if (outgoingCommand -> packet != NULL)
enet_list_insert (enet_list_end (sentUnreliableCommands), outgoingCommand);
outgoingCommand -> roundTripTimeout = peer -> roundTripTime + 4 * peer -> roundTripTimeVariance;
outgoingCommand -> roundTripTimeoutLimit = peer -> timeoutLimit * outgoingCommand -> roundTripTimeout;
}
if (enet_list_empty (& peer -> sentReliableCommands))
peer -> nextTimeout = host -> serviceTime + outgoingCommand -> roundTripTimeout;
enet_list_insert (enet_list_end (& peer -> sentReliableCommands),
enet_list_remove (& outgoingCommand -> outgoingCommandList));
outgoingCommand -> sentTime = host -> serviceTime;
buffer -> data = command;
buffer -> dataLength = commandSize;
host -> packetSize += buffer -> dataLength;
host -> headerFlags |= ENET_PROTOCOL_HEADER_FLAG_SENT_TIME;
* command = outgoingCommand -> command;
@@ -1578,10 +1567,9 @@ enet_protocol_check_outgoing_commands (ENetHost * host, ENetPeer * peer, ENetLis
buffer -> dataLength = outgoingCommand -> fragmentLength;
host -> packetSize += outgoingCommand -> fragmentLength;
peer -> reliableDataInTransit += outgoingCommand -> fragmentLength;
}
else
if (! (outgoingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE))
enet_free (outgoingCommand);
++ peer -> packetsSent;
@@ -1592,11 +1580,6 @@ enet_protocol_check_outgoing_commands (ENetHost * host, ENetPeer * peer, ENetLis
host -> commandCount = command - host -> commands;
host -> bufferCount = buffer - host -> buffers;
if (peer -> state == ENET_PEER_STATE_DISCONNECT_LATER &&
! enet_peer_has_outgoing_commands (peer) &&
enet_list_empty (sentUnreliableCommands))
enet_peer_disconnect (peer, peer -> eventData);
return canPing;
}
@@ -1605,24 +1588,22 @@ enet_protocol_send_outgoing_commands (ENetHost * host, ENetEvent * event, int ch
{
enet_uint8 headerData [sizeof (ENetProtocolHeader) + sizeof (enet_uint32)];
ENetProtocolHeader * header = (ENetProtocolHeader *) headerData;
int sentLength = 0;
ENetPeer * currentPeer;
int sentLength;
size_t shouldCompress = 0;
ENetList sentUnreliableCommands;
host -> continueSending = 1;
enet_list_clear (& sentUnreliableCommands);
for (int sendPass = 0, continueSending = 0; sendPass <= continueSending; ++ sendPass)
for (ENetPeer * currentPeer = host -> peers;
while (host -> continueSending)
for (host -> continueSending = 0,
currentPeer = host -> peers;
currentPeer < & host -> peers [host -> peerCount];
++ currentPeer)
{
if (currentPeer -> state == ENET_PEER_STATE_DISCONNECTED ||
currentPeer -> state == ENET_PEER_STATE_ZOMBIE ||
(sendPass > 0 && ! (currentPeer -> flags & ENET_PEER_FLAG_CONTINUE_SENDING)))
currentPeer -> state == ENET_PEER_STATE_ZOMBIE)
continue;
currentPeer -> flags &= ~ ENET_PEER_FLAG_CONTINUE_SENDING;
host -> headerFlags = 0;
host -> commandCount = 0;
host -> bufferCount = 1;
@@ -1639,22 +1620,24 @@ enet_protocol_send_outgoing_commands (ENetHost * host, ENetEvent * event, int ch
if (event != NULL && event -> type != ENET_EVENT_TYPE_NONE)
return 1;
else
goto nextPeer;
continue;
}
if (((enet_list_empty (& currentPeer -> outgoingCommands) &&
enet_list_empty (& currentPeer -> outgoingSendReliableCommands)) ||
enet_protocol_check_outgoing_commands (host, currentPeer, & sentUnreliableCommands)) &&
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) >= currentPeer -> pingInterval &&
currentPeer -> mtu - host -> packetSize >= sizeof (ENetProtocolPing))
{
enet_peer_ping (currentPeer);
enet_protocol_check_outgoing_commands (host, currentPeer, & sentUnreliableCommands);
enet_protocol_send_reliable_outgoing_commands (host, currentPeer);
}
if (! enet_list_empty (& currentPeer -> outgoingUnreliableCommands))
enet_protocol_send_unreliable_outgoing_commands (host, currentPeer);
if (host -> commandCount == 0)
goto nextPeer;
continue;
if (currentPeer -> packetLossEpoch == 0)
currentPeer -> packetLossEpoch = host -> serviceTime;
@@ -1665,11 +1648,21 @@ 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
printf ("peer %u: %f%%+-%f%% packet loss, %u+-%u ms round trip time, %f%% throttle, %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 -> outgoingCommands) + enet_list_size (& currentPeer -> outgoingSendReliableCommands), 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;
currentPeer -> packetLossVariance = (currentPeer -> packetLossVariance * 3 + ENET_DIFFERENCE (packetLoss, currentPeer -> packetLoss)) / 4;
currentPeer -> packetLoss = (currentPeer -> packetLoss * 7 + packetLoss) / 8;
if (packetLoss >= currentPeer -> packetLoss)
{
currentPeer -> packetLoss += (packetLoss - currentPeer -> packetLoss) / 8;
currentPeer -> packetLossVariance += (packetLoss - currentPeer -> packetLoss) / 4;
}
else
{
currentPeer -> packetLoss -= (currentPeer -> packetLoss - packetLoss) / 8;
currentPeer -> packetLossVariance += (currentPeer -> packetLoss - packetLoss) / 4;
}
currentPeer -> packetLossEpoch = host -> serviceTime;
currentPeer -> packetsSent = 0;
@@ -1725,61 +1718,26 @@ enet_protocol_send_outgoing_commands (ENetHost * host, ENetEvent * event, int ch
currentPeer -> lastSendTime = host -> serviceTime;
if ((currentPeer -> state == ENET_PEER_STATE_CONNECTING || currentPeer -> state == ENET_PEER_STATE_ACKNOWLEDGING_CONNECT) && currentPeer -> packetsLost == 3) {
// Disable QoS tagging if we don't get a response to 3 connection requests/acks in a row.
if (currentPeer -> state == ENET_PEER_STATE_CONNECTING && currentPeer -> packetsLost == 2) {
// Disable QoS tagging if we don't get a response to 2 connection requests in a row.
// Some networks drop QoS tagged packets, so let's try without it.
enet_socket_set_option (host -> socket, ENET_SOCKOPT_QOS, 0);
}
sentLength = enet_socket_send (host -> socket, & currentPeer -> address,
host -> wildcardBind ? (& currentPeer -> localAddress) : NULL,
host -> buffers, host -> bufferCount);
sentLength = enet_socket_send (host -> socket, & currentPeer -> address, host -> buffers, host -> bufferCount);
enet_protocol_remove_sent_unreliable_commands (currentPeer, & sentUnreliableCommands);
enet_protocol_remove_sent_unreliable_commands (currentPeer);
if (sentLength < 0)
return -1;
host -> totalSentData += sentLength;
host -> totalSentPackets ++;
nextPeer:
if (currentPeer -> flags & ENET_PEER_FLAG_CONTINUE_SENDING)
continueSending = sendPass + 1;
}
return 0;
}
static enet_uint32
enet_protocol_compute_wait_timeout(ENetHost * host, enet_uint32 timeout)
{
for (ENetPeer * currentPeer = host -> peers;
currentPeer < & host -> peers [host -> peerCount];
++ currentPeer)
{
if (! ENET_TIME_LESS (currentPeer -> nextTimeout, host -> serviceTime)) {
timeout = ENET_MIN (timeout, ENET_TIME_DIFFERENCE (currentPeer -> nextTimeout, host -> serviceTime) + 1);
}
if (currentPeer -> lastReceiveTime && currentPeer -> lastSendTime) {
enet_uint32 timeSinceLastRecv = ENET_TIME_DIFFERENCE (host -> serviceTime, currentPeer -> lastReceiveTime);
enet_uint32 timeSinceLastSend = ENET_TIME_DIFFERENCE (host -> serviceTime, currentPeer -> lastSendTime);
enet_uint32 timeSinceLastComm = ENET_MIN(timeSinceLastSend, timeSinceLastRecv);
if (timeSinceLastComm >= currentPeer -> pingInterval) {
// Ping is due now for this peer
return 0;
} else {
timeout = ENET_MIN (timeout, currentPeer -> pingInterval - timeSinceLastComm);
}
} else {
timeout = ENET_MIN (timeout, currentPeer -> pingInterval);
}
}
return timeout;
}
/** Sends any queued packets on the host specified to its designated peers.
@param host host to flush
@@ -1937,20 +1895,14 @@ enet_host_service (ENetHost * host, ENetEvent * event, enet_uint32 timeout)
do
{
enet_uint32 waitTime;
host -> serviceTime = enet_time_get ();
if (ENET_TIME_GREATER_EQUAL (host -> serviceTime, timeout))
return 0;
waitTime = enet_protocol_compute_wait_timeout(host, ENET_TIME_DIFFERENCE (timeout, host -> serviceTime));
if (waitTime == 0)
break;
waitCondition = ENET_SOCKET_WAIT_RECEIVE | ENET_SOCKET_WAIT_INTERRUPT;
if (enet_socket_wait (host -> socket, & waitCondition, waitTime) != 0)
if (enet_socket_wait (host -> socket, & waitCondition, ENET_TIME_DIFFERENCE (timeout, host -> serviceTime) / 10) != 0)
return -1;
}
while (waitCondition & ENET_SOCKET_WAIT_INTERRUPT);
+81 -421
View File
@@ -1,23 +1,14 @@
/**
/**
@file unix.c
@brief ENet Unix system specific functions
*/
#if !defined(_WIN32) || defined(NXDK)
// Required for IPV6_PKTINFO with Darwin headers
#ifndef __APPLE_USE_RFC_3542
#define __APPLE_USE_RFC_3542 1
#endif
// Required for in6_pktinfo with glibc headers
#ifndef _GNU_SOURCE
#define _GNU_SOURCE 1
#endif
#ifndef _WIN32
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/select.h>
#include <sys/time.h>
#include <arpa/inet.h>
#include <netinet/tcp.h>
#include <netdb.h>
#include <unistd.h>
@@ -29,11 +20,8 @@
#include "enet/enet.h"
#if defined(__APPLE__)
#if !defined(IPV6_RECVPKTINFO) || !defined(IPV6_PKTINFO)
#warning Missing IPv6 socket option definitions. Is __APPLE_USE_RFC_3542 defined?
#endif
#ifndef HAS_POLL
#define HAS_POLL 1
#ifdef HAS_POLL
#undef HAS_POLL
#endif
#ifndef HAS_FCNTL
#define HAS_FCNTL 1
@@ -57,9 +45,14 @@
#define HAS_GETNAMEINFO 1
#endif
#elif defined(__vita__)
// PS Vita: No support for ancillary data or advanced message control
#ifndef NO_MSGAPI
#define NO_MSGAPI 1
#ifdef HAS_POLL
#undef HAS_POLL
#endif
#ifdef HAS_FCNTL
#undef HAS_FCNTL
#endif
#ifdef HAS_IOCTL
#undef HAS_IOCTL
#endif
#ifndef HAS_INET_PTON
#define HAS_INET_PTON 1
@@ -67,6 +60,9 @@
#ifndef HAS_INET_NTOP
#define HAS_INET_NTOP 1
#endif
#ifdef HAS_MSGHDR_FLAGS
#undef HAS_MSGHDR_FLAGS
#endif
#ifndef HAS_SOCKLEN_T
#define HAS_SOCKLEN_T 1
#endif
@@ -76,104 +72,10 @@
#ifndef HAS_GETNAMEINFO
#define HAS_GETNAMEINFO 1
#endif
#elif defined(__WIIU__)
#ifndef HAS_POLL
#define HAS_POLL 1
#endif
#ifndef HAS_FCNTL
#define HAS_FCNTL 1
#endif
#ifndef HAS_IOCTL
#define HAS_IOCTL 1
#endif
#ifndef HAS_INET_PTON
#define HAS_INET_PTON 1
#endif
#ifndef HAS_INET_NTOP
#define HAS_INET_NTOP 1
#endif
#ifndef HAS_SOCKLEN_T
#define HAS_SOCKLEN_T 1
#endif
#ifndef HAS_GETADDRINFO
#define HAS_GETADDRINFO 1
#endif
#ifndef HAS_GETNAMEINFO
#define HAS_GETNAMEINFO 1
#endif
#ifndef NO_MSGAPI
#define NO_MSGAPI 1
#endif
#elif defined(NXDK)
#ifndef HAS_POLL
#define HAS_POLL 1
#endif
#ifndef HAS_FCNTL
#define HAS_FCNTL 1
#endif
#ifndef HAS_IOCTL
#define HAS_IOCTL 1
#endif
#ifndef HAS_INET_PTON
#define HAS_INET_PTON 1
#endif
#ifndef HAS_INET_NTOP
#define HAS_INET_NTOP 1
#endif
#ifndef HAS_SOCKLEN_T
#define HAS_SOCKLEN_T 1
#endif
#ifndef HAS_GETADDRINFO
#define HAS_GETADDRINFO 1
#endif
#ifndef HAS_GETNAMEINFO
#define HAS_GETNAMEINFO 1
#endif
#ifndef NO_MSGAPI
#define NO_MSGAPI 1
#endif
#elif defined(__3DS__)
#ifdef AF_INET6
#undef AF_INET6
#endif
#ifndef HAS_POLL
#define HAS_POLL 1
#endif
#ifndef HAS_FCNTL
#define HAS_FCNTL 1
#endif
#ifndef HAS_IOCTL
#define HAS_IOCTL 1
#endif
#ifndef HAS_INET_PTON
#define HAS_INET_PTON 1
#endif
#ifndef HAS_INET_NTOP
#define HAS_INET_NTOP 1
#endif
#ifndef HAS_SOCKLEN_T
#define HAS_SOCKLEN_T 1
#endif
#ifndef HAS_GETADDRINFO
#define HAS_GETADDRINFO 1
#endif
#ifndef HAS_GETNAMEINFO
#define HAS_GETNAMEINFO 1
#endif
#ifndef NO_MSGAPI
#define NO_MSGAPI 1
#endif
#elif defined(__HAIKU__)
#ifndef HAS_POLL
#define HAS_POLL 1
#endif
#else
#ifndef HAS_IOCTL
#define HAS_IOCTL 1
#endif
#ifndef HAS_POLL
#define HAS_POLL 1
#endif
#endif
#ifdef HAS_FCNTL
@@ -185,10 +87,10 @@
#endif
#ifdef HAS_POLL
#include <poll.h>
#include <sys/poll.h>
#endif
#if !defined(HAS_SOCKLEN_T) && !defined(__socklen_t_defined) && !defined(__HAIKU__)
#ifndef HAS_SOCKLEN_T
typedef int socklen_t;
#endif
@@ -217,9 +119,9 @@ enet_uint32
enet_host_random_seed (void)
{
struct timeval timeVal;
gettimeofday (& timeVal, NULL);
return (timeVal.tv_sec * 1000) ^ (timeVal.tv_usec / 1000);
}
@@ -239,31 +141,10 @@ enet_time_set (enet_uint32 newTimeBase)
struct timeval timeVal;
gettimeofday (& timeVal, NULL);
timeBase = timeVal.tv_sec * 1000 + timeVal.tv_usec / 1000 - newTimeBase;
}
#ifdef __APPLE__
void
enet_address_make_v4mapped (ENetAddress * address)
{
ENetAddress oldAddress = *address;
struct sockaddr_in *sin = ((struct sockaddr_in *)&oldAddress.address);
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&address->address;
memset(sin6, 0, sizeof(*sin6));
sin6->sin6_family = AF_INET6;
sin6->sin6_len = sizeof(*sin6);
sin6->sin6_port = sin->sin_port;
sin6->sin6_addr.s6_addr[10] = 0xFF;
sin6->sin6_addr.s6_addr[11] = 0xFF;
memcpy(&sin6->sin6_addr.s6_addr[12], &sin->sin_addr, 4);
address->addressLength = sizeof(*sin6);
}
#endif
int
enet_address_equal (ENetAddress * address1, ENetAddress * address2)
{
@@ -280,7 +161,6 @@ enet_address_equal (ENetAddress * address1, ENetAddress * address2)
return sin1 -> sin_port == sin2 -> sin_port &&
sin1 -> sin_addr.s_addr == sin2 -> sin_addr.s_addr;
}
#ifdef AF_INET6
case AF_INET6:
{
struct sockaddr_in6 *sin6a, *sin6b;
@@ -289,31 +169,6 @@ enet_address_equal (ENetAddress * address1, ENetAddress * address2)
return sin6a -> sin6_port == sin6b -> sin6_port &&
! memcmp (& sin6a -> sin6_addr, & sin6b -> sin6_addr, sizeof (sin6a -> sin6_addr));
}
#endif
default:
{
return 0;
}
}
}
int
enet_address_wildcard (const ENetAddress * address)
{
switch (address -> address.ss_family)
{
case AF_INET:
{
struct sockaddr_in *sin = (struct sockaddr_in *) & address -> address;
return sin -> sin_addr.s_addr == INADDR_ANY;
}
#ifdef AF_INET6
case AF_INET6:
{
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) & address -> address;
return ! memcmp (& sin6 -> sin6_addr, & in6addr_any, sizeof (in6addr_any));
}
#endif
default:
{
return 0;
@@ -330,14 +185,12 @@ enet_address_set_port (ENetAddress * address, enet_uint16 port)
sin -> sin_port = ENET_HOST_TO_NET_16 (port);
return 0;
}
#ifdef AF_INET6
else if (address -> address.ss_family == AF_INET6)
{
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) &address -> address;
sin6 -> sin6_port = ENET_HOST_TO_NET_16 (port);
return 0;
}
#endif
else
{
return -1;
@@ -371,9 +224,9 @@ enet_address_set_host (ENetAddress * address, const char * name)
{
memcpy (& address -> address, result -> ai_addr, result -> ai_addrlen);
address -> addressLength = result -> ai_addrlen;
freeaddrinfo (resultList);
return 0;
}
@@ -402,7 +255,7 @@ enet_socket_get_address (ENetSocket socket, ENetAddress * address)
return 0;
}
int
int
enet_socket_listen (ENetSocket socket, int backlog)
{
return listen (socket, backlog < 0 ? SOMAXCONN : backlog);
@@ -411,51 +264,7 @@ enet_socket_listen (ENetSocket socket, int backlog)
ENetSocket
enet_socket_create (int af, ENetSocketType type)
{
ENetSocket sock = socket (af, type == ENET_SOCKET_TYPE_DATAGRAM ? SOCK_DGRAM : SOCK_STREAM, 0);
if (sock < 0) {
return sock;
}
#ifdef IPV6_V6ONLY
if (af == AF_INET6) {
int off = 0;
// Some OSes don't support dual-stack sockets, so ignore failures
setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&off, sizeof(off));
}
#endif
#ifdef IP_PKTINFO
{
// We turn this on for all sockets because it may be required for IPv4
// traffic on dual-stack sockets on some OSes.
int on = 1;
setsockopt(sock, IPPROTO_IP, IP_PKTINFO, (char *)&on, sizeof(on));
}
#elif defined(IP_RECVDSTADDR)
// FreeBSD uses IP_RECVDSTADDR instead of IP_PKTINFO when struct in_pktinfo is not available
{
int on = 1;
setsockopt(sock, IPPROTO_IP, IP_RECVDSTADDR, (char *)&on, sizeof(on));
}
#endif
#ifdef IPV6_RECVPKTINFO
if (af == AF_INET6) {
int on = 1;
setsockopt(sock, IPPROTO_IPV6, IPV6_RECVPKTINFO, (char *)&on, sizeof(on));
}
#endif
#ifdef __WIIU__
{
// Enable usage of userbuffers on Wii U
int on = 1;
setsockopt(sock, SOL_SOCKET, SO_RUSRBUF, (char *)&on, sizeof(on));
}
#endif
return sock;
return socket (af, type == ENET_SOCKET_TYPE_DATAGRAM ? SOCK_DGRAM : SOCK_STREAM, 0);
}
int
@@ -466,7 +275,7 @@ enet_socket_set_option (ENetSocket socket, ENetSocketOption option, int value)
{
case ENET_SOCKOPT_NONBLOCK:
#ifdef HAS_FCNTL
result = fcntl (socket, F_SETFL, (value ? O_NONBLOCK : 0) | (fcntl (socket, F_GETFL, 0) & ~O_NONBLOCK));
result = fcntl (socket, F_SETFL, (value ? O_NONBLOCK : 0) | (fcntl (socket, F_GETFL) & ~O_NONBLOCK));
#else
#ifdef HAS_IOCTL
result = ioctl (socket, FIONBIO, & value);
@@ -488,7 +297,6 @@ enet_socket_set_option (ENetSocket socket, ENetSocketOption option, int value)
result = setsockopt (socket, SOL_SOCKET, SO_SNDBUF, (char *) & value, sizeof (int));
break;
#if !defined(__WIIU__) && !defined(__3DS__)
case ENET_SOCKOPT_RCVTIMEO:
{
struct timeval timeVal;
@@ -506,7 +314,6 @@ enet_socket_set_option (ENetSocket socket, ENetSocketOption option, int value)
result = setsockopt (socket, SOL_SOCKET, SO_SNDTIMEO, (char *) & timeVal, sizeof (struct timeval));
break;
}
#endif
case ENET_SOCKOPT_NODELAY:
result = setsockopt (socket, IPPROTO_TCP, TCP_NODELAY, (char *) & value, sizeof (int));
@@ -517,7 +324,7 @@ enet_socket_set_option (ENetSocket socket, ENetSocketOption option, int value)
// iOS/macOS
value = value ? NET_SERVICE_TYPE_VO : NET_SERVICE_TYPE_BE;
result = setsockopt (socket, SOL_SOCKET, SO_NET_SERVICE_TYPE, (char *) & value, sizeof (int));
#endif
#else
#ifdef IP_TOS
// UNIX - IPv4
value = value ? (46 << 2 | 0x01) : 0; // DSCP: Expedited Forwarding + ECT(1) (L4S)
@@ -533,10 +340,7 @@ enet_socket_set_option (ENetSocket socket, ENetSocketOption option, int value)
value = value ? 6 : 0; // Max priority without NET_CAP_ADMIN
result = setsockopt (socket, SOL_SOCKET, SO_PRIORITY, (char *) & value, sizeof (int));
#endif
break;
case ENET_SOCKOPT_TTL:
result = setsockopt (socket, IPPROTO_IP, IP_TTL, (char *) & value, sizeof (int));
#endif /* SO_NET_SERVICE_TYPE */
break;
default:
@@ -557,11 +361,6 @@ enet_socket_get_option (ENetSocket socket, ENetSocketOption option, int * value)
result = getsockopt (socket, SOL_SOCKET, SO_ERROR, value, & len);
break;
case ENET_SOCKOPT_TTL:
len = sizeof (int);
result = getsockopt (socket, IPPROTO_IP, IP_TTL, (char *) value, & len);
break;
default:
break;
}
@@ -588,10 +387,10 @@ enet_socket_accept (ENetSocket socket, ENetAddress * address)
if (address != NULL)
address -> addressLength = sizeof (address -> address);
result = accept (socket,
address != NULL ? (struct sockaddr *) & address -> address : NULL,
result = accept (socket,
address != NULL ? (struct sockaddr *) & address -> address : NULL,
address != NULL ? & address -> addressLength : NULL);
if (result == -1)
return ENET_SOCKET_NULL;
@@ -613,31 +412,30 @@ enet_socket_destroy (ENetSocket socket)
int
enet_socket_send (ENetSocket socket,
const ENetAddress * peerAddress,
const ENetAddress * localAddress,
const ENetAddress * address,
const ENetBuffer * buffers,
size_t bufferCount)
{
int sentLength;
#ifdef NO_MSGAPI
void* sendBuffer;
size_t sendLength;
if (bufferCount > 1)
{
size_t i;
sendLength = 0;
for (i = 0; i < bufferCount; i++)
{
sendLength += buffers[i].dataLength;
}
sendBuffer = malloc (sendLength);
if (sendBuffer == NULL)
return -1;
sendLength = 0;
for (i = 0; i < bufferCount; i++)
{
@@ -650,130 +448,30 @@ enet_socket_send (ENetSocket socket,
sendBuffer = buffers[0].data;
sendLength = buffers[0].dataLength;
}
sentLength = sendto (socket, sendBuffer, sendLength, MSG_NOSIGNAL,
(struct sockaddr *) & peerAddress -> address, peerAddress -> addressLength);
(struct sockaddr *) & address -> address, address -> addressLength);
if (bufferCount > 1)
free(sendBuffer);
#else
struct msghdr msgHdr;
char controlBufData[1024];
memset (& msgHdr, 0, sizeof (struct msghdr));
if (peerAddress != NULL)
if (address != NULL)
{
msgHdr.msg_name = (void*) & peerAddress -> address;
msgHdr.msg_namelen = peerAddress -> addressLength;
msgHdr.msg_name = (void*) & address -> address;
msgHdr.msg_namelen = address -> addressLength;
}
msgHdr.msg_iov = (struct iovec *) buffers;
msgHdr.msg_iovlen = bufferCount;
// We always send traffic from the same local address as we last received
// from this peer to ensure it correctly recognizes our responses as
// coming from the expected host.
if (localAddress != NULL) {
#ifdef IP_PKTINFO
if (localAddress->address.ss_family == AF_INET) {
struct in_pktinfo pktInfo;
pktInfo.ipi_spec_dst = ((struct sockaddr_in*)&localAddress->address)->sin_addr;
pktInfo.ipi_ifindex = 0; // Unspecified
msgHdr.msg_control = controlBufData;
msgHdr.msg_controllen = CMSG_SPACE(sizeof(pktInfo));
struct cmsghdr *chdr = CMSG_FIRSTHDR(&msgHdr);
chdr->cmsg_level = IPPROTO_IP;
chdr->cmsg_type = IP_PKTINFO;
chdr->cmsg_len = CMSG_LEN(sizeof(pktInfo));
memcpy(CMSG_DATA(chdr), &pktInfo, sizeof(pktInfo));
}
#elif defined(IP_SENDSRCADDR)
// FreeBSD uses IP_SENDSRCADDR with struct in_addr instead of IP_PKTINFO
if (localAddress->address.ss_family == AF_INET) {
struct in_addr srcAddr = ((struct sockaddr_in*)&localAddress->address)->sin_addr;
msgHdr.msg_control = controlBufData;
msgHdr.msg_controllen = CMSG_SPACE(sizeof(srcAddr));
struct cmsghdr *chdr = CMSG_FIRSTHDR(&msgHdr);
chdr->cmsg_level = IPPROTO_IP;
chdr->cmsg_type = IP_SENDSRCADDR;
chdr->cmsg_len = CMSG_LEN(sizeof(srcAddr));
memcpy(CMSG_DATA(chdr), &srcAddr, sizeof(srcAddr));
}
#endif
#ifdef IPV6_PKTINFO
if (localAddress->address.ss_family == AF_INET6) {
struct in6_pktinfo pktInfo;
pktInfo.ipi6_addr = ((struct sockaddr_in6*)&localAddress->address)->sin6_addr;
pktInfo.ipi6_ifindex = 0; // Unspecified
msgHdr.msg_control = controlBufData;
msgHdr.msg_controllen = CMSG_SPACE(sizeof(pktInfo));
struct cmsghdr *chdr = CMSG_FIRSTHDR(&msgHdr);
chdr->cmsg_level = IPPROTO_IPV6;
chdr->cmsg_type = IPV6_PKTINFO;
chdr->cmsg_len = CMSG_LEN(sizeof(pktInfo));
memcpy(CMSG_DATA(chdr), &pktInfo, sizeof(pktInfo));
}
#endif
}
sentLength = sendmsg (socket, & msgHdr, MSG_NOSIGNAL);
#endif
if (sentLength == -1)
{
switch (errno)
{
case EWOULDBLOCK:
return 0;
// These errors are treated as possible transient
// conditions that could be caused by a network
// interruption. We'll ignore them and allow the
// socket timeout to kill us if the connection
// is permanently interrupted.
case EADDRNOTAVAIL:
case ENETDOWN:
case ENETUNREACH:
#if !defined(EHOSTDOWN) || (EHOSTDOWN != EHOSTUNREACH)
case EHOSTDOWN:
#endif
case EHOSTUNREACH:
return 0;
default:
return -1;
}
}
return sentLength;
}
int
enet_socket_receive (ENetSocket socket,
ENetAddress * peerAddress,
ENetAddress * localAddress,
ENetBuffer * buffers,
size_t bufferCount)
{
int recvLength;
#ifdef NO_MSGAPI
// This will ONLY work with a single buffer!
peerAddress -> addressLength = sizeof (peerAddress -> address);
recvLength = recvfrom (socket, buffers[0].data, buffers[0].dataLength, MSG_NOSIGNAL,
(struct sockaddr *) & peerAddress -> address, & peerAddress -> addressLength);
if (recvLength == -1)
{
if (errno == EWOULDBLOCK)
return 0;
@@ -781,23 +479,46 @@ enet_socket_receive (ENetSocket socket,
return -1;
}
return sentLength;
}
int
enet_socket_receive (ENetSocket socket,
ENetAddress * address,
ENetBuffer * buffers,
size_t bufferCount)
{
int recvLength;
#ifdef NO_MSGAPI
// This will ONLY work with a single buffer!
address -> addressLength = sizeof (address -> address);
recvLength = recvfrom (socket, buffers[0].data, buffers[0].dataLength, MSG_NOSIGNAL,
(struct sockaddr *) & address -> address, & address -> addressLength);
if (recvLength == -1)
{
if (errno == EWOULDBLOCK)
return 0;
return -1;
}
return recvLength;
#else
struct msghdr msgHdr;
char controlBufData[1024];
memset (& msgHdr, 0, sizeof (struct msghdr));
if (peerAddress != NULL)
if (address != NULL)
{
msgHdr.msg_name = & peerAddress -> address;
msgHdr.msg_namelen = sizeof (peerAddress -> address);
msgHdr.msg_name = & address -> address;
msgHdr.msg_namelen = sizeof (address -> address);
}
msgHdr.msg_iov = (struct iovec *) buffers;
msgHdr.msg_iovlen = bufferCount;
msgHdr.msg_control = controlBufData;
msgHdr.msg_controllen = sizeof(controlBufData);
recvLength = recvmsg (socket, & msgHdr, MSG_NOSIGNAL);
@@ -808,66 +529,15 @@ enet_socket_receive (ENetSocket socket,
return -1;
}
if (address != NULL)
address -> addressLength = msgHdr.msg_namelen;
#ifdef HAS_MSGHDR_FLAGS
if (msgHdr.msg_flags & MSG_TRUNC)
return -2;
return -1;
#endif
// Retrieve the local address that this traffic was received on
// to ensure we respond from the correct address/interface.
if (localAddress != NULL) {
for (struct cmsghdr *chdr = CMSG_FIRSTHDR(&msgHdr); chdr != NULL; chdr = CMSG_NXTHDR(&msgHdr, chdr)) {
#ifdef IP_PKTINFO
if (chdr->cmsg_level == IPPROTO_IP && chdr->cmsg_type == IP_PKTINFO) {
struct sockaddr_in *localAddr = (struct sockaddr_in*)&localAddress->address;
localAddr->sin_family = AF_INET;
localAddr->sin_addr = ((struct in_pktinfo*)CMSG_DATA(chdr))->ipi_addr;
localAddress->addressLength = sizeof(*localAddr);
break;
}
#elif defined(IP_RECVDSTADDR)
// FreeBSD uses IP_RECVDSTADDR with struct in_addr instead of IP_PKTINFO
if (chdr->cmsg_level == IPPROTO_IP && chdr->cmsg_type == IP_RECVDSTADDR) {
struct sockaddr_in *localAddr = (struct sockaddr_in*)&localAddress->address;
localAddr->sin_family = AF_INET;
localAddr->sin_addr = *((struct in_addr*)CMSG_DATA(chdr));
localAddress->addressLength = sizeof(*localAddr);
break;
}
#endif
#ifdef IPV6_PKTINFO
if (chdr->cmsg_level == IPPROTO_IPV6 && chdr->cmsg_type == IPV6_PKTINFO) {
struct sockaddr_in6 *localAddr = (struct sockaddr_in6*)&localAddress->address;
localAddr->sin6_family = AF_INET6;
localAddr->sin6_addr = ((struct in6_pktinfo*)CMSG_DATA(chdr))->ipi6_addr;
localAddress->addressLength = sizeof(*localAddr);
break;
}
#endif
}
}
if (peerAddress != NULL) {
peerAddress -> addressLength = msgHdr.msg_namelen;
#ifdef __APPLE__
// HACK: Apple platforms return AF_INET addresses in msg_name from recvmsg() on dual-stack sockets
// instead of AF_INET6 addresses then rejects those same addresses when they are passed to sendmsg().
// Strangely, this only happens when the socket is bound, and IPV6_PKTINFO properly returns v4-mapped
// addresses in the same call. This is probably a kernel bug, so we fix it up here.
if (peerAddress -> address.ss_family == AF_INET && localAddress -> address.ss_family == AF_INET6) {
enet_address_make_v4mapped(peerAddress);
}
#endif
}
return recvLength;
#endif
}
@@ -889,7 +559,7 @@ enet_socket_wait (ENetSocket socket, enet_uint32 * condition, enet_uint32 timeou
#ifdef HAS_POLL
struct pollfd pollSocket;
int pollCount;
pollSocket.fd = socket;
pollSocket.events = 0;
@@ -899,18 +569,7 @@ enet_socket_wait (ENetSocket socket, enet_uint32 * condition, enet_uint32 timeou
if (* condition & ENET_SOCKET_WAIT_RECEIVE)
pollSocket.events |= POLLIN;
#if defined(__3DS__)
uint64_t poll_start = osGetTime();
for (uint64_t i = poll_start; (i - poll_start) < timeout; i = osGetTime()) {
pollCount = poll(& pollSocket, 1, 0); // need to do this on 3ds since poll will block even if socket is ready before
if (pollCount) {
break;
}
svcSleepThread(1000);
}
#else
pollCount = poll (& pollSocket, 1, timeout);
#endif
if (pollCount < 0)
{
@@ -931,7 +590,7 @@ enet_socket_wait (ENetSocket socket, enet_uint32 * condition, enet_uint32 timeou
if (pollSocket.revents & POLLOUT)
* condition |= ENET_SOCKET_WAIT_SEND;
if (pollSocket.revents & POLLIN)
* condition |= ENET_SOCKET_WAIT_RECEIVE;
@@ -963,7 +622,7 @@ enet_socket_wait (ENetSocket socket, enet_uint32 * condition, enet_uint32 timeou
return 0;
}
return -1;
}
@@ -983,3 +642,4 @@ enet_socket_wait (ENetSocket socket, enet_uint32 * condition, enet_uint32 timeou
}
#endif
+60 -338
View File
@@ -1,57 +1,26 @@
/**
/**
@file win32.c
@brief ENet Win32 system specific functions
*/
#if defined(_WIN32) && !defined(NXDK)
#ifdef _WIN32
#define ENET_BUILDING_LIB 1
#include "enet/enet.h"
#include <windows.h>
#include <mswsock.h>
#ifndef HAS_QOS_FLOWID
typedef UINT32 QOS_FLOWID;
#endif
#ifndef HAS_PQOS_FLOWID
typedef UINT32 *PQOS_FLOWID;
#endif
#include <mmsystem.h>
#include <qos2.h>
#ifndef QOS_NON_ADAPTIVE_FLOW
#define QOS_NON_ADAPTIVE_FLOW 0x00000002
#endif
static enet_uint32 timeBase = 0;
#if !(defined(WINAPI_FAMILY) && WINAPI_FAMILY == WINAPI_FAMILY_APP)
# define HAS_QWAVE
# include <versionhelpers.h>
#else
# define IsWindows10OrGreater() TRUE
#endif
#ifdef HAS_QWAVE
static HANDLE qosHandle = INVALID_HANDLE_VALUE;
static QOS_FLOWID qosFlowId;
static BOOL qosAddedFlow;
static HMODULE QwaveLibraryHandle;
BOOL (WINAPI *pfnQOSCreateHandle)(PQOS_VERSION Version, PHANDLE QOSHandle);
BOOL (WINAPI *pfnQOSCloseHandle)(HANDLE QOSHandle);
BOOL (WINAPI *pfnQOSAddSocketToFlow)(HANDLE QOSHandle, SOCKET Socket, PSOCKADDR DestAddr, QOS_TRAFFIC_TYPE TrafficType, DWORD Flags, PQOS_FLOWID FlowId);
#endif
static BOOL enableEcn;
static LPFN_WSARECVMSG pfnWSARecvMsg;
int
enet_initialize (void)
{
WORD versionRequested = MAKEWORD (2, 0);
WSADATA wsaData;
if (WSAStartup (versionRequested, & wsaData))
return -1;
@@ -59,72 +28,48 @@ enet_initialize (void)
HIBYTE (wsaData.wVersion) != 0)
{
WSACleanup ();
return -1;
}
#ifdef HAS_QWAVE
QwaveLibraryHandle = LoadLibraryA("qwave.dll");
if (QwaveLibraryHandle != NULL) {
pfnQOSCreateHandle = (void*)GetProcAddress(QwaveLibraryHandle, "QOSCreateHandle");
pfnQOSCloseHandle = (void*)GetProcAddress(QwaveLibraryHandle, "QOSCloseHandle");
pfnQOSAddSocketToFlow = (void*)GetProcAddress(QwaveLibraryHandle, "QOSAddSocketToFlow");
timeBeginPeriod (1);
if (pfnQOSCreateHandle == NULL || pfnQOSCloseHandle == NULL || pfnQOSAddSocketToFlow == NULL) {
pfnQOSCreateHandle = NULL;
pfnQOSCloseHandle = NULL;
pfnQOSAddSocketToFlow = NULL;
FreeLibrary(QwaveLibraryHandle);
QwaveLibraryHandle = NULL;
}
}
#endif
return 0;
}
void
enet_deinitialize (void)
{
#ifdef HAS_QWAVE
qosAddedFlow = FALSE;
qosFlowId = 0;
enableEcn = FALSE;
if (qosHandle != INVALID_HANDLE_VALUE)
{
pfnQOSCloseHandle(qosHandle);
QOSCloseHandle(qosHandle);
qosHandle = INVALID_HANDLE_VALUE;
}
if (QwaveLibraryHandle != NULL) {
pfnQOSCreateHandle = NULL;
pfnQOSCloseHandle = NULL;
pfnQOSAddSocketToFlow = NULL;
timeEndPeriod (1);
FreeLibrary(QwaveLibraryHandle);
QwaveLibraryHandle = NULL;
}
#endif
WSACleanup ();
}
enet_uint32
enet_host_random_seed (void)
{
return (enet_uint32) GetTickCount ();
return (enet_uint32) timeGetTime ();
}
enet_uint32
enet_time_get (void)
{
return (enet_uint32) GetTickCount () - timeBase;
return (enet_uint32) timeGetTime () - timeBase;
}
void
enet_time_set (enet_uint32 newTimeBase)
{
timeBase = (enet_uint32) GetTickCount () - newTimeBase;
timeBase = (enet_uint32) timeGetTime () - newTimeBase;
}
int
@@ -190,28 +135,6 @@ enet_address_equal (ENetAddress * address1, ENetAddress * address2)
}
}
int
enet_address_wildcard (const ENetAddress * address)
{
switch (address -> address.ss_family)
{
case AF_INET:
{
struct sockaddr_in *sin = (struct sockaddr_in *) & address -> address;
return sin -> sin_addr.S_un.S_addr == INADDR_ANY;
}
case AF_INET6:
{
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) & address -> address;
return ! memcmp (& sin6 -> sin6_addr, & in6addr_any, sizeof (in6addr_any));
}
default:
{
return 0;
}
}
}
int
enet_address_set_host (ENetAddress * address, const char * name)
{
@@ -228,9 +151,9 @@ enet_address_set_host (ENetAddress * address, const char * name)
{
memcpy (& address -> address, result -> ai_addr, result -> ai_addrlen);
address -> addressLength = result -> ai_addrlen;
freeaddrinfo (resultList);
return 0;
}
@@ -268,46 +191,7 @@ enet_socket_listen (ENetSocket socket, int backlog)
ENetSocket
enet_socket_create (int af, ENetSocketType type)
{
SOCKET sock = socket (af, type == ENET_SOCKET_TYPE_DATAGRAM ? SOCK_DGRAM : SOCK_STREAM, 0);
if (sock == INVALID_SOCKET)
return INVALID_SOCKET;
DWORD bytesReturned;
GUID wsaRecvMsgGuid = WSAID_WSARECVMSG;
if (WSAIoctl(sock, SIO_GET_EXTENSION_FUNCTION_POINTER, &wsaRecvMsgGuid, sizeof(wsaRecvMsgGuid),
&pfnWSARecvMsg, sizeof(pfnWSARecvMsg), &bytesReturned, NULL, NULL) == SOCKET_ERROR) {
closesocket(sock);
return INVALID_SOCKET;
}
BOOL val;
// Enable dual-stack operation for IPv6 sockets
if (af == AF_INET6) {
val = FALSE;
if (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&val, sizeof(val)) == SOCKET_ERROR) {
closesocket(sock);
return INVALID_SOCKET;
}
}
// Enable returning local address info for IPv4 and dual-stack sockets
val = TRUE;
if (setsockopt(sock, IPPROTO_IP, IP_PKTINFO, (char*)&val, sizeof(val)) == SOCKET_ERROR) {
closesocket(sock);
return INVALID_SOCKET;
}
// Enable returning local address info for IPv6 and dual-stack sockets
if (af == AF_INET6) {
val = TRUE;
if (setsockopt(sock, IPPROTO_IPV6, IPV6_PKTINFO, (char*)&val, sizeof(val)) == SOCKET_ERROR) {
closesocket(sock);
return INVALID_SOCKET;
}
}
return sock;
return socket (af, type == ENET_SOCKET_TYPE_DATAGRAM ? SOCK_DGRAM : SOCK_STREAM, 0);
}
int
@@ -349,38 +233,30 @@ enet_socket_set_option (ENetSocket socket, ENetSocketOption option, int value)
case ENET_SOCKOPT_QOS:
{
// Enable ECN marking on Windows 10 if QOS is enabled
enableEcn = value != 0 && IsWindows10OrGreater();
#ifdef HAS_QWAVE
if (value)
{
QOS_VERSION qosVersion;
qosVersion.MajorVersion = 1;
qosVersion.MinorVersion = 0;
if (pfnQOSCreateHandle == NULL || !pfnQOSCreateHandle(&qosVersion, &qosHandle))
if (!QOSCreateHandle(&qosVersion, &qosHandle))
{
qosHandle = INVALID_HANDLE_VALUE;
}
}
else if (qosHandle != INVALID_HANDLE_VALUE)
{
pfnQOSCloseHandle(qosHandle);
QOSCloseHandle(qosHandle);
qosHandle = INVALID_HANDLE_VALUE;
}
qosAddedFlow = FALSE;
qosFlowId = 0;
#endif
result = 0;
break;
}
case ENET_SOCKOPT_TTL:
result = setsockopt (socket, IPPROTO_IP, IP_TTL, (char *) & value, sizeof (int));
break;
default:
break;
}
@@ -398,11 +274,6 @@ enet_socket_get_option (ENetSocket socket, ENetSocketOption option, int * value)
result = getsockopt (socket, SOL_SOCKET, SO_ERROR, (char *) value, & len);
break;
case ENET_SOCKOPT_TTL:
len = sizeof(int);
result = getsockopt (socket, IPPROTO_IP, IP_TTL, (char *) value, & len);
break;
default:
break;
}
@@ -429,10 +300,10 @@ enet_socket_accept (ENetSocket socket, ENetAddress * address)
if (address != NULL)
address -> addressLength = sizeof (address -> address);
result = accept (socket,
address != NULL ? (struct sockaddr *) & address -> address : NULL,
result = accept (socket,
address != NULL ? (struct sockaddr *) & address -> address : NULL,
address != NULL ? & address -> addressLength : NULL);
if (result == -1)
return ENET_SOCKET_NULL;
@@ -454,159 +325,40 @@ enet_socket_destroy (ENetSocket socket)
int
enet_socket_send (ENetSocket socket,
const ENetAddress * peerAddress,
const ENetAddress * localAddress,
const ENetAddress * address,
const ENetBuffer * buffers,
size_t bufferCount)
{
DWORD sentLength;
WSAMSG msg = { 0 };
char controlBufData[1024];
PWSACMSGHDR chdr = NULL;
#ifdef HAS_QWAVE
if (!qosAddedFlow && qosHandle != INVALID_HANDLE_VALUE)
{
BOOL isV4MappedV6Addr =
peerAddress->address.ss_family == AF_INET6 &&
IN6_IS_ADDR_V4MAPPED(&((PSOCKADDR_IN6)&peerAddress->address)->sin6_addr);
// qWAVE doesn't properly support IPv4-mapped IPv6 addresses, nor does it
// correctly support IPv4 addresses on a dual-stack socket (despite MSDN's
// claims to the contrary). To get proper QoS tagging when hosting in dual
// stack mode, we will temporarily connect() the socket to allow qWAVE to
// successfully initialize a flow, then disconnect it again so WSASendMsg()
// works later on.
if (isV4MappedV6Addr) {
connect(socket, (PSOCKADDR)&peerAddress->address, peerAddress->addressLength);
}
qosFlowId = 0; // Must be initialized to 0
pfnQOSAddSocketToFlow(qosHandle,
socket,
isV4MappedV6Addr ? NULL : (struct sockaddr *)&peerAddress->address,
QOSTrafficTypeControl,
QOS_NON_ADAPTIVE_FLOW,
&qosFlowId);
if (isV4MappedV6Addr) {
SOCKADDR_IN6 empty = { 0 };
empty.sin6_family = AF_INET6;
connect(socket, (PSOCKADDR)&empty, sizeof(empty));
}
QOSAddSocketToFlow(qosHandle,
socket,
(struct sockaddr *)&address->address,
QOSTrafficTypeControl,
QOS_NON_ADAPTIVE_FLOW,
&qosFlowId);
// Even if we failed, don't try again
qosAddedFlow = TRUE;
}
#endif
msg.name = (struct sockaddr *) & peerAddress -> address;
msg.namelen = peerAddress -> addressLength;
msg.lpBuffers = (LPWSABUF) buffers;
msg.dwBufferCount = (DWORD) bufferCount;
// We always send traffic from the same local address as we last received
// from this peer to ensure it correctly recognizes our responses as
// coming from the expected host.
if (localAddress != NULL) {
if (localAddress->address.ss_family == AF_INET) {
IN_PKTINFO pktInfo;
pktInfo.ipi_addr = ((PSOCKADDR_IN)&localAddress->address)->sin_addr;
pktInfo.ipi_ifindex = 0; // Unspecified
msg.Control.buf = controlBufData;
msg.Control.len += WSA_CMSG_SPACE(sizeof(pktInfo));
if (chdr == NULL) {
chdr = WSA_CMSG_FIRSTHDR(&msg);
}
else {
chdr = WSA_CMSG_NXTHDR(&msg, chdr);
}
chdr->cmsg_level = IPPROTO_IP;
chdr->cmsg_type = IP_PKTINFO;
chdr->cmsg_len = WSA_CMSG_LEN(sizeof(pktInfo));
memcpy(WSA_CMSG_DATA(chdr), &pktInfo, sizeof(pktInfo));
}
else if (localAddress->address.ss_family == AF_INET6) {
IN6_PKTINFO pktInfo;
pktInfo.ipi6_addr = ((PSOCKADDR_IN6)&localAddress->address)->sin6_addr;
pktInfo.ipi6_ifindex = 0; // Unspecified
msg.Control.buf = controlBufData;
msg.Control.len += WSA_CMSG_SPACE(sizeof(pktInfo));
if (chdr == NULL) {
chdr = WSA_CMSG_FIRSTHDR(&msg);
}
else {
chdr = WSA_CMSG_NXTHDR(&msg, chdr);
}
chdr->cmsg_level = IPPROTO_IPV6;
chdr->cmsg_type = IPV6_PKTINFO;
chdr->cmsg_len = WSA_CMSG_LEN(sizeof(pktInfo));
memcpy(WSA_CMSG_DATA(chdr), &pktInfo, sizeof(pktInfo));
}
}
// This is a bit of a hack because it's not really per-socket or
// per-destination, but it is fine for our current usage of ENet
// in Moonlight and Sunshine where only a single socket is used.
if (enableEcn) {
BOOL isV4MappedV6Addr =
peerAddress->address.ss_family == AF_INET6 &&
IN6_IS_ADDR_V4MAPPED(&((PSOCKADDR_IN6)&peerAddress->address)->sin6_addr);
msg.Control.buf = controlBufData;
msg.Control.len += WSA_CMSG_SPACE(sizeof(INT));
if (chdr == NULL) {
chdr = WSA_CMSG_FIRSTHDR(&msg);
}
else {
chdr = WSA_CMSG_NXTHDR(&msg, chdr);
}
if (peerAddress->address.ss_family == AF_INET || isV4MappedV6Addr) {
chdr->cmsg_level = IPPROTO_IP;
chdr->cmsg_type = IP_ECN;
}
else {
chdr->cmsg_level = IPPROTO_IPV6;
chdr->cmsg_type = IPV6_ECN;
}
chdr->cmsg_len = WSA_CMSG_LEN(sizeof(INT));
*(PINT)WSA_CMSG_DATA(chdr) = 0x01; // ECT(1) (L4S)
}
if (WSASendMsg (socket,
& msg,
0,
& sentLength,
NULL,
NULL) == SOCKET_ERROR)
if (WSASendTo (socket,
(LPWSABUF) buffers,
(DWORD) bufferCount,
& sentLength,
0,
address != NULL ? (struct sockaddr *) & address -> address : NULL,
address != NULL ? address -> addressLength : 0,
NULL,
NULL) == SOCKET_ERROR)
{
switch (WSAGetLastError ())
{
case WSAEWOULDBLOCK:
return 0;
if (WSAGetLastError () == WSAEWOULDBLOCK)
return 0;
// These errors are treated as possible transient
// conditions that could be caused by a network
// interruption. We'll ignore them and allow the
// socket timeout to kill us if the connection
// is permanently interrupted.
case WSAEADDRNOTAVAIL:
case WSAENETDOWN:
case WSAENETUNREACH:
case WSAEHOSTDOWN:
case WSAEHOSTUNREACH:
return 0;
default:
return -1;
}
return -1;
}
return (int) sentLength;
@@ -614,69 +366,39 @@ enet_socket_send (ENetSocket socket,
int
enet_socket_receive (ENetSocket socket,
ENetAddress * peerAddress,
ENetAddress * localAddress,
ENetAddress * address,
ENetBuffer * buffers,
size_t bufferCount)
{
DWORD recvLength;
WSAMSG msg = { 0 };
char controlBufData[1024];
DWORD flags = 0,
recvLength;
if (address != NULL)
address -> addressLength = sizeof (address -> address);
msg.name = peerAddress != NULL ? (struct sockaddr *) & peerAddress -> address : NULL;
msg.namelen = peerAddress != NULL ? sizeof (peerAddress -> address) : 0;
msg.lpBuffers = (LPWSABUF) buffers;
msg.dwBufferCount = (DWORD) bufferCount;
msg.Control.buf = controlBufData;
msg.Control.len = sizeof(controlBufData);
if (pfnWSARecvMsg (socket,
& msg,
& recvLength,
NULL,
NULL) == SOCKET_ERROR)
if (WSARecvFrom (socket,
(LPWSABUF) buffers,
(DWORD) bufferCount,
& recvLength,
& flags,
address != NULL ? (struct sockaddr *) & address -> address : NULL,
address != NULL ? & address -> addressLength : NULL,
NULL,
NULL) == SOCKET_ERROR)
{
switch (WSAGetLastError ())
{
case WSAEWOULDBLOCK:
case WSAECONNRESET:
return 0;
case WSAEMSGSIZE:
return -2;
}
return -1;
}
if (msg.dwFlags & MSG_PARTIAL)
return -2;
if (flags & MSG_PARTIAL)
return -1;
// Retrieve the local address that this traffic was received on
// to ensure we respond from the correct address/interface.
if (localAddress != NULL) {
for (PWSACMSGHDR chdr = WSA_CMSG_FIRSTHDR(&msg); chdr != NULL; chdr = WSA_CMSG_NXTHDR(&msg, chdr)) {
if (chdr->cmsg_level == IPPROTO_IP && chdr->cmsg_type == IP_PKTINFO) {
PSOCKADDR_IN localAddr = (PSOCKADDR_IN)&localAddress->address;
localAddr->sin_family = AF_INET;
localAddr->sin_addr = ((IN_PKTINFO*)WSA_CMSG_DATA(chdr))->ipi_addr;
localAddress->addressLength = sizeof(*localAddr);
break;
}
else if (chdr->cmsg_level == IPPROTO_IPV6 && chdr->cmsg_type == IPV6_PKTINFO) {
PSOCKADDR_IN6 localAddr = (PSOCKADDR_IN6)&localAddress->address;
localAddr->sin6_family = AF_INET6;
localAddr->sin6_addr = ((IN6_PKTINFO*)WSA_CMSG_DATA(chdr))->ipi6_addr;
localAddress->addressLength = sizeof(*localAddr);
break;
}
}
}
peerAddress->addressLength = msg.namelen;
return (int) recvLength;
}
@@ -697,10 +419,10 @@ enet_socket_wait (ENetSocket socket, enet_uint32 * condition, enet_uint32 timeou
fd_set readSet, writeSet;
struct timeval timeVal;
int selectCount;
timeVal.tv_sec = timeout / 1000;
timeVal.tv_usec = (timeout % 1000) * 1000;
FD_ZERO (& readSet);
FD_ZERO (& writeSet);
@@ -722,12 +444,12 @@ enet_socket_wait (ENetSocket socket, enet_uint32 * condition, enet_uint32 timeou
if (FD_ISSET (socket, & writeSet))
* condition |= ENET_SOCKET_WAIT_SEND;
if (FD_ISSET (socket, & readSet))
* condition |= ENET_SOCKET_WAIT_RECEIVE;
return 0;
}
}
#endif