35 Commits

Author SHA1 Message Date
Cameron Gutman e790647a57 Correctly support hosts with multiple possible source addresses 2023-02-12 15:35:34 -06:00
Mariotaku 4cde9cc3dc Fixed build with MinGW (#8)
* Fixed build with MinGW

* improved typedef check for MinGW

* added include dir to enet lib
2021-09-15 23:02:02 -05:00
Cameron Gutman 8d69c5abe4 Avoid statically linking to qwave.dll
It's not present on Server SKUs by default.
2021-06-12 12:14:46 -05:00
Cameron Gutman ad5bf95397 fix excessive retransmissions when average RTT variance is 0 2021-05-16 15:35:02 -05:00
Cameron Gutman ab9d471cec fix SRTT calculations when RTT < 8 ms and SRTT >= 8 ms 2021-05-16 14:15:38 -05:00
Cameron Gutman c20ca391e2 fix RTO limit being exceeded 2021-05-14 18:46:49 -05:00
Cameron Gutman 70ce1c3e0b Merge remote-tracking branch 'upstream/master' into moonlight 2021-04-29 09:40:57 -05:00
Cameron Gutman d8976c4fcc Merge pull request #6 from GaryOderNichts/wiiu
Wii U changes
2021-04-17 23:27:01 -05:00
GaryOderNichts bdfdb8b85d Wii U changes 2021-04-12 13:56:21 +02:00
Cameron Gutman d9e561938f Merge pull request #5 from lsalzman/master
Rebase to lsalzman/enet: update to 1.3.17
2021-01-09 18:38:33 -06:00
Cameron Gutman 2a788029bf Enable poll() for Linux/BSD 2020-07-27 00:01:51 -07:00
Cameron Gutman 757933e7bc Enable poll() on macOS and iOS 2020-07-26 20:06:38 -07:00
Cameron Gutman 8d794daa7c Merge branch 'master' of https://github.com/lsalzman/enet into moonlight
# Conflicts:
#	unix.c
#	win32.c
2020-06-12 21:46:42 -07:00
Cameron Gutman 9bf55a3433 Disable QoS tagging if 2 connect packets in a row are dropped 2020-06-12 21:16:46 -07:00
Cameron Gutman 5c96da29c2 Enable QoS prioritization on Windows 2020-04-09 17:42:12 -07:00
Cameron Gutman d988023971 Use EF instead of CS7 for DSCP
Some security guidelines recommend dropping CS7 tagged packets at the edge,
since CS7 is reserved for network control. EF seems to be the standard for
telephony applications and is fairly well preserved across the Internet per
https://www.sciencedirect.com/science/article/pii/S0166531619300203
2020-04-03 16:58:18 -07:00
Cameron Gutman 637cd52e96 Enable QoS prioritization on Linux 2020-03-29 15:44:14 -07:00
Cameron Gutman 512b3f26f9 Enable QOS prioritization on macOS 2020-03-29 15:21:26 -07:00
Cameron Gutman 5503534362 Fix Linux build 2019-10-12 19:41:41 -07:00
Sunguk Lee 93b080b053 vita: No more need vita specific codesets (#4)
* vita: No more need to define sockaddr_storage

* vita: Remove everything and combine unix codeset

* unix: Remove HACK for the specialized code of the vita nonblock IO
2019-10-12 15:10:59 -07:00
Cameron Gutman cf38f85e08 Be more lenient with the expected peer address for multi-homed hosts 2019-09-14 14:05:05 -07:00
Cameron Gutman e770a52bca Merge pull request #3 from d3m3vilurr/fix-vita-error-code
vita: No more use self defined net error code
2019-02-17 09:49:11 -08:00
Sunguk Lee 42891f6919 vita: No more use self defined net error code 2018-07-28 21:50:59 +09:00
Antonio Aloisio eb38c3c737 Fixed build with latest VitaSDK (#2) 2018-07-25 21:27:12 -07:00
Sunguk Lee e33ca1dc47 Add vita environment (#1)
* vita: Initial port

* vita: add debug logging and reduce max number of IOV (caused errors)

* vita: now using newlib's socket apis

* vita: Refactoring for cgutman/enet

* Fix review things

https://github.com/cgutman/enet/pull/1#pullrequestreview-2436331
2016-10-02 00:56:59 -07:00
Cameron Gutman 7546b505c1 Lower ENet's MTU to 900 because some ISPs will drop the RTSP DESCRIBE response packets with the default MTU 2016-05-21 18:01:31 -05:00
Cameron Gutman 2bc07bb50d Add enet_address_set_address() function to allow ENetAddress to be populated from sockaddr directly 2016-04-02 14:04:31 -04:00
Cameron Gutman a602abf244 Switch to gettimeofday() for seeding on UNIX 2016-03-31 11:22:06 -04:00
Cameron Gutman 167f41aa2b Fix build with NO_MSGAPI undefined 2016-03-27 22:47:50 -04:00
Cameron Gutman b2ee3b7b48 Add support for building with PNaCl's newlibc 2016-03-11 00:27:48 -08:00
Cameron Gutman 8b24595dbd Require an address family to be specified when creating a host 2016-03-07 14:26:13 -08:00
Cameron Gutman b3e34fa1db Fix some IPv6 compatibility issues 2016-03-06 23:22:59 -08:00
Cameron Gutman 4f7ef11c23 Fix some compilation warnings 2016-03-06 15:33:32 -08:00
Cameron Gutman a39d3bb49c Wake up every once in a while to see if any retransmissions or pings need to be sent 2016-03-06 14:56:08 -08:00
Cameron Gutman ae9002fe19 Protocol agnostic socket address to fix IPv6 and remove broadcast support 2016-03-06 14:47:01 -08:00
8 changed files with 769 additions and 459 deletions
+15
View File
@@ -7,6 +7,7 @@ include(CheckFunctionExists)
include(CheckStructHasMember)
include(CheckTypeSize)
check_function_exists("fcntl" HAS_FCNTL)
check_function_exists("ioctl" HAS_IOCTL)
check_function_exists("poll" HAS_POLL)
check_function_exists("getaddrinfo" HAS_GETADDRINFO)
check_function_exists("getnameinfo" HAS_GETNAMEINFO)
@@ -18,6 +19,10 @@ 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 "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()
@@ -27,6 +32,9 @@ endif()
if(HAS_FCNTL)
add_definitions(-DHAS_FCNTL=1)
endif()
if(HAS_IOCTL)
add_definitions(-DHAS_IOCTL=1)
endif()
if(HAS_POLL)
add_definitions(-DHAS_POLL=1)
endif()
@@ -54,6 +62,12 @@ 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)
@@ -88,6 +102,7 @@ add_library(enet STATIC
${INCLUDE_FILES}
${SOURCE_FILES}
)
target_include_directories(enet SYSTEM PUBLIC include)
if (MINGW)
target_link_libraries(enet winmm ws2_32)
+6 -29
View File
@@ -12,6 +12,7 @@
/** Creates a host for communicating to peers.
@param addressFamily the address family of the socket that should be created (ex: PF_INET/PF_INET6)
@param address the address at which other peers may connect to this host. If NULL, then no peers may connect to the host.
@param peerCount the maximum number of peers that should be allocated for the host.
@param channelLimit the maximum number of channels allowed; if 0, then this is equivalent to ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT
@@ -26,7 +27,7 @@
at any given time.
*/
ENetHost *
enet_host_create (const ENetAddress * address, size_t peerCount, size_t channelLimit, enet_uint32 incomingBandwidth, enet_uint32 outgoingBandwidth)
enet_host_create (int addressFamily, const ENetAddress * address, size_t peerCount, size_t channelLimit, enet_uint32 incomingBandwidth, enet_uint32 outgoingBandwidth)
{
ENetHost * host;
ENetPeer * currentPeer;
@@ -48,7 +49,7 @@ enet_host_create (const ENetAddress * address, size_t peerCount, size_t channelL
}
memset (host -> peers, 0, peerCount * sizeof (ENetPeer));
host -> socket = enet_socket_create (ENET_SOCKET_TYPE_DATAGRAM);
host -> socket = enet_socket_create (addressFamily, ENET_SOCKET_TYPE_DATAGRAM);
if (host -> socket == ENET_SOCKET_NULL || (address != NULL && enet_socket_bind (host -> socket, address) < 0))
{
if (host -> socket != ENET_SOCKET_NULL)
@@ -61,9 +62,9 @@ enet_host_create (const ENetAddress * address, size_t peerCount, size_t channelL
}
enet_socket_set_option (host -> socket, ENET_SOCKOPT_NONBLOCK, 1);
enet_socket_set_option (host -> socket, ENET_SOCKOPT_BROADCAST, 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;
@@ -87,8 +88,8 @@ enet_host_create (const ENetAddress * address, size_t peerCount, size_t channelL
host -> commandCount = 0;
host -> bufferCount = 0;
host -> checksum = NULL;
host -> receivedAddress.host = ENET_HOST_ANY;
host -> receivedAddress.port = 0;
memset(& host -> receivedPeerAddress, 0, sizeof (host -> receivedPeerAddress));
memset(& host -> receivedLocalAddress, 0, sizeof (host -> receivedLocalAddress));
host -> receivedData = NULL;
host -> receivedDataLength = 0;
@@ -261,30 +262,6 @@ enet_host_connect (ENetHost * host, const ENetAddress * address, size_t channelC
return currentPeer;
}
/** Queues a packet to be sent to all peers associated with the host.
@param host host on which to broadcast the packet
@param channelID channel on which to broadcast
@param packet packet to broadcast
*/
void
enet_host_broadcast (ENetHost * host, enet_uint8 channelID, ENetPacket * packet)
{
ENetPeer * currentPeer;
for (currentPeer = host -> peers;
currentPeer < & host -> peers [host -> peerCount];
++ currentPeer)
{
if (currentPeer -> state != ENET_PEER_STATE_CONNECTED)
continue;
enet_peer_send (currentPeer, channelID, packet);
}
if (packet -> referenceCount == 0)
enet_packet_destroy (packet);
}
/** Sets the packet compressor the host should use to compress and decompress packets.
@param host host to enable or disable compression for
@param compressor callbacks for for the packet compressor; if NULL, then compression is disabled
+21 -60
View File
@@ -55,14 +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_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
@@ -72,24 +72,13 @@ typedef enum _ENetSocketShutdown
ENET_SOCKET_SHUTDOWN_READ_WRITE = 2
} ENetSocketShutdown;
#define ENET_HOST_ANY 0
#define ENET_HOST_BROADCAST 0xFFFFFFFFU
#define ENET_PORT_ANY 0
/**
* Portable internet address structure.
*
* 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. The constant ENET_HOST_BROADCAST may be used to specify the
* broadcast address (255.255.255.255). This makes sense for enet_host_connect,
* but not for enet_host_create. Once a server responds to a broadcast, the
* address is updated from ENET_HOST_BROADCAST to the server's actual IP address.
*/
typedef struct _ENetAddress
{
enet_uint32 host;
enet_uint16 port;
socklen_t addressLength;
struct sockaddr_storage address;
} ENetAddress;
/**
@@ -212,7 +201,7 @@ enum
ENET_HOST_RECEIVE_BUFFER_SIZE = 256 * 1024,
ENET_HOST_SEND_BUFFER_SIZE = 256 * 1024,
ENET_HOST_BANDWIDTH_THROTTLE_INTERVAL = 1000,
ENET_HOST_DEFAULT_MTU = 1400,
ENET_HOST_DEFAULT_MTU = 900,
ENET_HOST_DEFAULT_MAXIMUM_PACKET_SIZE = 32 * 1024 * 1024,
ENET_HOST_DEFAULT_MAXIMUM_WAITING_DATA = 32 * 1024 * 1024,
@@ -270,6 +259,7 @@ 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;
@@ -353,7 +343,6 @@ typedef int (ENET_CALLBACK * ENetInterceptCallback) (struct _ENetHost * host, st
@sa enet_host_connect()
@sa enet_host_service()
@sa enet_host_flush()
@sa enet_host_broadcast()
@sa enet_host_compress()
@sa enet_host_compress_with_range_coder()
@sa enet_host_channel_limit()
@@ -385,7 +374,8 @@ 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 receivedAddress;
ENetAddress receivedPeerAddress;
ENetAddress receivedLocalAddress;
enet_uint8 * receivedData;
size_t receivedDataLength;
enet_uint32 totalSentData; /**< total data sent, user should reset to 0 as needed to prevent overflow */
@@ -494,14 +484,14 @@ ENET_API void enet_time_set (enet_uint32);
/** @defgroup socket ENet socket functions
@{
*/
ENET_API ENetSocket enet_socket_create (ENetSocketType);
ENET_API ENetSocket enet_socket_create (int, ENetSocketType);
ENET_API int enet_socket_bind (ENetSocket, const ENetAddress *);
ENET_API int enet_socket_get_address (ENetSocket, ENetAddress *);
ENET_API int enet_socket_listen (ENetSocket, int);
ENET_API ENetSocket enet_socket_accept (ENetSocket, ENetAddress *);
ENET_API int enet_socket_connect (ENetSocket, const ENetAddress *);
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_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_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 *);
@@ -514,17 +504,6 @@ ENET_API int enet_socketset_select (ENetSocket, ENetSocketSet *, ENetSock
/** @defgroup Address ENet address functions
@{
*/
/** Attempts to parse the printable form of the IP address in the parameter hostName
and sets the host field in the address parameter if successful.
@param address destination to store the parsed IP address
@param hostName IP address to parse
@retval 0 on success
@retval < 0 on failure
@returns the address of the given hostName in address on success
*/
ENET_API int enet_address_set_host_ip (ENetAddress * address, const char * hostName);
/** Attempts to resolve the host named by the parameter hostName and sets
the host field in the address parameter if successful.
@param address destination to store resolved address
@@ -534,26 +513,9 @@ ENET_API int enet_address_set_host_ip (ENetAddress * address, const char * hostN
@returns the address of the given hostName in address on success
*/
ENET_API int enet_address_set_host (ENetAddress * address, const char * hostName);
/** Gives the printable form of the IP address specified in the address parameter.
@param address address printed
@param hostName destination for name, must not be NULL
@param nameLength maximum length of hostName.
@returns the null-terminated name of the host in hostName on success
@retval 0 on success
@retval < 0 on failure
*/
ENET_API int enet_address_get_host_ip (const ENetAddress * address, char * hostName, size_t nameLength);
/** Attempts to do a reverse lookup of the host field in the address parameter.
@param address address used for reverse lookup
@param hostName destination for name, must not be NULL
@param nameLength maximum length of hostName.
@returns the null-terminated name of the host in hostName on success
@retval 0 on success
@retval < 0 on failure
*/
ENET_API int enet_address_get_host (const ENetAddress * address, char * hostName, size_t nameLength);
ENET_API int enet_address_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_equal (ENetAddress * address1, ENetAddress * address2);
/** @} */
@@ -562,13 +524,12 @@ 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 (const ENetAddress *, size_t, size_t, enet_uint32, enet_uint32);
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);
ENET_API int enet_host_check_events (ENetHost *, ENetEvent *);
ENET_API int enet_host_service (ENetHost *, ENetEvent *, enet_uint32);
ENET_API void enet_host_flush (ENetHost *);
ENET_API void enet_host_broadcast (ENetHost *, enet_uint8, ENetPacket *);
ENET_API void enet_host_compress (ENetHost *, const ENetCompressor *);
ENET_API int enet_host_compress_with_range_coder (ENetHost * host);
ENET_API void enet_host_channel_limit (ENetHost *, size_t);
+4
View File
@@ -10,7 +10,11 @@
enum
{
ENET_PROTOCOL_MINIMUM_MTU = 576,
#ifdef __WIIU__
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
@@ -18,6 +18,7 @@
#include <stdlib.h>
#include <winsock2.h>
#include <Ws2tcpip.h>
typedef SOCKET ENetSocket;
+27 -20
View File
@@ -309,10 +309,9 @@ enet_protocol_handle_connect (ENetHost * host, ENetProtocolHeader * header, ENet
}
else
if (currentPeer -> state != ENET_PEER_STATE_CONNECTING &&
currentPeer -> address.host == host -> receivedAddress.host)
enet_address_equal (& currentPeer -> address, & host -> receivedPeerAddress))
{
if (currentPeer -> address.port == host -> receivedAddress.port &&
currentPeer -> connectID == command -> connect.connectID)
if (currentPeer -> connectID == command -> connect.connectID)
return NULL;
++ duplicatePeers;
@@ -330,7 +329,8 @@ 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 -> receivedAddress;
peer -> address = host -> receivedPeerAddress;
peer -> localAddress = host -> receivedLocalAddress;
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);
@@ -860,19 +860,19 @@ enet_protocol_handle_acknowledge (ENetHost * host, ENetEvent * event, ENetPeer *
{
enet_peer_throttle (peer, roundTripTime);
peer -> roundTripTimeVariance -= peer -> roundTripTimeVariance / 4;
peer -> roundTripTimeVariance -= (peer -> roundTripTimeVariance + 3) / 4;
if (roundTripTime >= peer -> roundTripTime)
{
enet_uint32 diff = roundTripTime - peer -> roundTripTime;
peer -> roundTripTimeVariance += diff / 4;
peer -> roundTripTime += diff / 8;
peer -> roundTripTimeVariance += (diff + 3) / 4;
peer -> roundTripTime += (diff + 7) / 8;
}
else
{
enet_uint32 diff = peer -> roundTripTime - roundTripTime;
peer -> roundTripTimeVariance += diff / 4;
peer -> roundTripTime -= diff / 8;
peer -> roundTripTimeVariance += (diff + 3) / 4;
peer -> roundTripTime -= (diff + 7) / 8;
}
}
else
@@ -1031,9 +1031,7 @@ enet_protocol_handle_incoming_commands (ENetHost * host, ENetEvent * event)
if (peer -> state == ENET_PEER_STATE_DISCONNECTED ||
peer -> state == ENET_PEER_STATE_ZOMBIE ||
((host -> receivedAddress.host != peer -> address.host ||
host -> receivedAddress.port != peer -> address.port) &&
peer -> address.host != ENET_HOST_BROADCAST) ||
/* ! enet_address_equal(& host -> receivedAddress, & peer -> address) || */
(peer -> outgoingPeerID < ENET_PROTOCOL_MAXIMUM_PEER_ID &&
sessionID != peer -> incomingSessionID))
return 0;
@@ -1075,8 +1073,8 @@ enet_protocol_handle_incoming_commands (ENetHost * host, ENetEvent * event)
if (peer != NULL)
{
peer -> address.host = host -> receivedAddress.host;
peer -> address.port = host -> receivedAddress.port;
memcpy(& peer -> address, & host -> receivedPeerAddress, sizeof (host -> receivedPeerAddress));
memcpy(& peer -> localAddress, & host -> receivedLocalAddress, sizeof (host -> receivedLocalAddress));
peer -> incomingDataTotal += host -> receivedDataLength;
}
@@ -1227,7 +1225,8 @@ enet_protocol_receive_incoming_commands (ENetHost * host, ENetEvent * event)
buffer.dataLength = sizeof (host -> packetData [0]);
receivedLength = enet_socket_receive (host -> socket,
& host -> receivedAddress,
& host -> receivedPeerAddress,
& host -> receivedLocalAddress,
& buffer,
1);
@@ -1368,6 +1367,8 @@ enet_protocol_check_timeouts (ENetHost * host, ENetPeer * peer, ENetEvent * even
++ peer -> packetsLost;
outgoingCommand -> roundTripTimeout *= 2;
if (outgoingCommand -> roundTripTimeout > outgoingCommand -> roundTripTimeoutLimit)
outgoingCommand -> roundTripTimeout = outgoingCommand -> roundTripTimeoutLimit;
enet_list_insert (insertPosition, enet_list_remove (& outgoingCommand -> outgoingCommandList));
@@ -1468,7 +1469,7 @@ enet_protocol_check_outgoing_commands (ENetHost * host, ENetPeer * peer)
if (outgoingCommand -> roundTripTimeout == 0)
{
outgoingCommand -> roundTripTimeout = peer -> roundTripTime + 4 * peer -> roundTripTimeVariance;
outgoingCommand -> roundTripTimeout = peer -> roundTripTime + 4 * ENET_MAX (1, peer -> roundTripTimeVariance);
outgoingCommand -> roundTripTimeoutLimit = peer -> timeoutLimit * outgoingCommand -> roundTripTimeout;
}
@@ -1686,7 +1687,13 @@ enet_protocol_send_outgoing_commands (ENetHost * host, ENetEvent * event, int ch
currentPeer -> lastSendTime = host -> serviceTime;
sentLength = enet_socket_send (host -> socket, & currentPeer -> address, host -> buffers, host -> bufferCount);
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, & currentPeer -> localAddress, host -> buffers, host -> bufferCount);
enet_protocol_remove_sent_unreliable_commands (currentPeer);
@@ -1780,7 +1787,7 @@ enet_host_service (ENetHost * host, ENetEvent * event, enet_uint32 timeout)
timeout += host -> serviceTime;
do
for (;;)
{
if (ENET_TIME_DIFFERENCE (host -> serviceTime, host -> bandwidthThrottleEpoch) >= ENET_HOST_BANDWIDTH_THROTTLE_INTERVAL)
enet_host_bandwidth_throttle (host);
@@ -1864,13 +1871,13 @@ enet_host_service (ENetHost * host, ENetEvent * event, enet_uint32 timeout)
waitCondition = ENET_SOCKET_WAIT_RECEIVE | ENET_SOCKET_WAIT_INTERRUPT;
if (enet_socket_wait (host -> socket, & waitCondition, ENET_TIME_DIFFERENCE (timeout, host -> serviceTime)) != 0)
if (enet_socket_wait (host -> socket, & waitCondition, ENET_TIME_DIFFERENCE (timeout, host -> serviceTime) / 10) != 0)
return -1;
}
while (waitCondition & ENET_SOCKET_WAIT_INTERRUPT);
host -> serviceTime = enet_time_get ();
} while (waitCondition & ENET_SOCKET_WAIT_RECEIVE);
}
return 0;
}
+379 -198
View File
@@ -4,9 +4,19 @@
*/
#ifndef _WIN32
// 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
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/select.h>
#include <sys/time.h>
#include <netinet/tcp.h>
#include <netdb.h>
@@ -18,9 +28,9 @@
#define ENET_BUILDING_LIB 1
#include "enet/enet.h"
#ifdef __APPLE__
#ifdef HAS_POLL
#undef HAS_POLL
#if defined(__APPLE__)
#ifndef HAS_POLL
#define HAS_POLL 1
#endif
#ifndef HAS_FCNTL
#define HAS_FCNTL 1
@@ -43,12 +53,79 @@
#ifndef HAS_GETNAMEINFO
#define HAS_GETNAMEINFO 1
#endif
#elif defined(__vita__)
#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
#endif
#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
#ifndef HAS_GETADDRINFO
#define HAS_GETADDRINFO 1
#endif
#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
#else
#ifndef HAS_IOCTL
#define HAS_IOCTL 1
#endif
#ifndef HAS_POLL
#define HAS_POLL 1
#endif
#endif
#ifdef HAS_FCNTL
#include <fcntl.h>
#endif
#ifdef HAS_IOCTL
#include <sys/ioctl.h>
#endif
#ifdef HAS_POLL
#include <poll.h>
#endif
@@ -57,6 +134,10 @@
typedef int socklen_t;
#endif
#ifndef SOMAXCONN
#define SOMAXCONN 128
#endif
#ifndef MSG_NOSIGNAL
#define MSG_NOSIGNAL 0
#endif
@@ -77,7 +158,11 @@ enet_deinitialize (void)
enet_uint32
enet_host_random_seed (void)
{
return (enet_uint32) time (NULL);
struct timeval timeVal;
gettimeofday (& timeVal, NULL);
return (timeVal.tv_sec * 1000) ^ (timeVal.tv_usec / 1000);
}
enet_uint32
@@ -101,186 +186,116 @@ enet_time_set (enet_uint32 newTimeBase)
}
int
enet_address_set_host_ip (ENetAddress * address, const char * name)
enet_address_equal (ENetAddress * address1, ENetAddress * address2)
{
#ifdef HAS_INET_PTON
if (! inet_pton (AF_INET, name, & address -> host))
#else
if (! inet_aton (name, (struct in_addr *) & address -> host))
#endif
return -1;
if (address1 -> address.ss_family != address2 -> address.ss_family)
return 0;
switch (address1 -> address.ss_family)
{
case AF_INET:
{
struct sockaddr_in *sin1, *sin2;
sin1 = (struct sockaddr_in *) & address1 -> address;
sin2 = (struct sockaddr_in *) & address2 -> address;
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;
sin6a = (struct sockaddr_in6 *) & address1 -> address;
sin6b = (struct sockaddr_in6 *) & address2 -> address;
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_set_port (ENetAddress * address, enet_uint16 port)
{
if (address -> address.ss_family == AF_INET)
{
struct sockaddr_in *sin = (struct sockaddr_in *) &address -> address;
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;
}
}
int
enet_address_set_address (ENetAddress * address, struct sockaddr * addr, socklen_t addrlen)
{
if (addrlen > sizeof(struct sockaddr_storage))
return -1;
memcpy (&address->address, addr, addrlen);
address->addressLength = addrlen;
return 0;
}
int
enet_address_set_host (ENetAddress * address, const char * name)
{
#ifdef HAS_GETADDRINFO
struct addrinfo hints, * resultList = NULL, * result = NULL;
memset (& hints, 0, sizeof (hints));
hints.ai_family = AF_INET;
hints.ai_family = AF_UNSPEC;
hints.ai_flags = AI_ADDRCONFIG;
if (getaddrinfo (name, NULL, NULL, & resultList) != 0)
if (getaddrinfo (name, NULL, & hints, & resultList) != 0)
return -1;
for (result = resultList; result != NULL; result = result -> ai_next)
{
if (result -> ai_family == AF_INET && result -> ai_addr != NULL && result -> ai_addrlen >= sizeof (struct sockaddr_in))
{
struct sockaddr_in * sin = (struct sockaddr_in *) result -> ai_addr;
address -> host = sin -> sin_addr.s_addr;
freeaddrinfo (resultList);
return 0;
}
memcpy (& address -> address, result -> ai_addr, result -> ai_addrlen);
address -> addressLength = result -> ai_addrlen;
freeaddrinfo (resultList);
return 0;
}
if (resultList != NULL)
freeaddrinfo (resultList);
#else
struct hostent * hostEntry = NULL;
#ifdef HAS_GETHOSTBYNAME_R
struct hostent hostData;
char buffer [2048];
int errnum;
#if defined(linux) || defined(__linux) || defined(__linux__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
gethostbyname_r (name, & hostData, buffer, sizeof (buffer), & hostEntry, & errnum);
#else
hostEntry = gethostbyname_r (name, & hostData, buffer, sizeof (buffer), & errnum);
#endif
#else
hostEntry = gethostbyname (name);
#endif
if (hostEntry != NULL && hostEntry -> h_addrtype == AF_INET)
{
address -> host = * (enet_uint32 *) hostEntry -> h_addr_list [0];
return 0;
}
#endif
return enet_address_set_host_ip (address, name);
}
int
enet_address_get_host_ip (const ENetAddress * address, char * name, size_t nameLength)
{
#ifdef HAS_INET_NTOP
if (inet_ntop (AF_INET, & address -> host, name, nameLength) == NULL)
#else
char * addr = inet_ntoa (* (struct in_addr *) & address -> host);
if (addr != NULL)
{
size_t addrLen = strlen(addr);
if (addrLen >= nameLength)
return -1;
memcpy (name, addr, addrLen + 1);
}
else
#endif
return -1;
return 0;
}
int
enet_address_get_host (const ENetAddress * address, char * name, size_t nameLength)
{
#ifdef HAS_GETNAMEINFO
struct sockaddr_in sin;
int err;
memset (& sin, 0, sizeof (struct sockaddr_in));
sin.sin_family = AF_INET;
sin.sin_port = ENET_HOST_TO_NET_16 (address -> port);
sin.sin_addr.s_addr = address -> host;
err = getnameinfo ((struct sockaddr *) & sin, sizeof (sin), name, nameLength, NULL, 0, NI_NAMEREQD);
if (! err)
{
if (name != NULL && nameLength > 0 && ! memchr (name, '\0', nameLength))
return -1;
return 0;
}
if (err != EAI_NONAME)
return -1;
#else
struct in_addr in;
struct hostent * hostEntry = NULL;
#ifdef HAS_GETHOSTBYADDR_R
struct hostent hostData;
char buffer [2048];
int errnum;
in.s_addr = address -> host;
#if defined(linux) || defined(__linux) || defined(__linux__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
gethostbyaddr_r ((char *) & in, sizeof (struct in_addr), AF_INET, & hostData, buffer, sizeof (buffer), & hostEntry, & errnum);
#else
hostEntry = gethostbyaddr_r ((char *) & in, sizeof (struct in_addr), AF_INET, & hostData, buffer, sizeof (buffer), & errnum);
#endif
#else
in.s_addr = address -> host;
hostEntry = gethostbyaddr ((char *) & in, sizeof (struct in_addr), AF_INET);
#endif
if (hostEntry != NULL)
{
size_t hostLen = strlen (hostEntry -> h_name);
if (hostLen >= nameLength)
return -1;
memcpy (name, hostEntry -> h_name, hostLen + 1);
return 0;
}
#endif
return enet_address_get_host_ip (address, name, nameLength);
return -1;
}
int
enet_socket_bind (ENetSocket socket, const ENetAddress * address)
{
struct sockaddr_in sin;
memset (& sin, 0, sizeof (struct sockaddr_in));
sin.sin_family = AF_INET;
if (address != NULL)
{
sin.sin_port = ENET_HOST_TO_NET_16 (address -> port);
sin.sin_addr.s_addr = address -> host;
}
else
{
sin.sin_port = 0;
sin.sin_addr.s_addr = INADDR_ANY;
}
return bind (socket,
(struct sockaddr *) & sin,
sizeof (struct sockaddr_in));
(struct sockaddr *) & address -> address,
address -> addressLength);
}
int
enet_socket_get_address (ENetSocket socket, ENetAddress * address)
{
struct sockaddr_in sin;
socklen_t sinLength = sizeof (struct sockaddr_in);
address -> addressLength = sizeof (address -> address);
if (getsockname (socket, (struct sockaddr *) & sin, & sinLength) == -1)
if (getsockname (socket, (struct sockaddr *) & address -> address, & address -> addressLength) == -1)
return -1;
address -> host = (enet_uint32) sin.sin_addr.s_addr;
address -> port = ENET_NET_TO_HOST_16 (sin.sin_port);
return 0;
}
@@ -291,9 +306,39 @@ enet_socket_listen (ENetSocket socket, int backlog)
}
ENetSocket
enet_socket_create (ENetSocketType type)
enet_socket_create (int af, ENetSocketType type)
{
return socket (PF_INET, type == ENET_SOCKET_TYPE_DATAGRAM ? SOCK_DGRAM : SOCK_STREAM, 0);
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));
}
#endif
#ifdef IPV6_RECVPKTINFO
if (af == AF_INET6) {
int on = 1;
setsockopt(sock, IPPROTO_IPV6, IPV6_RECVPKTINFO, (char *)&on, sizeof(on));
}
#endif
return sock;
}
int
@@ -306,12 +351,12 @@ enet_socket_set_option (ENetSocket socket, ENetSocketOption option, int value)
#ifdef HAS_FCNTL
result = fcntl (socket, F_SETFL, (value ? O_NONBLOCK : 0) | (fcntl (socket, F_GETFL) & ~O_NONBLOCK));
#else
#ifdef HAS_IOCTL
result = ioctl (socket, FIONBIO, & value);
#else
result = setsockopt (socket, SOL_SOCKET, SO_NONBLOCK, (char *) & value, sizeof(int));
#endif
#endif
break;
case ENET_SOCKOPT_BROADCAST:
result = setsockopt (socket, SOL_SOCKET, SO_BROADCAST, (char *) & value, sizeof (int));
break;
case ENET_SOCKOPT_REUSEADDR:
@@ -326,6 +371,7 @@ enet_socket_set_option (ENetSocket socket, ENetSocketOption option, int value)
result = setsockopt (socket, SOL_SOCKET, SO_SNDBUF, (char *) & value, sizeof (int));
break;
#ifndef __WIIU__
case ENET_SOCKOPT_RCVTIMEO:
{
struct timeval timeVal;
@@ -343,11 +389,36 @@ 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));
break;
case ENET_SOCKOPT_QOS:
#ifdef SO_NET_SERVICE_TYPE
// 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));
#else
#ifdef IP_TOS
// UNIX - IPv4
value = value ? 46 << 2 : 0; // DSCP: Expedited Forwarding
result = setsockopt (socket, IPPROTO_IP, IP_TOS, (char *) & value, sizeof (int));
#endif
#ifdef IPV6_TCLASS
// UNIX - IPv6
value = value ? 46 << 2: 0; // DSCP: Expedited Forwarding
result = setsockopt (socket, IPPROTO_IPV6, IPV6_TCLASS, (char *) & value, sizeof (int));
#endif
#ifdef SO_PRIORITY
// Linux
value = value ? 6 : 0; // Max priority without NET_CAP_ADMIN
result = setsockopt (socket, SOL_SOCKET, SO_PRIORITY, (char *) & value, sizeof (int));
#endif
#endif /* SO_NET_SERVICE_TYPE */
break;
default:
break;
}
@@ -375,16 +446,9 @@ enet_socket_get_option (ENetSocket socket, ENetSocketOption option, int * value)
int
enet_socket_connect (ENetSocket socket, const ENetAddress * address)
{
struct sockaddr_in sin;
int result;
memset (& sin, 0, sizeof (struct sockaddr_in));
sin.sin_family = AF_INET;
sin.sin_port = ENET_HOST_TO_NET_16 (address -> port);
sin.sin_addr.s_addr = address -> host;
result = connect (socket, (struct sockaddr *) & sin, sizeof (struct sockaddr_in));
result = connect (socket, (struct sockaddr *) & address -> address, address -> addressLength);
if (result == -1 && errno == EINPROGRESS)
return 0;
@@ -395,25 +459,20 @@ ENetSocket
enet_socket_accept (ENetSocket socket, ENetAddress * address)
{
int result;
struct sockaddr_in sin;
socklen_t sinLength = sizeof (struct sockaddr_in);
if (address != NULL)
address -> addressLength = sizeof (address -> address);
result = accept (socket,
address != NULL ? (struct sockaddr *) & sin : NULL,
address != NULL ? & sinLength : NULL);
address != NULL ? (struct sockaddr *) & address -> address : NULL,
address != NULL ? & address -> addressLength : NULL);
if (result == -1)
return ENET_SOCKET_NULL;
if (address != NULL)
{
address -> host = (enet_uint32) sin.sin_addr.s_addr;
address -> port = ENET_NET_TO_HOST_16 (sin.sin_port);
}
return result;
}
}
int
enet_socket_shutdown (ENetSocket socket, ENetSocketShutdown how)
{
@@ -429,32 +488,106 @@ enet_socket_destroy (ENetSocket socket)
int
enet_socket_send (ENetSocket socket,
const ENetAddress * address,
const ENetAddress * peerAddress,
const ENetAddress * localAddress,
const ENetBuffer * buffers,
size_t bufferCount)
{
struct msghdr msgHdr;
struct sockaddr_in sin;
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++)
{
memcpy (& ((unsigned char *)sendBuffer)[sendLength], buffers[i].data, buffers[i].dataLength);
sendLength += buffers[i].dataLength;
}
}
else
{
sendBuffer = buffers[0].data;
sendLength = buffers[0].dataLength;
}
sentLength = sendto (socket, sendBuffer, sendLength, MSG_NOSIGNAL,
(struct sockaddr *) & peerAddress -> address, peerAddress -> addressLength);
if (bufferCount > 1)
free(sendBuffer);
#else
struct msghdr msgHdr;
char controlBufData[1024];
memset (& msgHdr, 0, sizeof (struct msghdr));
if (address != NULL)
if (peerAddress != NULL)
{
memset (& sin, 0, sizeof (struct sockaddr_in));
sin.sin_family = AF_INET;
sin.sin_port = ENET_HOST_TO_NET_16 (address -> port);
sin.sin_addr.s_addr = address -> host;
msgHdr.msg_name = & sin;
msgHdr.msg_namelen = sizeof (struct sockaddr_in);
msgHdr.msg_name = (void*) & peerAddress -> address;
msgHdr.msg_namelen = peerAddress -> 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));
}
#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)
{
@@ -469,24 +602,45 @@ enet_socket_send (ENetSocket socket,
int
enet_socket_receive (ENetSocket socket,
ENetAddress * address,
ENetAddress * peerAddress,
ENetAddress * localAddress,
ENetBuffer * buffers,
size_t bufferCount)
{
struct msghdr msgHdr;
struct sockaddr_in sin;
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 *) & peerAddress -> address, & peerAddress -> 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 (address != NULL)
if (peerAddress != NULL)
{
msgHdr.msg_name = & sin;
msgHdr.msg_namelen = sizeof (struct sockaddr_in);
msgHdr.msg_name = & peerAddress -> address;
msgHdr.msg_namelen = sizeof (peerAddress -> 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);
@@ -503,13 +657,40 @@ enet_socket_receive (ENetSocket socket,
return -1;
#endif
if (address != NULL)
{
address -> host = (enet_uint32) sin.sin_addr.s_addr;
address -> port = ENET_NET_TO_HOST_16 (sin.sin_port);
// 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;
}
#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;
return recvLength;
#endif
}
int
+316 -152
View File
@@ -7,21 +7,43 @@
#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;
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);
LPFN_WSARECVMSG pfnWSARecvMsg;
int
enet_initialize (void)
{
WORD versionRequested = MAKEWORD (1, 1);
WORD versionRequested = MAKEWORD (2, 0);
WSADATA wsaData;
if (WSAStartup (versionRequested, & wsaData))
return -1;
if (LOBYTE (wsaData.wVersion) != 1||
HIBYTE (wsaData.wVersion) != 1)
if (LOBYTE (wsaData.wVersion) != 2||
HIBYTE (wsaData.wVersion) != 0)
{
WSACleanup ();
@@ -30,12 +52,46 @@ enet_initialize (void)
timeBeginPeriod (1);
QwaveLibraryHandle = LoadLibraryA("qwave.dll");
if (QwaveLibraryHandle != NULL) {
pfnQOSCreateHandle = (void*)GetProcAddress(QwaveLibraryHandle, "QOSCreateHandle");
pfnQOSCloseHandle = (void*)GetProcAddress(QwaveLibraryHandle, "QOSCloseHandle");
pfnQOSAddSocketToFlow = (void*)GetProcAddress(QwaveLibraryHandle, "QOSAddSocketToFlow");
if (pfnQOSCreateHandle == NULL || pfnQOSCloseHandle == NULL || pfnQOSAddSocketToFlow == NULL) {
pfnQOSCreateHandle = NULL;
pfnQOSCloseHandle = NULL;
pfnQOSAddSocketToFlow = NULL;
FreeLibrary(QwaveLibraryHandle);
QwaveLibraryHandle = NULL;
}
}
return 0;
}
void
enet_deinitialize (void)
{
qosAddedFlow = FALSE;
qosFlowId = 0;
if (qosHandle != INVALID_HANDLE_VALUE)
{
pfnQOSCloseHandle(qosHandle);
qosHandle = INVALID_HANDLE_VALUE;
}
if (QwaveLibraryHandle != NULL) {
pfnQOSCreateHandle = NULL;
pfnQOSCloseHandle = NULL;
pfnQOSAddSocketToFlow = NULL;
FreeLibrary(QwaveLibraryHandle);
QwaveLibraryHandle = NULL;
}
timeEndPeriod (1);
WSACleanup ();
@@ -60,121 +116,112 @@ enet_time_set (enet_uint32 newTimeBase)
}
int
enet_address_set_host_ip (ENetAddress * address, const char * name)
enet_address_set_port (ENetAddress * address, enet_uint16 port)
{
enet_uint8 vals [4] = { 0, 0, 0, 0 };
int i;
for (i = 0; i < 4; ++ i)
if (address -> address.ss_family == AF_INET)
{
const char * next = name + 1;
if (* name != '0')
{
long val = strtol (name, (char **) & next, 10);
if (val < 0 || val > 255 || next == name || next - name > 3)
return -1;
vals [i] = (enet_uint8) val;
}
if (* next != (i < 3 ? '.' : '\0'))
return -1;
name = next + 1;
struct sockaddr_in *sin = (struct sockaddr_in *) &address -> address;
sin -> sin_port = ENET_HOST_TO_NET_16 (port);
return 0;
}
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;
}
else
{
return -1;
}
}
memcpy (& address -> host, vals, sizeof (enet_uint32));
int
enet_address_set_address (ENetAddress * address, struct sockaddr * addr, socklen_t addrlen)
{
if (addrlen > sizeof(struct sockaddr_storage))
return -1;
memcpy (&address->address, addr, addrlen);
address->addressLength = addrlen;
return 0;
}
int
enet_address_equal (ENetAddress * address1, ENetAddress * address2)
{
if (address1 -> address.ss_family != address2 -> address.ss_family)
return 0;
switch (address1 -> address.ss_family)
{
case AF_INET:
{
struct sockaddr_in *sin1, *sin2;
sin1 = (struct sockaddr_in *) & address1 -> address;
sin2 = (struct sockaddr_in *) & address2 -> address;
return sin1 -> sin_port == sin2 -> sin_port &&
sin1 -> sin_addr.S_un.S_addr == sin2 -> sin_addr.S_un.S_addr;
}
case AF_INET6:
{
struct sockaddr_in6 *sin6a, *sin6b;
sin6a = (struct sockaddr_in6 *) & address1 -> address;
sin6b = (struct sockaddr_in6 *) & address2 -> address;
return sin6a -> sin6_port == sin6b -> sin6_port &&
! memcmp (& sin6a -> sin6_addr, & sin6b -> sin6_addr, sizeof (sin6a -> sin6_addr));
}
default:
{
return 0;
}
}
}
int
enet_address_set_host (ENetAddress * address, const char * name)
{
struct hostent * hostEntry;
struct addrinfo hints, * resultList = NULL, * result = NULL;
hostEntry = gethostbyname (name);
if (hostEntry == NULL ||
hostEntry -> h_addrtype != AF_INET)
return enet_address_set_host_ip (address, name);
memset (& hints, 0, sizeof (hints));
hints.ai_family = AF_UNSPEC;
hints.ai_flags = AI_ADDRCONFIG;
address -> host = * (enet_uint32 *) hostEntry -> h_addr_list [0];
if (getaddrinfo (name, NULL, & hints, & resultList) != 0)
return -1;
return 0;
}
int
enet_address_get_host_ip (const ENetAddress * address, char * name, size_t nameLength)
{
char * addr = inet_ntoa (* (struct in_addr *) & address -> host);
if (addr == NULL)
return -1;
else
for (result = resultList; result != NULL; result = result -> ai_next)
{
size_t addrLen = strlen(addr);
if (addrLen >= nameLength)
return -1;
memcpy (name, addr, addrLen + 1);
}
return 0;
}
int
enet_address_get_host (const ENetAddress * address, char * name, size_t nameLength)
{
struct in_addr in;
struct hostent * hostEntry;
in.s_addr = address -> host;
hostEntry = gethostbyaddr ((char *) & in, sizeof (struct in_addr), AF_INET);
if (hostEntry == NULL)
return enet_address_get_host_ip (address, name, nameLength);
else
{
size_t hostLen = strlen (hostEntry -> h_name);
if (hostLen >= nameLength)
return -1;
memcpy (name, hostEntry -> h_name, hostLen + 1);
memcpy (& address -> address, result -> ai_addr, result -> ai_addrlen);
address -> addressLength = result -> ai_addrlen;
freeaddrinfo (resultList);
return 0;
}
return 0;
if (resultList != NULL)
freeaddrinfo (resultList);
return -1;
}
int
enet_socket_bind (ENetSocket socket, const ENetAddress * address)
{
struct sockaddr_in sin;
memset (& sin, 0, sizeof (struct sockaddr_in));
sin.sin_family = AF_INET;
if (address != NULL)
{
sin.sin_port = ENET_HOST_TO_NET_16 (address -> port);
sin.sin_addr.s_addr = address -> host;
}
else
{
sin.sin_port = 0;
sin.sin_addr.s_addr = INADDR_ANY;
}
return bind (socket,
(struct sockaddr *) & sin,
sizeof (struct sockaddr_in)) == SOCKET_ERROR ? -1 : 0;
(struct sockaddr *) & address -> address,
address -> addressLength);
}
int
enet_socket_get_address (ENetSocket socket, ENetAddress * address)
{
struct sockaddr_in sin;
int sinLength = sizeof (struct sockaddr_in);
address -> addressLength = sizeof (address -> address);
if (getsockname (socket, (struct sockaddr *) & sin, & sinLength) == -1)
if (getsockname (socket, (struct sockaddr *) & address -> address, & address -> addressLength) == -1)
return -1;
address -> host = (enet_uint32) sin.sin_addr.s_addr;
address -> port = ENET_NET_TO_HOST_16 (sin.sin_port);
return 0;
}
@@ -185,9 +232,48 @@ enet_socket_listen (ENetSocket socket, int backlog)
}
ENetSocket
enet_socket_create (ENetSocketType type)
enet_socket_create (int af, ENetSocketType type)
{
return socket (PF_INET, type == ENET_SOCKET_TYPE_DATAGRAM ? SOCK_DGRAM : SOCK_STREAM, 0);
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;
}
int
@@ -203,10 +289,6 @@ enet_socket_set_option (ENetSocket socket, ENetSocketOption option, int value)
break;
}
case ENET_SOCKOPT_BROADCAST:
result = setsockopt (socket, SOL_SOCKET, SO_BROADCAST, (char *) & value, sizeof (int));
break;
case ENET_SOCKOPT_REUSEADDR:
result = setsockopt (socket, SOL_SOCKET, SO_REUSEADDR, (char *) & value, sizeof (int));
break;
@@ -231,6 +313,32 @@ enet_socket_set_option (ENetSocket socket, ENetSocketOption option, int value)
result = setsockopt (socket, IPPROTO_TCP, TCP_NODELAY, (char *) & value, sizeof (int));
break;
case ENET_SOCKOPT_QOS:
{
if (value)
{
QOS_VERSION qosVersion;
qosVersion.MajorVersion = 1;
qosVersion.MinorVersion = 0;
if (pfnQOSCreateHandle == NULL || !pfnQOSCreateHandle(&qosVersion, &qosHandle))
{
qosHandle = INVALID_HANDLE_VALUE;
}
}
else if (qosHandle != INVALID_HANDLE_VALUE)
{
pfnQOSCloseHandle(qosHandle);
qosHandle = INVALID_HANDLE_VALUE;
}
qosAddedFlow = FALSE;
qosFlowId = 0;
result = 0;
break;
}
default:
break;
}
@@ -257,16 +365,9 @@ enet_socket_get_option (ENetSocket socket, ENetSocketOption option, int * value)
int
enet_socket_connect (ENetSocket socket, const ENetAddress * address)
{
struct sockaddr_in sin;
int result;
memset (& sin, 0, sizeof (struct sockaddr_in));
sin.sin_family = AF_INET;
sin.sin_port = ENET_HOST_TO_NET_16 (address -> port);
sin.sin_addr.s_addr = address -> host;
result = connect (socket, (struct sockaddr *) & sin, sizeof (struct sockaddr_in));
result = connect (socket, (struct sockaddr *) & address -> address, address -> addressLength);
if (result == SOCKET_ERROR && WSAGetLastError () != WSAEWOULDBLOCK)
return -1;
@@ -276,22 +377,17 @@ enet_socket_connect (ENetSocket socket, const ENetAddress * address)
ENetSocket
enet_socket_accept (ENetSocket socket, ENetAddress * address)
{
SOCKET result;
struct sockaddr_in sin;
int sinLength = sizeof (struct sockaddr_in);
result = accept (socket,
address != NULL ? (struct sockaddr *) & sin : NULL,
address != NULL ? & sinLength : NULL);
if (result == INVALID_SOCKET)
return ENET_SOCKET_NULL;
int result;
if (address != NULL)
{
address -> host = (enet_uint32) sin.sin_addr.s_addr;
address -> port = ENET_NET_TO_HOST_16 (sin.sin_port);
}
address -> addressLength = sizeof (address -> address);
result = accept (socket,
address != NULL ? (struct sockaddr *) & address -> address : NULL,
address != NULL ? & address -> addressLength : NULL);
if (result == -1)
return ENET_SOCKET_NULL;
return result;
}
@@ -311,31 +407,76 @@ enet_socket_destroy (ENetSocket socket)
int
enet_socket_send (ENetSocket socket,
const ENetAddress * address,
const ENetAddress * peerAddress,
const ENetAddress * localAddress,
const ENetBuffer * buffers,
size_t bufferCount)
{
struct sockaddr_in sin;
DWORD sentLength = 0;
DWORD sentLength;
WSAMSG msg = { 0 };
char controlBufData[1024];
if (address != NULL)
if (!qosAddedFlow && qosHandle != INVALID_HANDLE_VALUE)
{
memset (& sin, 0, sizeof (struct sockaddr_in));
qosFlowId = 0; // Must be initialized to 0
pfnQOSAddSocketToFlow(qosHandle,
socket,
(struct sockaddr *)&peerAddress->address,
QOSTrafficTypeControl,
QOS_NON_ADAPTIVE_FLOW,
&qosFlowId);
sin.sin_family = AF_INET;
sin.sin_port = ENET_HOST_TO_NET_16 (address -> port);
sin.sin_addr.s_addr = address -> host;
// Even if we failed, don't try again
qosAddedFlow = TRUE;
}
if (WSASendTo (socket,
(LPWSABUF) buffers,
(DWORD) bufferCount,
& sentLength,
0,
address != NULL ? (struct sockaddr *) & sin : NULL,
address != NULL ? sizeof (struct sockaddr_in) : 0,
NULL,
NULL) == SOCKET_ERROR)
msg.name = peerAddress != NULL ? (struct sockaddr *) & peerAddress -> address : NULL;
msg.namelen = peerAddress != NULL ? peerAddress -> addressLength : 0;
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));
PWSACMSGHDR chdr = WSA_CMSG_FIRSTHDR(&msg);
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));
PWSACMSGHDR chdr = WSA_CMSG_FIRSTHDR(&msg);
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));
}
}
if (WSASendMsg (socket,
& msg,
0,
& sentLength,
NULL,
NULL) == SOCKET_ERROR)
{
if (WSAGetLastError () == WSAEWOULDBLOCK)
return 0;
@@ -348,24 +489,27 @@ enet_socket_send (ENetSocket socket,
int
enet_socket_receive (ENetSocket socket,
ENetAddress * address,
ENetAddress * peerAddress,
ENetAddress * localAddress,
ENetBuffer * buffers,
size_t bufferCount)
{
INT sinLength = sizeof (struct sockaddr_in);
DWORD flags = 0,
recvLength = 0;
struct sockaddr_in sin;
DWORD recvLength;
WSAMSG msg = { 0 };
char controlBufData[1024];
if (WSARecvFrom (socket,
(LPWSABUF) buffers,
(DWORD) bufferCount,
& recvLength,
& flags,
address != NULL ? (struct sockaddr *) & sin : NULL,
address != NULL ? & sinLength : NULL,
NULL,
NULL) == SOCKET_ERROR)
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)
{
switch (WSAGetLastError ())
{
@@ -377,15 +521,35 @@ enet_socket_receive (ENetSocket socket,
return -1;
}
if (flags & MSG_PARTIAL)
if (msg.dwFlags & MSG_PARTIAL)
return -1;
if (address != NULL)
{
address -> host = (enet_uint32) sin.sin_addr.s_addr;
address -> port = ENET_NET_TO_HOST_16 (sin.sin_port);
// 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;
}