Compare commits
126 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 0eb84dcca8 | |||
| c7353c0593 | |||
| 78cc9b4b03 | |||
| dea6fb5414 | |||
| 115a10baa1 | |||
| 44c85e1627 | |||
| badcd6c01d | |||
| b757dc7c28 | |||
| bbf71856bb | |||
| 76125b56b3 | |||
| 9e1cfe280a | |||
| 0032f5e750 | |||
| d3a323fc8b | |||
| 04e2759067 | |||
| a754295f42 | |||
| a92d6960a6 | |||
| a339bf51c8 | |||
| 061ce30163 | |||
| c76572875a | |||
| f6e67b1138 | |||
| acf813c4aa | |||
| c6bb0e5011 | |||
| 43218d4de2 | |||
| 89a7ebd63d | |||
| c07aa74c60 | |||
| bbfe93c248 | |||
| 880e41f3ab | |||
| 50ab7907d8 | |||
| 68ffba7d45 | |||
| bbed828aae | |||
| bdda0eecc5 | |||
| 2a85cd6445 | |||
| 4979b629c2 | |||
| 33c726ab73 | |||
| 441a6e9c5b | |||
| 7914bc74a9 | |||
| fc123218d3 | |||
| ea4607a90d | |||
| 8ae0e85298 | |||
| 07a40ef0f9 | |||
| eb89a34d66 | |||
| 4faa11a243 | |||
| 47e42dbf42 | |||
| 153e10f953 | |||
| e790647a57 | |||
| be7cefa39c | |||
| 9dde91d003 | |||
| ca18dfb8f8 | |||
| d7e5470cf7 | |||
| bb788ea48b | |||
| 4e69c700d6 | |||
| 311360dbdd | |||
| b06d154579 | |||
| 6800acd9c7 | |||
| 4f8e9bdc4c | |||
| 3340d1cf85 | |||
| bd0115c907 | |||
| 987cd0650f | |||
| 92ef50a080 | |||
| 498b9e3571 | |||
| 4cde9cc3dc | |||
| 74cea7abf5 | |||
| 8d69c5abe4 | |||
| ad5bf95397 | |||
| ab9d471cec | |||
| c20ca391e2 | |||
| 9fda19e54b | |||
| 70ce1c3e0b | |||
| cf735e639e | |||
| e8dbb360fb | |||
| 0286dcdb34 | |||
| d8976c4fcc | |||
| bdfdb8b85d | |||
| e3ada4ed75 | |||
| d9e561938f | |||
| 2cc0e7c780 | |||
| b64793fa5e | |||
| e0e7045b7e | |||
| 4de13a2c2e | |||
| 0d1fb32ee8 | |||
| 0bd265b230 | |||
| 54dac7af81 | |||
| b63fd5256a | |||
| 65dc0f74d8 | |||
| bde113ef56 | |||
| e55d226969 | |||
| 259e5dbd23 | |||
| 8d55487767 | |||
| 5de0a6f764 | |||
| 2a788029bf | |||
| 757933e7bc | |||
| eda26a26d9 | |||
| 4f3dbbaeb1 | |||
| 47d2e192aa | |||
| 8d794daa7c | |||
| 224f31101f | |||
| 22272e29f9 | |||
| 5b93d08fa5 | |||
| c25b57b2c1 | |||
| f89e5986d0 | |||
| bb14921419 | |||
| 67cee4803a | |||
| 007b7d2a3f | |||
| 92bf2d8256 | |||
| 33c7d6903e | |||
| 6991632abf | |||
| b4c427059a | |||
| 6537dc81f3 | |||
| 0eaf48eeb0 | |||
| b8713bdf88 | |||
| e2ef83927d | |||
| cea2c5be9f | |||
| 295456fba9 | |||
| 219c625c74 | |||
| 335715309c | |||
| 2e1c6bceea | |||
| 39a72ab199 | |||
| 67f964c2ad | |||
| a84c120eff | |||
| 6cc8cc8a26 | |||
| 9d9ba122d4 | |||
| 90560cd471 | |||
| 0891c520d2 | |||
| 5f5e977eef | |||
| 3ae5af4548 | |||
| f46fee0acc |
@@ -0,0 +1,21 @@
|
||||
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 }}
|
||||
+66
-14
@@ -1,7 +1,9 @@
|
||||
cmake_minimum_required(VERSION 2.6)
|
||||
cmake_minimum_required(VERSION 2.8.12...3.20)
|
||||
|
||||
project(enet)
|
||||
|
||||
option(ENET_NO_INSTALL "Disable installation of headers and libraries" OFF)
|
||||
|
||||
# The "configure" step.
|
||||
include(CheckFunctionExists)
|
||||
include(CheckStructHasMember)
|
||||
@@ -19,7 +21,16 @@ 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()
|
||||
@@ -53,17 +64,58 @@ 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
|
||||
callbacks.c
|
||||
compress.c
|
||||
host.c
|
||||
list.c
|
||||
packet.c
|
||||
peer.c
|
||||
protocol.c
|
||||
unix.c
|
||||
win32.c
|
||||
)
|
||||
${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()
|
||||
|
||||
@@ -1,4 +1,25 @@
|
||||
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):
|
||||
|
||||
|
||||
@@ -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.13
|
||||
PROJECT_NUMBER = v1.3.17
|
||||
|
||||
# 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,4 +1,4 @@
|
||||
Copyright (c) 2002-2016 Lee Salzman
|
||||
Copyright (c) 2002-2020 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
@@ -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:1:0
|
||||
libenet_la_LDFLAGS = $(AM_LDFLAGS) -version-info 7:5:0
|
||||
AM_CPPFLAGS = -I$(top_srcdir)/include
|
||||
|
||||
ACLOCAL_AMFLAGS = -Im4
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Please visit the ENet homepage at http://enet.bespin.org for installation
|
||||
Please visit the ENet homepage at http://sauerbraten.org/enet/ for installation
|
||||
and usage instructions.
|
||||
|
||||
If you obtained this package from github, the quick description on how to build
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
AC_INIT([libenet], [1.3.13])
|
||||
AC_INIT([libenet], [1.3.17])
|
||||
AC_CONFIG_SRCDIR([include/enet/enet.h])
|
||||
AM_INIT_AUTOMAKE([foreign])
|
||||
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
@page License License
|
||||
|
||||
Copyright (c) 2002-2016 Lee Salzman
|
||||
Copyright (c) 2002-2020 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
@@ -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.13) can be downloaded <a class="el" href="download/enet-1.3.13.tar.gz">here</a>.
|
||||
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 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="http://freenode.net">freenode IRC network (irc.freenode.net)</a> for real-time discussion about the ENet library.
|
||||
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.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
+2
-2
@@ -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 */,
|
||||
57600 / 8 /* 56K modem with 56 Kbps downstream bandwidth */,
|
||||
14400 / 8 /* 56K modem with 14 Kbps upstream bandwidth */);
|
||||
0 /* assume any amount of incoming bandwidth */,
|
||||
0 /* assume any amount of outgoing bandwidth */);
|
||||
|
||||
if (client == NULL)
|
||||
{
|
||||
|
||||
@@ -61,10 +61,11 @@ 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;
|
||||
@@ -88,7 +89,8 @@ enet_host_create (int addressFamily, const ENetAddress * address, size_t peerCou
|
||||
host -> commandCount = 0;
|
||||
host -> bufferCount = 0;
|
||||
host -> checksum = NULL;
|
||||
memset(& host -> receivedAddress, 0, sizeof (host -> receivedAddress));
|
||||
memset(& host -> receivedPeerAddress, 0, sizeof (host -> receivedPeerAddress));
|
||||
memset(& host -> receivedLocalAddress, 0, sizeof (host -> receivedLocalAddress));
|
||||
host -> receivedData = NULL;
|
||||
host -> receivedDataLength = 0;
|
||||
|
||||
@@ -96,6 +98,7 @@ 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;
|
||||
@@ -123,9 +126,8 @@ 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 -> sentUnreliableCommands);
|
||||
enet_list_clear (& currentPeer -> outgoingReliableCommands);
|
||||
enet_list_clear (& currentPeer -> outgoingUnreliableCommands);
|
||||
enet_list_clear (& currentPeer -> outgoingCommands);
|
||||
enet_list_clear (& currentPeer -> outgoingSendReliableCommands);
|
||||
enet_list_clear (& currentPeer -> dispatchedCommands);
|
||||
|
||||
enet_peer_reset (currentPeer);
|
||||
@@ -161,6 +163,16 @@ 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
|
||||
@@ -200,7 +212,8 @@ 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 = ++ host -> randomSeed;
|
||||
currentPeer -> connectID = enet_host_random (host);
|
||||
currentPeer -> mtu = host -> mtu;
|
||||
|
||||
if (host -> outgoingBandwidth == 0)
|
||||
currentPeer -> windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE;
|
||||
|
||||
+79
-56
@@ -1,4 +1,4 @@
|
||||
/**
|
||||
/**
|
||||
@file enet.h
|
||||
@brief ENet public header file
|
||||
*/
|
||||
@@ -12,7 +12,7 @@ extern "C"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#if defined(_WIN32) && !defined(NXDK)
|
||||
#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 13
|
||||
#define ENET_VERSION_PATCH 17
|
||||
#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,14 +55,16 @@ typedef enum _ENetSocketWait
|
||||
typedef enum _ENetSocketOption
|
||||
{
|
||||
ENET_SOCKOPT_NONBLOCK = 1,
|
||||
ENET_SOCKOPT_RCVBUF,
|
||||
ENET_SOCKOPT_SNDBUF,
|
||||
ENET_SOCKOPT_REUSEADDR,
|
||||
ENET_SOCKOPT_RCVTIMEO,
|
||||
ENET_SOCKOPT_SNDTIMEO,
|
||||
ENET_SOCKOPT_ERROR,
|
||||
ENET_SOCKOPT_NODELAY,
|
||||
ENET_SOCKOPT_QOS,
|
||||
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,
|
||||
} ENetSocketOption;
|
||||
|
||||
typedef enum _ENetSocketShutdown
|
||||
@@ -73,7 +75,7 @@ typedef enum _ENetSocketShutdown
|
||||
} ENetSocketShutdown;
|
||||
|
||||
/**
|
||||
* Portable internet address structure.
|
||||
* Portable internet address structure.
|
||||
*/
|
||||
typedef struct _ENetAddress
|
||||
{
|
||||
@@ -87,7 +89,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
|
||||
@@ -114,16 +116,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
|
||||
@@ -158,7 +160,7 @@ typedef struct _ENetOutgoingCommand
|
||||
enet_uint16 unreliableSequenceNumber;
|
||||
enet_uint32 sentTime;
|
||||
enet_uint32 roundTripTimeout;
|
||||
enet_uint32 roundTripTimeoutLimit;
|
||||
enet_uint32 queueTime;
|
||||
enet_uint32 fragmentOffset;
|
||||
enet_uint16 fragmentLength;
|
||||
enet_uint16 sendAttempts;
|
||||
@@ -167,7 +169,7 @@ typedef struct _ENetOutgoingCommand
|
||||
} ENetOutgoingCommand;
|
||||
|
||||
typedef struct _ENetIncomingCommand
|
||||
{
|
||||
{
|
||||
ENetListNode incomingCommandList;
|
||||
enet_uint16 reliableSequenceNumber;
|
||||
enet_uint16 unreliableSequenceNumber;
|
||||
@@ -189,7 +191,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
|
||||
@@ -198,8 +200,17 @@ 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,
|
||||
@@ -208,7 +219,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,
|
||||
@@ -239,13 +250,19 @@ 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;
|
||||
@@ -254,6 +271,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;
|
||||
@@ -296,14 +314,14 @@ typedef struct _ENetPeer
|
||||
enet_uint16 outgoingReliableSequenceNumber;
|
||||
ENetList acknowledgements;
|
||||
ENetList sentReliableCommands;
|
||||
ENetList sentUnreliableCommands;
|
||||
ENetList outgoingReliableCommands;
|
||||
ENetList outgoingUnreliableCommands;
|
||||
ENetList outgoingSendReliableCommands;
|
||||
ENetList outgoingCommands;
|
||||
ENetList dispatchedCommands;
|
||||
int needsDispatch;
|
||||
enet_uint16 flags;
|
||||
enet_uint16 reserved;
|
||||
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;
|
||||
@@ -327,7 +345,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.
|
||||
@@ -346,6 +364,7 @@ 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 */
|
||||
@@ -358,7 +377,7 @@ typedef struct _ENetHost
|
||||
size_t channelLimit; /**< maximum number of channels allowed for connected peers */
|
||||
enet_uint32 serviceTime;
|
||||
ENetList dispatchQueue;
|
||||
int continueSending;
|
||||
enet_uint32 totalQueued;
|
||||
size_t packetSize;
|
||||
enet_uint16 headerFlags;
|
||||
ENetProtocol commands [ENET_PROTOCOL_MAXIMUM_PACKET_COMMANDS];
|
||||
@@ -368,7 +387,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 */
|
||||
@@ -389,21 +409,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
|
||||
@@ -416,10 +436,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 */
|
||||
@@ -429,17 +449,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
|
||||
@@ -448,7 +468,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.
|
||||
*/
|
||||
@@ -456,7 +476,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);
|
||||
|
||||
@@ -483,8 +503,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 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 *);
|
||||
@@ -508,6 +528,7 @@ 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);
|
||||
|
||||
/** @} */
|
||||
@@ -516,7 +537,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);
|
||||
@@ -529,6 +550,7 @@ 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);
|
||||
@@ -542,12 +564,13 @@ 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 *);
|
||||
extern void enet_peer_dispatch_incoming_reliable_commands (ENetPeer *, ENetChannel *);
|
||||
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_on_connect (ENetPeer *);
|
||||
extern void enet_peer_on_disconnect (ENetPeer *);
|
||||
|
||||
@@ -555,7 +578,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,4 +1,4 @@
|
||||
/**
|
||||
/**
|
||||
@file protocol.h
|
||||
@brief ENet protocol
|
||||
*/
|
||||
@@ -10,7 +10,11 @@
|
||||
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,
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/in.h>
|
||||
#include <unistd.h>
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
#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__ */
|
||||
|
||||
|
||||
@@ -11,12 +11,14 @@
|
||||
#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;
|
||||
|
||||
|
||||
@@ -98,53 +98,46 @@ enet_packet_resize (ENetPacket * packet, size_t dataLength)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int initializedCRC32 = 0;
|
||||
static enet_uint32 crcTable [256];
|
||||
|
||||
static enet_uint32
|
||||
reflect_crc (int val, int bits)
|
||||
static const enet_uint32 crcTable [256] =
|
||||
{
|
||||
int result = 0, bit;
|
||||
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
|
||||
};
|
||||
|
||||
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)
|
||||
{
|
||||
@@ -153,7 +146,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;
|
||||
|
||||
@@ -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,6 +90,13 @@ 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
|
||||
@@ -99,7 +106,7 @@ enet_peer_throttle (ENetPeer * peer, enet_uint32 rtt)
|
||||
int
|
||||
enet_peer_send (ENetPeer * peer, enet_uint8 channelID, ENetPacket * packet)
|
||||
{
|
||||
ENetChannel * channel = & peer -> channels [channelID];
|
||||
ENetChannel * channel;
|
||||
ENetProtocol command;
|
||||
size_t fragmentLength;
|
||||
|
||||
@@ -108,6 +115,7 @@ 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);
|
||||
@@ -268,7 +276,7 @@ enet_peer_reset_outgoing_commands (ENetList * queue)
|
||||
}
|
||||
|
||||
static void
|
||||
enet_peer_remove_incoming_commands (ENetList * queue, ENetListIterator startCommand, ENetListIterator endCommand)
|
||||
enet_peer_remove_incoming_commands (ENetList * queue, ENetListIterator startCommand, ENetListIterator endCommand, ENetIncomingCommand * excludeCommand)
|
||||
{
|
||||
ENetListIterator currentCommand;
|
||||
|
||||
@@ -278,6 +286,9 @@ 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)
|
||||
@@ -298,7 +309,7 @@ enet_peer_remove_incoming_commands (ENetList * queue, ENetListIterator startComm
|
||||
static void
|
||||
enet_peer_reset_incoming_commands (ENetList * queue)
|
||||
{
|
||||
enet_peer_remove_incoming_commands(queue, enet_list_begin (queue), enet_list_end (queue));
|
||||
enet_peer_remove_incoming_commands(queue, enet_list_begin (queue), enet_list_end (queue), NULL);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -306,20 +317,19 @@ enet_peer_reset_queues (ENetPeer * peer)
|
||||
{
|
||||
ENetChannel * channel;
|
||||
|
||||
if (peer -> needsDispatch)
|
||||
if (peer -> flags & ENET_PEER_FLAG_NEEDS_DISPATCH)
|
||||
{
|
||||
enet_list_remove (& peer -> dispatchList);
|
||||
|
||||
peer -> needsDispatch = 0;
|
||||
peer -> flags &= ~ ENET_PEER_FLAG_NEEDS_DISPATCH;
|
||||
}
|
||||
|
||||
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 -> sentUnreliableCommands);
|
||||
enet_peer_reset_outgoing_commands (& peer -> outgoingReliableCommands);
|
||||
enet_peer_reset_outgoing_commands (& peer -> outgoingUnreliableCommands);
|
||||
enet_peer_reset_outgoing_commands (& peer -> outgoingCommands);
|
||||
enet_peer_reset_outgoing_commands (& peer -> outgoingSendReliableCommands);
|
||||
enet_peer_reset_incoming_commands (& peer -> dispatchedCommands);
|
||||
|
||||
if (peer -> channels != NULL && peer -> channelCount > 0)
|
||||
@@ -418,6 +428,7 @@ enet_peer_reset (ENetPeer * peer)
|
||||
peer -> outgoingUnsequencedGroup = 0;
|
||||
peer -> eventData = 0;
|
||||
peer -> totalWaitingData = 0;
|
||||
peer -> flags = 0;
|
||||
|
||||
memset (peer -> unsequencedWindow, 0, sizeof (peer -> unsequencedWindow));
|
||||
|
||||
@@ -560,6 +571,17 @@ 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
|
||||
@@ -570,9 +592,7 @@ void
|
||||
enet_peer_disconnect_later (ENetPeer * peer, enet_uint32 data)
|
||||
{
|
||||
if ((peer -> state == ENET_PEER_STATE_CONNECTED || peer -> state == ENET_PEER_STATE_DISCONNECT_LATER) &&
|
||||
! (enet_list_empty (& peer -> outgoingReliableCommands) &&
|
||||
enet_list_empty (& peer -> outgoingUnreliableCommands) &&
|
||||
enet_list_empty (& peer -> sentReliableCommands)))
|
||||
enet_peer_has_outgoing_commands (peer))
|
||||
{
|
||||
peer -> state = ENET_PEER_STATE_DISCONNECT_LATER;
|
||||
peer -> eventData = data;
|
||||
@@ -616,8 +636,6 @@ 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)
|
||||
@@ -628,36 +646,40 @@ enet_peer_setup_outgoing_command (ENetPeer * peer, ENetOutgoingCommand * outgoin
|
||||
outgoingCommand -> unreliableSequenceNumber = 0;
|
||||
}
|
||||
else
|
||||
if (outgoingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE)
|
||||
{
|
||||
++ channel -> outgoingReliableSequenceNumber;
|
||||
channel -> outgoingUnreliableSequenceNumber = 0;
|
||||
ENetChannel * channel = & peer -> channels [outgoingCommand -> command.header.channelID];
|
||||
|
||||
outgoingCommand -> reliableSequenceNumber = channel -> outgoingReliableSequenceNumber;
|
||||
outgoingCommand -> unreliableSequenceNumber = 0;
|
||||
}
|
||||
else
|
||||
if (outgoingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_FLAG_UNSEQUENCED)
|
||||
{
|
||||
++ peer -> outgoingUnsequencedGroup;
|
||||
if (outgoingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE)
|
||||
{
|
||||
++ channel -> outgoingReliableSequenceNumber;
|
||||
channel -> outgoingUnreliableSequenceNumber = 0;
|
||||
|
||||
outgoingCommand -> reliableSequenceNumber = 0;
|
||||
outgoingCommand -> unreliableSequenceNumber = 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;
|
||||
}
|
||||
}
|
||||
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)
|
||||
{
|
||||
@@ -668,15 +690,16 @@ 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)
|
||||
enet_list_insert (enet_list_end (& peer -> outgoingReliableCommands), outgoingCommand);
|
||||
if ((outgoingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE) != 0 &&
|
||||
outgoingCommand -> packet != NULL)
|
||||
enet_list_insert (enet_list_end (& peer -> outgoingSendReliableCommands), outgoingCommand);
|
||||
else
|
||||
enet_list_insert (enet_list_end (& peer -> outgoingUnreliableCommands), outgoingCommand);
|
||||
enet_list_insert (enet_list_end (& peer -> outgoingCommands), outgoingCommand);
|
||||
}
|
||||
|
||||
ENetOutgoingCommand *
|
||||
@@ -699,7 +722,7 @@ enet_peer_queue_outgoing_command (ENetPeer * peer, const ENetProtocol * command,
|
||||
}
|
||||
|
||||
void
|
||||
enet_peer_dispatch_incoming_unreliable_commands (ENetPeer * peer, ENetChannel * channel)
|
||||
enet_peer_dispatch_incoming_unreliable_commands (ENetPeer * peer, ENetChannel * channel, ENetIncomingCommand * queuedCommand)
|
||||
{
|
||||
ENetListIterator droppedCommand, startCommand, currentCommand;
|
||||
|
||||
@@ -724,11 +747,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 -> needsDispatch)
|
||||
if (! (peer -> flags & ENET_PEER_FLAG_NEEDS_DISPATCH))
|
||||
{
|
||||
enet_list_insert (enet_list_end (& peer -> host -> dispatchQueue), & peer -> dispatchList);
|
||||
|
||||
peer -> needsDispatch = 1;
|
||||
peer -> flags |= ENET_PEER_FLAG_NEEDS_DISPATCH;
|
||||
}
|
||||
|
||||
droppedCommand = currentCommand;
|
||||
@@ -752,11 +775,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 -> needsDispatch)
|
||||
if (! (peer -> flags & ENET_PEER_FLAG_NEEDS_DISPATCH))
|
||||
{
|
||||
enet_list_insert (enet_list_end (& peer -> host -> dispatchQueue), & peer -> dispatchList);
|
||||
|
||||
peer -> needsDispatch = 1;
|
||||
peer -> flags |= ENET_PEER_FLAG_NEEDS_DISPATCH;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -768,21 +791,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 -> needsDispatch)
|
||||
if (! (peer -> flags & ENET_PEER_FLAG_NEEDS_DISPATCH))
|
||||
{
|
||||
enet_list_insert (enet_list_end (& peer -> host -> dispatchQueue), & peer -> dispatchList);
|
||||
|
||||
peer -> needsDispatch = 1;
|
||||
peer -> flags |= ENET_PEER_FLAG_NEEDS_DISPATCH;
|
||||
}
|
||||
|
||||
droppedCommand = currentCommand;
|
||||
}
|
||||
|
||||
enet_peer_remove_incoming_commands (& channel -> incomingUnreliableCommands, enet_list_begin (& channel -> incomingUnreliableCommands), droppedCommand);
|
||||
enet_peer_remove_incoming_commands (& channel -> incomingUnreliableCommands, enet_list_begin (& channel -> incomingUnreliableCommands), droppedCommand, queuedCommand);
|
||||
}
|
||||
|
||||
void
|
||||
enet_peer_dispatch_incoming_reliable_commands (ENetPeer * peer, ENetChannel * channel)
|
||||
enet_peer_dispatch_incoming_reliable_commands (ENetPeer * peer, ENetChannel * channel, ENetIncomingCommand * queuedCommand)
|
||||
{
|
||||
ENetListIterator currentCommand;
|
||||
|
||||
@@ -809,15 +832,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 -> needsDispatch)
|
||||
if (! (peer -> flags & ENET_PEER_FLAG_NEEDS_DISPATCH))
|
||||
{
|
||||
enet_list_insert (enet_list_end (& peer -> host -> dispatchQueue), & peer -> dispatchList);
|
||||
|
||||
peer -> needsDispatch = 1;
|
||||
peer -> flags |= ENET_PEER_FLAG_NEEDS_DISPATCH;
|
||||
}
|
||||
|
||||
if (! enet_list_empty (& channel -> incomingUnreliableCommands))
|
||||
enet_peer_dispatch_incoming_unreliable_commands (peer, channel);
|
||||
enet_peer_dispatch_incoming_unreliable_commands (peer, channel, queuedCommand);
|
||||
}
|
||||
|
||||
ENetIncomingCommand *
|
||||
@@ -975,11 +998,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);
|
||||
enet_peer_dispatch_incoming_reliable_commands (peer, channel, incomingCommand);
|
||||
break;
|
||||
|
||||
default:
|
||||
enet_peer_dispatch_incoming_unreliable_commands (peer, channel);
|
||||
enet_peer_dispatch_incoming_unreliable_commands (peer, channel, incomingCommand);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
+303
-255
@@ -9,7 +9,7 @@
|
||||
#include "enet/time.h"
|
||||
#include "enet/enet.h"
|
||||
|
||||
static size_t commandSizes [ENET_PROTOCOL_COMMAND_COUNT] =
|
||||
static const 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 -> needsDispatch)
|
||||
if (! (peer -> flags & ENET_PEER_FLAG_NEEDS_DISPATCH))
|
||||
{
|
||||
enet_list_insert (enet_list_end (& host -> dispatchQueue), & peer -> dispatchList);
|
||||
|
||||
peer -> needsDispatch = 1;
|
||||
peer -> flags |= ENET_PEER_FLAG_NEEDS_DISPATCH;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 -> needsDispatch = 0;
|
||||
peer -> flags &= ~ ENET_PEER_FLAG_NEEDS_DISPATCH;
|
||||
|
||||
switch (peer -> state)
|
||||
{
|
||||
@@ -101,7 +101,7 @@ enet_protocol_dispatch_incoming_commands (ENetHost * host, ENetEvent * event)
|
||||
|
||||
if (! enet_list_empty (& peer -> dispatchedCommands))
|
||||
{
|
||||
peer -> needsDispatch = 1;
|
||||
peer -> flags |= ENET_PEER_FLAG_NEEDS_DISPATCH;
|
||||
|
||||
enet_list_insert (enet_list_end (& host -> dispatchQueue), & peer -> dispatchList);
|
||||
}
|
||||
@@ -159,13 +159,16 @@ enet_protocol_notify_disconnect (ENetHost * host, ENetPeer * peer, ENetEvent * e
|
||||
}
|
||||
|
||||
static void
|
||||
enet_protocol_remove_sent_unreliable_commands (ENetPeer * peer)
|
||||
enet_protocol_remove_sent_unreliable_commands (ENetPeer * peer, ENetList * sentUnreliableCommands)
|
||||
{
|
||||
ENetOutgoingCommand * outgoingCommand;
|
||||
|
||||
while (! enet_list_empty (& peer -> sentUnreliableCommands))
|
||||
if (enet_list_empty (sentUnreliableCommands))
|
||||
return;
|
||||
|
||||
do
|
||||
{
|
||||
outgoingCommand = (ENetOutgoingCommand *) enet_list_front (& peer -> sentUnreliableCommands);
|
||||
outgoingCommand = (ENetOutgoingCommand *) enet_list_front (sentUnreliableCommands);
|
||||
|
||||
enet_list_remove (& outgoingCommand -> outgoingCommandList);
|
||||
|
||||
@@ -182,7 +185,36 @@ enet_protocol_remove_sent_unreliable_commands (ENetPeer * peer)
|
||||
}
|
||||
|
||||
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
|
||||
@@ -206,21 +238,9 @@ enet_protocol_remove_sent_reliable_command (ENetPeer * peer, enet_uint16 reliabl
|
||||
|
||||
if (currentCommand == enet_list_end (& peer -> sentReliableCommands))
|
||||
{
|
||||
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;
|
||||
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);
|
||||
|
||||
wasSent = 0;
|
||||
}
|
||||
@@ -298,7 +318,7 @@ enet_protocol_handle_connect (ENetHost * host, ENetProtocolHeader * header, ENet
|
||||
}
|
||||
else
|
||||
if (currentPeer -> state != ENET_PEER_STATE_CONNECTING &&
|
||||
enet_address_equal (& currentPeer -> address, & host -> receivedAddress))
|
||||
enet_address_equal (& currentPeer -> address, & host -> receivedPeerAddress))
|
||||
{
|
||||
if (currentPeer -> connectID == command -> connect.connectID)
|
||||
return NULL;
|
||||
@@ -318,7 +338,9 @@ 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 -> mtu = host -> mtu;
|
||||
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);
|
||||
@@ -363,7 +385,8 @@ enet_protocol_handle_connect (ENetHost * host, ENetProtocolHeader * header, ENet
|
||||
if (mtu > ENET_PROTOCOL_MAXIMUM_MTU)
|
||||
mtu = ENET_PROTOCOL_MAXIMUM_MTU;
|
||||
|
||||
peer -> mtu = mtu;
|
||||
if (mtu < peer -> mtu)
|
||||
peer -> mtu = mtu;
|
||||
|
||||
if (host -> outgoingBandwidth == 0 &&
|
||||
peer -> incomingBandwidth == 0)
|
||||
@@ -530,7 +553,8 @@ enet_protocol_handle_send_fragment (ENetHost * host, ENetPeer * peer, const ENet
|
||||
|
||||
fragmentLength = ENET_NET_TO_HOST_16 (command -> sendFragment.dataLength);
|
||||
* currentData += fragmentLength;
|
||||
if (fragmentLength > host -> maximumPacketSize ||
|
||||
if (fragmentLength <= 0 ||
|
||||
fragmentLength > host -> maximumPacketSize ||
|
||||
* currentData < host -> receivedData ||
|
||||
* currentData > & host -> receivedData [host -> receivedDataLength])
|
||||
return -1;
|
||||
@@ -554,6 +578,7 @@ 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;
|
||||
@@ -613,7 +638,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);
|
||||
enet_peer_dispatch_incoming_reliable_commands (peer, channel, NULL);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -731,7 +756,7 @@ enet_protocol_handle_send_unreliable_fragment (ENetHost * host, ENetPeer * peer,
|
||||
fragmentLength);
|
||||
|
||||
if (startCommand -> fragmentsRemaining <= 0)
|
||||
enet_peer_dispatch_incoming_unreliable_commands (peer, channel);
|
||||
enet_peer_dispatch_incoming_unreliable_commands (peer, channel, NULL);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -841,42 +866,53 @@ 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);
|
||||
|
||||
enet_peer_throttle (peer, roundTripTime);
|
||||
|
||||
peer -> roundTripTimeVariance -= peer -> roundTripTimeVariance / 4;
|
||||
|
||||
if (roundTripTime >= peer -> roundTripTime)
|
||||
if (peer -> lastReceiveTime > 0)
|
||||
{
|
||||
peer -> roundTripTime += (roundTripTime - peer -> roundTripTime) / 8;
|
||||
peer -> roundTripTimeVariance += (roundTripTime - peer -> roundTripTime) / 4;
|
||||
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;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
peer -> roundTripTime -= (peer -> roundTripTime - roundTripTime) / 8;
|
||||
peer -> roundTripTimeVariance += (peer -> roundTripTime - roundTripTime) / 4;
|
||||
peer -> roundTripTime = roundTripTime;
|
||||
peer -> roundTripTimeVariance = (roundTripTime + 1) / 2;
|
||||
}
|
||||
|
||||
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 = peer -> highestRoundTripTimeVariance;
|
||||
peer -> lastRoundTripTimeVariance = ENET_MAX (peer -> highestRoundTripTimeVariance, 1);
|
||||
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);
|
||||
@@ -898,9 +934,7 @@ enet_protocol_handle_acknowledge (ENetHost * host, ENetEvent * event, ENetPeer *
|
||||
break;
|
||||
|
||||
case ENET_PEER_STATE_DISCONNECT_LATER:
|
||||
if (enet_list_empty (& peer -> outgoingReliableCommands) &&
|
||||
enet_list_empty (& peer -> outgoingUnreliableCommands) &&
|
||||
enet_list_empty (& peer -> sentReliableCommands))
|
||||
if (! enet_peer_has_outgoing_commands (peer))
|
||||
enet_peer_disconnect (peer, peer -> eventData);
|
||||
break;
|
||||
|
||||
@@ -1051,7 +1085,8 @@ enet_protocol_handle_incoming_commands (ENetHost * host, ENetEvent * event)
|
||||
|
||||
if (peer != NULL)
|
||||
{
|
||||
memcpy(& peer -> address, & host -> receivedAddress, sizeof (host -> receivedAddress));
|
||||
memcpy(& peer -> address, & host -> receivedPeerAddress, sizeof (host -> receivedPeerAddress));
|
||||
memcpy(& peer -> localAddress, & host -> receivedLocalAddress, sizeof (host -> receivedLocalAddress));
|
||||
peer -> incomingDataTotal += host -> receivedDataLength;
|
||||
}
|
||||
|
||||
@@ -1202,10 +1237,14 @@ 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);
|
||||
|
||||
if (receivedLength == -2)
|
||||
continue;
|
||||
|
||||
if (receivedLength < 0)
|
||||
return -1;
|
||||
|
||||
@@ -1249,7 +1288,7 @@ enet_protocol_receive_incoming_commands (ENetHost * host, ENetEvent * event)
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1269,7 +1308,7 @@ enet_protocol_send_acknowledgements (ENetHost * host, ENetPeer * peer)
|
||||
buffer >= & host -> buffers [sizeof (host -> buffers) / sizeof (ENetBuffer)] ||
|
||||
peer -> mtu - host -> packetSize < sizeof (ENetProtocolAcknowledge))
|
||||
{
|
||||
host -> continueSending = 1;
|
||||
peer -> flags |= ENET_PEER_FLAG_CONTINUE_SENDING;
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -1305,115 +1344,16 @@ 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;
|
||||
ENetListIterator currentCommand, insertPosition, insertSendReliablePosition;
|
||||
enet_uint32 roundTripTimeout;
|
||||
|
||||
currentCommand = enet_list_begin (& peer -> sentReliableCommands);
|
||||
insertPosition = enet_list_begin (& peer -> outgoingReliableCommands);
|
||||
insertPosition = enet_list_begin (& peer -> outgoingCommands);
|
||||
insertSendReliablePosition = enet_list_begin (& peer -> outgoingSendReliableCommands);
|
||||
|
||||
while (currentCommand != enet_list_end (& peer -> sentReliableCommands))
|
||||
{
|
||||
@@ -1430,7 +1370,7 @@ enet_protocol_check_timeouts (ENetHost * host, ENetPeer * peer, ENetEvent * even
|
||||
|
||||
if (peer -> earliestTimeout != 0 &&
|
||||
(ENET_TIME_DIFFERENCE (host -> serviceTime, peer -> earliestTimeout) >= peer -> timeoutMaximum ||
|
||||
(outgoingCommand -> roundTripTimeout >= outgoingCommand -> roundTripTimeoutLimit &&
|
||||
((1U << (outgoingCommand -> sendAttempts - 1)) >= peer -> timeoutLimit &&
|
||||
ENET_TIME_DIFFERENCE (host -> serviceTime, peer -> earliestTimeout) >= peer -> timeoutMinimum)))
|
||||
{
|
||||
enet_protocol_notify_disconnect (host, peer, event);
|
||||
@@ -1438,14 +1378,23 @@ enet_protocol_check_timeouts (ENetHost * host, ENetPeer * peer, ENetEvent * even
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (outgoingCommand -> packet != NULL)
|
||||
peer -> reliableDataInTransit -= outgoingCommand -> fragmentLength;
|
||||
|
||||
++ peer -> packetsLost;
|
||||
|
||||
outgoingCommand -> roundTripTimeout *= 2;
|
||||
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;
|
||||
|
||||
enet_list_insert (insertPosition, enet_list_remove (& outgoingCommand -> outgoingCommandList));
|
||||
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));
|
||||
|
||||
if (currentCommand == enet_list_begin (& peer -> sentReliableCommands) &&
|
||||
! enet_list_empty (& peer -> sentReliableCommands))
|
||||
@@ -1460,61 +1409,79 @@ enet_protocol_check_timeouts (ENetHost * host, ENetPeer * peer, ENetEvent * even
|
||||
}
|
||||
|
||||
static int
|
||||
enet_protocol_send_reliable_outgoing_commands (ENetHost * host, ENetPeer * peer)
|
||||
enet_protocol_check_outgoing_commands (ENetHost * host, ENetPeer * peer, ENetList * sentUnreliableCommands)
|
||||
{
|
||||
ENetProtocol * command = & host -> commands [host -> commandCount];
|
||||
ENetBuffer * buffer = & host -> buffers [host -> bufferCount];
|
||||
ENetOutgoingCommand * outgoingCommand;
|
||||
ENetListIterator currentCommand;
|
||||
ENetChannel *channel;
|
||||
enet_uint16 reliableWindow;
|
||||
ENetListIterator currentCommand, currentSendReliableCommand;
|
||||
ENetChannel *channel = NULL;
|
||||
enet_uint16 reliableWindow = 0;
|
||||
size_t commandSize;
|
||||
int windowExceeded = 0, windowWrap = 0, canPing = 1;
|
||||
int windowWrap = 0, canPing = 1;
|
||||
|
||||
currentCommand = enet_list_begin (& peer -> outgoingReliableCommands);
|
||||
|
||||
while (currentCommand != enet_list_end (& peer -> outgoingReliableCommands))
|
||||
currentCommand = enet_list_begin (& peer -> outgoingCommands);
|
||||
currentSendReliableCommand = enet_list_begin (& peer -> outgoingSendReliableCommands);
|
||||
|
||||
for (;;)
|
||||
{
|
||||
outgoingCommand = (ENetOutgoingCommand *) currentCommand;
|
||||
if (currentCommand != enet_list_end (& peer -> outgoingCommands))
|
||||
{
|
||||
outgoingCommand = (ENetOutgoingCommand *) currentCommand;
|
||||
|
||||
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)
|
||||
{
|
||||
currentCommand = enet_list_next (currentCommand);
|
||||
|
||||
continue;
|
||||
}
|
||||
if (currentSendReliableCommand != enet_list_end (& peer -> outgoingSendReliableCommands) &&
|
||||
ENET_TIME_LESS (((ENetOutgoingCommand *) currentSendReliableCommand) -> queueTime, outgoingCommand -> queueTime))
|
||||
goto useSendReliableCommand;
|
||||
|
||||
currentCommand = enet_list_next (currentCommand);
|
||||
}
|
||||
|
||||
if (outgoingCommand -> packet != NULL)
|
||||
else
|
||||
if (currentSendReliableCommand != enet_list_end (& peer -> outgoingSendReliableCommands))
|
||||
{
|
||||
if (! windowExceeded)
|
||||
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)
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
if (outgoingCommand -> packet != NULL)
|
||||
{
|
||||
enet_uint32 windowSize = (peer -> packetThrottle * peer -> windowSize) / ENET_PEER_PACKET_THROTTLE_SCALE;
|
||||
|
||||
|
||||
if (peer -> reliableDataInTransit + outgoingCommand -> fragmentLength > ENET_MAX (windowSize, peer -> mtu))
|
||||
windowExceeded = 1;
|
||||
}
|
||||
if (windowExceeded)
|
||||
{
|
||||
currentCommand = enet_list_next (currentCommand);
|
||||
{
|
||||
currentSendReliableCommand = enet_list_end (& peer -> outgoingSendReliableCommands);
|
||||
|
||||
continue;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
canPing = 0;
|
||||
}
|
||||
|
||||
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)] ||
|
||||
@@ -1522,40 +1489,84 @@ enet_protocol_send_reliable_outgoing_commands (ENetHost * host, ENetPeer * peer)
|
||||
(outgoingCommand -> packet != NULL &&
|
||||
(enet_uint16) (peer -> mtu - host -> packetSize) < (enet_uint16) (commandSize + outgoingCommand -> fragmentLength)))
|
||||
{
|
||||
host -> continueSending = 1;
|
||||
|
||||
peer -> flags |= ENET_PEER_FLAG_CONTINUE_SENDING;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
currentCommand = enet_list_next (currentCommand);
|
||||
|
||||
if (channel != NULL && outgoingCommand -> sendAttempts < 1)
|
||||
if (outgoingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE)
|
||||
{
|
||||
channel -> usedReliableWindows |= 1 << reliableWindow;
|
||||
++ channel -> reliableWindows [reliableWindow];
|
||||
}
|
||||
if (channel != NULL && outgoingCommand -> sendAttempts < 1)
|
||||
{
|
||||
channel -> usedReliableWindows |= 1 << reliableWindow;
|
||||
++ channel -> reliableWindows [reliableWindow];
|
||||
}
|
||||
|
||||
++ outgoingCommand -> sendAttempts;
|
||||
|
||||
if (outgoingCommand -> roundTripTimeout == 0)
|
||||
++ 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;
|
||||
}
|
||||
else
|
||||
{
|
||||
outgoingCommand -> roundTripTimeout = peer -> roundTripTime + 4 * peer -> roundTripTimeVariance;
|
||||
outgoingCommand -> roundTripTimeoutLimit = peer -> timeoutLimit * outgoingCommand -> roundTripTimeout;
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
@@ -1567,9 +1578,10 @@ enet_protocol_send_reliable_outgoing_commands (ENetHost * host, ENetPeer * peer)
|
||||
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;
|
||||
|
||||
@@ -1580,6 +1592,11 @@ enet_protocol_send_reliable_outgoing_commands (ENetHost * host, ENetPeer * peer)
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -1588,22 +1605,24 @@ enet_protocol_send_outgoing_commands (ENetHost * host, ENetEvent * event, int ch
|
||||
{
|
||||
enet_uint8 headerData [sizeof (ENetProtocolHeader) + sizeof (enet_uint32)];
|
||||
ENetProtocolHeader * header = (ENetProtocolHeader *) headerData;
|
||||
ENetPeer * currentPeer;
|
||||
int sentLength;
|
||||
int sentLength = 0;
|
||||
size_t shouldCompress = 0;
|
||||
|
||||
host -> continueSending = 1;
|
||||
ENetList sentUnreliableCommands;
|
||||
|
||||
while (host -> continueSending)
|
||||
for (host -> continueSending = 0,
|
||||
currentPeer = host -> peers;
|
||||
enet_list_clear (& sentUnreliableCommands);
|
||||
|
||||
for (int sendPass = 0, continueSending = 0; sendPass <= continueSending; ++ sendPass)
|
||||
for (ENetPeer * currentPeer = host -> peers;
|
||||
currentPeer < & host -> peers [host -> peerCount];
|
||||
++ currentPeer)
|
||||
{
|
||||
if (currentPeer -> state == ENET_PEER_STATE_DISCONNECTED ||
|
||||
currentPeer -> state == ENET_PEER_STATE_ZOMBIE)
|
||||
currentPeer -> state == ENET_PEER_STATE_ZOMBIE ||
|
||||
(sendPass > 0 && ! (currentPeer -> flags & ENET_PEER_FLAG_CONTINUE_SENDING)))
|
||||
continue;
|
||||
|
||||
currentPeer -> flags &= ~ ENET_PEER_FLAG_CONTINUE_SENDING;
|
||||
|
||||
host -> headerFlags = 0;
|
||||
host -> commandCount = 0;
|
||||
host -> bufferCount = 1;
|
||||
@@ -1620,24 +1639,22 @@ enet_protocol_send_outgoing_commands (ENetHost * host, ENetEvent * event, int ch
|
||||
if (event != NULL && event -> type != ENET_EVENT_TYPE_NONE)
|
||||
return 1;
|
||||
else
|
||||
continue;
|
||||
goto nextPeer;
|
||||
}
|
||||
|
||||
if ((enet_list_empty (& currentPeer -> outgoingReliableCommands) ||
|
||||
enet_protocol_send_reliable_outgoing_commands (host, currentPeer)) &&
|
||||
if (((enet_list_empty (& currentPeer -> outgoingCommands) &&
|
||||
enet_list_empty (& currentPeer -> outgoingSendReliableCommands)) ||
|
||||
enet_protocol_check_outgoing_commands (host, currentPeer, & sentUnreliableCommands)) &&
|
||||
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_send_reliable_outgoing_commands (host, currentPeer);
|
||||
enet_protocol_check_outgoing_commands (host, currentPeer, & sentUnreliableCommands);
|
||||
}
|
||||
|
||||
if (! enet_list_empty (& currentPeer -> outgoingUnreliableCommands))
|
||||
enet_protocol_send_unreliable_outgoing_commands (host, currentPeer);
|
||||
|
||||
if (host -> commandCount == 0)
|
||||
continue;
|
||||
goto nextPeer;
|
||||
|
||||
if (currentPeer -> packetLossEpoch == 0)
|
||||
currentPeer -> packetLossEpoch = host -> serviceTime;
|
||||
@@ -1648,21 +1665,11 @@ 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/%u outgoing, %u/%u incoming\n", currentPeer -> incomingPeerID, currentPeer -> packetLoss / (float) ENET_PEER_PACKET_LOSS_SCALE, currentPeer -> packetLossVariance / (float) ENET_PEER_PACKET_LOSS_SCALE, currentPeer -> roundTripTime, currentPeer -> roundTripTimeVariance, currentPeer -> packetThrottle / (float) ENET_PEER_PACKET_THROTTLE_SCALE, enet_list_size (& currentPeer -> outgoingReliableCommands), enet_list_size (& currentPeer -> outgoingUnreliableCommands), currentPeer -> channels != NULL ? enet_list_size (& currentPeer -> channels -> incomingReliableCommands) : 0, currentPeer -> channels != NULL ? enet_list_size (& currentPeer -> channels -> incomingUnreliableCommands) : 0);
|
||||
printf ("peer %u: %f%%+-%f%% packet loss, %u+-%u ms round trip time, %f%% throttle, %u 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);
|
||||
#endif
|
||||
|
||||
currentPeer -> packetLossVariance -= currentPeer -> packetLossVariance / 4;
|
||||
|
||||
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 -> packetLossVariance = (currentPeer -> packetLossVariance * 3 + ENET_DIFFERENCE (packetLoss, currentPeer -> packetLoss)) / 4;
|
||||
currentPeer -> packetLoss = (currentPeer -> packetLoss * 7 + packetLoss) / 8;
|
||||
|
||||
currentPeer -> packetLossEpoch = host -> serviceTime;
|
||||
currentPeer -> packetsSent = 0;
|
||||
@@ -1718,26 +1725,61 @@ enet_protocol_send_outgoing_commands (ENetHost * host, ENetEvent * event, int ch
|
||||
|
||||
currentPeer -> lastSendTime = host -> serviceTime;
|
||||
|
||||
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.
|
||||
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.
|
||||
// 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 -> buffers, host -> bufferCount);
|
||||
sentLength = enet_socket_send (host -> socket, & currentPeer -> address,
|
||||
host -> wildcardBind ? (& currentPeer -> localAddress) : NULL,
|
||||
host -> buffers, host -> bufferCount);
|
||||
|
||||
enet_protocol_remove_sent_unreliable_commands (currentPeer);
|
||||
enet_protocol_remove_sent_unreliable_commands (currentPeer, & sentUnreliableCommands);
|
||||
|
||||
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
|
||||
@@ -1895,14 +1937,20 @@ 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, ENET_TIME_DIFFERENCE (timeout, host -> serviceTime) / 10) != 0)
|
||||
if (enet_socket_wait (host -> socket, & waitCondition, waitTime) != 0)
|
||||
return -1;
|
||||
}
|
||||
while (waitCondition & ENET_SOCKET_WAIT_INTERRUPT);
|
||||
|
||||
@@ -1,14 +1,23 @@
|
||||
/**
|
||||
/**
|
||||
@file unix.c
|
||||
@brief ENet Unix system specific functions
|
||||
*/
|
||||
#ifndef _WIN32
|
||||
#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
|
||||
|
||||
#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>
|
||||
@@ -20,8 +29,11 @@
|
||||
#include "enet/enet.h"
|
||||
|
||||
#if defined(__APPLE__)
|
||||
#ifdef HAS_POLL
|
||||
#undef HAS_POLL
|
||||
#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
|
||||
#endif
|
||||
#ifndef HAS_FCNTL
|
||||
#define HAS_FCNTL 1
|
||||
@@ -45,14 +57,9 @@
|
||||
#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
|
||||
// PS Vita: No support for ancillary data or advanced message control
|
||||
#ifndef NO_MSGAPI
|
||||
#define NO_MSGAPI 1
|
||||
#endif
|
||||
#ifndef HAS_INET_PTON
|
||||
#define HAS_INET_PTON 1
|
||||
@@ -60,9 +67,6 @@
|
||||
#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
|
||||
@@ -72,10 +76,104 @@
|
||||
#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
|
||||
@@ -87,10 +185,10 @@
|
||||
#endif
|
||||
|
||||
#ifdef HAS_POLL
|
||||
#include <sys/poll.h>
|
||||
#include <poll.h>
|
||||
#endif
|
||||
|
||||
#ifndef HAS_SOCKLEN_T
|
||||
#if !defined(HAS_SOCKLEN_T) && !defined(__socklen_t_defined) && !defined(__HAIKU__)
|
||||
typedef int socklen_t;
|
||||
#endif
|
||||
|
||||
@@ -119,9 +217,9 @@ enet_uint32
|
||||
enet_host_random_seed (void)
|
||||
{
|
||||
struct timeval timeVal;
|
||||
|
||||
|
||||
gettimeofday (& timeVal, NULL);
|
||||
|
||||
|
||||
return (timeVal.tv_sec * 1000) ^ (timeVal.tv_usec / 1000);
|
||||
}
|
||||
|
||||
@@ -141,10 +239,31 @@ 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)
|
||||
{
|
||||
@@ -161,6 +280,7 @@ 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;
|
||||
@@ -169,6 +289,31 @@ 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;
|
||||
@@ -185,12 +330,14 @@ 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;
|
||||
@@ -224,9 +371,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;
|
||||
}
|
||||
|
||||
@@ -255,7 +402,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);
|
||||
@@ -264,7 +411,51 @@ enet_socket_listen (ENetSocket socket, int backlog)
|
||||
ENetSocket
|
||||
enet_socket_create (int af, ENetSocketType type)
|
||||
{
|
||||
return socket (af, 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));
|
||||
}
|
||||
#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;
|
||||
}
|
||||
|
||||
int
|
||||
@@ -275,7 +466,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) & ~O_NONBLOCK));
|
||||
result = fcntl (socket, F_SETFL, (value ? O_NONBLOCK : 0) | (fcntl (socket, F_GETFL, 0) & ~O_NONBLOCK));
|
||||
#else
|
||||
#ifdef HAS_IOCTL
|
||||
result = ioctl (socket, FIONBIO, & value);
|
||||
@@ -297,6 +488,7 @@ 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;
|
||||
@@ -314,6 +506,7 @@ 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));
|
||||
@@ -324,15 +517,15 @@ 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));
|
||||
#else
|
||||
#endif
|
||||
#ifdef IP_TOS
|
||||
// UNIX - IPv4
|
||||
value = value ? 46 << 2 : 0; // DSCP: Expedited Forwarding
|
||||
value = value ? (46 << 2 | 0x01) : 0; // DSCP: Expedited Forwarding + ECT(1) (L4S)
|
||||
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
|
||||
value = value ? (46 << 2 | 0x01): 0; // DSCP: Expedited Forwarding + ECT(1) (L4S)
|
||||
result = setsockopt (socket, IPPROTO_IPV6, IPV6_TCLASS, (char *) & value, sizeof (int));
|
||||
#endif
|
||||
#ifdef SO_PRIORITY
|
||||
@@ -340,7 +533,10 @@ 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
|
||||
#endif /* SO_NET_SERVICE_TYPE */
|
||||
break;
|
||||
|
||||
case ENET_SOCKOPT_TTL:
|
||||
result = setsockopt (socket, IPPROTO_IP, IP_TTL, (char *) & value, sizeof (int));
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -361,6 +557,11 @@ 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;
|
||||
}
|
||||
@@ -387,10 +588,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;
|
||||
|
||||
@@ -412,30 +613,31 @@ 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)
|
||||
{
|
||||
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++)
|
||||
{
|
||||
@@ -448,35 +650,108 @@ enet_socket_send (ENetSocket socket,
|
||||
sendBuffer = buffers[0].data;
|
||||
sendLength = buffers[0].dataLength;
|
||||
}
|
||||
|
||||
|
||||
sentLength = sendto (socket, sendBuffer, sendLength, MSG_NOSIGNAL,
|
||||
(struct sockaddr *) & address -> address, address -> addressLength);
|
||||
|
||||
(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)
|
||||
{
|
||||
msgHdr.msg_name = (void*) & address -> address;
|
||||
msgHdr.msg_namelen = address -> addressLength;
|
||||
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));
|
||||
}
|
||||
#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)
|
||||
{
|
||||
if (errno == EWOULDBLOCK)
|
||||
return 0;
|
||||
switch (errno)
|
||||
{
|
||||
case EWOULDBLOCK:
|
||||
return 0;
|
||||
|
||||
return -1;
|
||||
// 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;
|
||||
@@ -484,7 +759,8 @@ enet_socket_send (ENetSocket socket,
|
||||
|
||||
int
|
||||
enet_socket_receive (ENetSocket socket,
|
||||
ENetAddress * address,
|
||||
ENetAddress * peerAddress,
|
||||
ENetAddress * localAddress,
|
||||
ENetBuffer * buffers,
|
||||
size_t bufferCount)
|
||||
{
|
||||
@@ -492,33 +768,36 @@ enet_socket_receive (ENetSocket socket,
|
||||
|
||||
#ifdef NO_MSGAPI
|
||||
// This will ONLY work with a single buffer!
|
||||
|
||||
address -> addressLength = sizeof (address -> address);
|
||||
|
||||
peerAddress -> addressLength = sizeof (peerAddress -> address);
|
||||
recvLength = recvfrom (socket, buffers[0].data, buffers[0].dataLength, MSG_NOSIGNAL,
|
||||
(struct sockaddr *) & address -> address, & address -> addressLength);
|
||||
|
||||
(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 = & address -> address;
|
||||
msgHdr.msg_namelen = sizeof (address -> address);
|
||||
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);
|
||||
|
||||
@@ -529,15 +808,66 @@ 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 -1;
|
||||
return -2;
|
||||
#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
|
||||
}
|
||||
@@ -559,7 +889,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;
|
||||
|
||||
@@ -569,7 +899,18 @@ 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)
|
||||
{
|
||||
@@ -590,7 +931,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;
|
||||
|
||||
@@ -622,7 +963,7 @@ enet_socket_wait (ENetSocket socket, enet_uint32 * condition, enet_uint32 timeou
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -642,4 +983,3 @@ enet_socket_wait (ENetSocket socket, enet_uint32 * condition, enet_uint32 timeou
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1,26 +1,57 @@
|
||||
/**
|
||||
/**
|
||||
@file win32.c
|
||||
@brief ENet Win32 system specific functions
|
||||
*/
|
||||
#ifdef _WIN32
|
||||
#if defined(_WIN32) && !defined(NXDK)
|
||||
|
||||
#define ENET_BUILDING_LIB 1
|
||||
#include "enet/enet.h"
|
||||
#include <windows.h>
|
||||
#include <mmsystem.h>
|
||||
#include <mswsock.h>
|
||||
#ifndef HAS_QOS_FLOWID
|
||||
typedef UINT32 QOS_FLOWID;
|
||||
#endif
|
||||
#ifndef HAS_PQOS_FLOWID
|
||||
typedef UINT32 *PQOS_FLOWID;
|
||||
#endif
|
||||
#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;
|
||||
|
||||
@@ -28,48 +59,72 @@ enet_initialize (void)
|
||||
HIBYTE (wsaData.wVersion) != 0)
|
||||
{
|
||||
WSACleanup ();
|
||||
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
timeBeginPeriod (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");
|
||||
|
||||
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)
|
||||
{
|
||||
QOSCloseHandle(qosHandle);
|
||||
pfnQOSCloseHandle(qosHandle);
|
||||
qosHandle = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
timeEndPeriod (1);
|
||||
if (QwaveLibraryHandle != NULL) {
|
||||
pfnQOSCreateHandle = NULL;
|
||||
pfnQOSCloseHandle = NULL;
|
||||
pfnQOSAddSocketToFlow = NULL;
|
||||
|
||||
FreeLibrary(QwaveLibraryHandle);
|
||||
QwaveLibraryHandle = NULL;
|
||||
}
|
||||
#endif
|
||||
WSACleanup ();
|
||||
}
|
||||
|
||||
enet_uint32
|
||||
enet_host_random_seed (void)
|
||||
{
|
||||
return (enet_uint32) timeGetTime ();
|
||||
return (enet_uint32) GetTickCount ();
|
||||
}
|
||||
|
||||
enet_uint32
|
||||
enet_time_get (void)
|
||||
{
|
||||
return (enet_uint32) timeGetTime () - timeBase;
|
||||
return (enet_uint32) GetTickCount () - timeBase;
|
||||
}
|
||||
|
||||
void
|
||||
enet_time_set (enet_uint32 newTimeBase)
|
||||
{
|
||||
timeBase = (enet_uint32) timeGetTime () - newTimeBase;
|
||||
timeBase = (enet_uint32) GetTickCount () - newTimeBase;
|
||||
}
|
||||
|
||||
int
|
||||
@@ -135,6 +190,28 @@ 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)
|
||||
{
|
||||
@@ -151,9 +228,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;
|
||||
}
|
||||
|
||||
@@ -191,7 +268,46 @@ enet_socket_listen (ENetSocket socket, int backlog)
|
||||
ENetSocket
|
||||
enet_socket_create (int af, ENetSocketType type)
|
||||
{
|
||||
return socket (af, 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
|
||||
@@ -233,30 +349,38 @@ 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 (!QOSCreateHandle(&qosVersion, &qosHandle))
|
||||
if (pfnQOSCreateHandle == NULL || !pfnQOSCreateHandle(&qosVersion, &qosHandle))
|
||||
{
|
||||
qosHandle = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
}
|
||||
else if (qosHandle != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
QOSCloseHandle(qosHandle);
|
||||
pfnQOSCloseHandle(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;
|
||||
}
|
||||
@@ -274,6 +398,11 @@ 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;
|
||||
}
|
||||
@@ -300,10 +429,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;
|
||||
|
||||
@@ -325,40 +454,159 @@ 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)
|
||||
{
|
||||
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
|
||||
QOSAddSocketToFlow(qosHandle,
|
||||
socket,
|
||||
(struct sockaddr *)&address->address,
|
||||
QOSTrafficTypeControl,
|
||||
QOS_NON_ADAPTIVE_FLOW,
|
||||
&qosFlowId);
|
||||
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));
|
||||
}
|
||||
|
||||
// Even if we failed, don't try again
|
||||
qosAddedFlow = TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
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)
|
||||
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 (WSAGetLastError () == WSAEWOULDBLOCK)
|
||||
return 0;
|
||||
switch (WSAGetLastError ())
|
||||
{
|
||||
case WSAEWOULDBLOCK:
|
||||
return 0;
|
||||
|
||||
return -1;
|
||||
// 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 (int) sentLength;
|
||||
@@ -366,39 +614,69 @@ enet_socket_send (ENetSocket socket,
|
||||
|
||||
int
|
||||
enet_socket_receive (ENetSocket socket,
|
||||
ENetAddress * address,
|
||||
ENetAddress * peerAddress,
|
||||
ENetAddress * localAddress,
|
||||
ENetBuffer * buffers,
|
||||
size_t bufferCount)
|
||||
{
|
||||
DWORD flags = 0,
|
||||
recvLength;
|
||||
|
||||
if (address != NULL)
|
||||
address -> addressLength = sizeof (address -> address);
|
||||
DWORD recvLength;
|
||||
WSAMSG msg = { 0 };
|
||||
char controlBufData[1024];
|
||||
|
||||
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)
|
||||
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 ())
|
||||
{
|
||||
case WSAEWOULDBLOCK:
|
||||
case WSAECONNRESET:
|
||||
return 0;
|
||||
case WSAEMSGSIZE:
|
||||
return -2;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (flags & MSG_PARTIAL)
|
||||
return -1;
|
||||
if (msg.dwFlags & MSG_PARTIAL)
|
||||
return -2;
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
@@ -419,10 +697,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);
|
||||
|
||||
@@ -444,12 +722,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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user