Compare commits
182 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 | |||
| 9bf55a3433 | |||
| 224f31101f | |||
| 22272e29f9 | |||
| 5b93d08fa5 | |||
| c25b57b2c1 | |||
| f89e5986d0 | |||
| 5c96da29c2 | |||
| bb14921419 | |||
| 67cee4803a | |||
| 007b7d2a3f | |||
| 92bf2d8256 | |||
| 33c7d6903e | |||
| 6991632abf | |||
| d988023971 | |||
| b4c427059a | |||
| 637cd52e96 | |||
| 512b3f26f9 | |||
| 6537dc81f3 | |||
| 5503534362 | |||
| 93b080b053 | |||
| cf38f85e08 | |||
| e770a52bca | |||
| 0eaf48eeb0 | |||
| b8713bdf88 | |||
| e2ef83927d | |||
| cea2c5be9f | |||
| 295456fba9 | |||
| 219c625c74 | |||
| 335715309c | |||
| 2e1c6bceea | |||
| 42891f6919 | |||
| eb38c3c737 | |||
| 39a72ab199 | |||
| 67f964c2ad | |||
| a84c120eff | |||
| 6cc8cc8a26 | |||
| 9d9ba122d4 | |||
| 90560cd471 | |||
| 0891c520d2 | |||
| 5f5e977eef | |||
| 3ae5af4548 | |||
| e33ca1dc47 | |||
| f46fee0acc | |||
| 7546b505c1 | |||
| 2bc07bb50d | |||
| a602abf244 | |||
| 167f41aa2b | |||
| b2ee3b7b48 | |||
| 8b24595dbd | |||
| b3e34fa1db | |||
| 4f7ef11c23 | |||
| a39d3bb49c | |||
| ae9002fe19 | |||
| 4d1067179b | |||
| 00ccd3bd3f | |||
| 809a1d15b6 | |||
| 5f476546ed | |||
| f7c46f03fd | |||
| 7c27a5d5f8 | |||
| 9b06a12e71 | |||
| 8df6e58c5f | |||
| b574c946d8 | |||
| 4d2694d74e | |||
| c8fa0aeea4 | |||
| 2fb98f9b02 | |||
| 6ef4e7d277 | |||
| d85a037ec4 | |||
| 99004c45ac | |||
| 736474ca83 | |||
| 9c4d9953ac | |||
| 6f287186d8 | |||
| 379290acd5 | |||
| 127643fae4 | |||
| 98219eb50d | |||
| b14c7e99e0 | |||
| 464e883f04 | |||
| 9895a4f110 | |||
| 518144338d | |||
| 734a630bed | |||
| ea8d41f65c | |||
| 73c930881f | |||
| 5721b667f2 | |||
| c58ec4cc44 | |||
| b3de8a29c4 | |||
| 259376b214 | |||
| 01416f5850 | |||
| 272d4432f8 |
@@ -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 }}
|
||||
+121
@@ -0,0 +1,121 @@
|
||||
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)
|
||||
include(CheckTypeSize)
|
||||
check_function_exists("fcntl" HAS_FCNTL)
|
||||
check_function_exists("ioctl" HAS_IOCTL)
|
||||
check_function_exists("poll" HAS_POLL)
|
||||
check_function_exists("getaddrinfo" HAS_GETADDRINFO)
|
||||
check_function_exists("getnameinfo" HAS_GETNAMEINFO)
|
||||
check_function_exists("gethostbyname_r" HAS_GETHOSTBYNAME_R)
|
||||
check_function_exists("gethostbyaddr_r" HAS_GETHOSTBYADDR_R)
|
||||
check_function_exists("inet_pton" HAS_INET_PTON)
|
||||
check_function_exists("inet_ntop" HAS_INET_NTOP)
|
||||
check_struct_has_member("struct msghdr" "msg_flags" "sys/types.h;sys/socket.h" HAS_MSGHDR_FLAGS)
|
||||
set(CMAKE_EXTRA_INCLUDE_FILES "sys/types.h" "sys/socket.h")
|
||||
check_type_size("socklen_t" HAS_SOCKLEN_T BUILTIN_TYPES_ONLY)
|
||||
unset(CMAKE_EXTRA_INCLUDE_FILES)
|
||||
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()
|
||||
if(HAS_IOCTL)
|
||||
add_definitions(-DHAS_IOCTL=1)
|
||||
endif()
|
||||
if(HAS_POLL)
|
||||
add_definitions(-DHAS_POLL=1)
|
||||
endif()
|
||||
if(HAS_GETNAMEINFO)
|
||||
add_definitions(-DHAS_GETNAMEINFO=1)
|
||||
endif()
|
||||
if(HAS_GETADDRINFO)
|
||||
add_definitions(-DHAS_GETADDRINFO=1)
|
||||
endif()
|
||||
if(HAS_GETHOSTBYNAME_R)
|
||||
add_definitions(-DHAS_GETHOSTBYNAME_R=1)
|
||||
endif()
|
||||
if(HAS_GETHOSTBYADDR_R)
|
||||
add_definitions(-DHAS_GETHOSTBYADDR_R=1)
|
||||
endif()
|
||||
if(HAS_INET_PTON)
|
||||
add_definitions(-DHAS_INET_PTON=1)
|
||||
endif()
|
||||
if(HAS_INET_NTOP)
|
||||
add_definitions(-DHAS_INET_NTOP=1)
|
||||
endif()
|
||||
if(HAS_MSGHDR_FLAGS)
|
||||
add_definitions(-DHAS_MSGHDR_FLAGS=1)
|
||||
endif()
|
||||
if(HAS_SOCKLEN_T)
|
||||
add_definitions(-DHAS_SOCKLEN_T=1)
|
||||
endif()
|
||||
if(HAS_QOS_FLOWID)
|
||||
add_definitions(-DHAS_QOS_FLOWID=1)
|
||||
endif()
|
||||
if(HAS_PQOS_FLOWID)
|
||||
add_definitions(-DHAS_PQOS_FLOWID=1)
|
||||
endif()
|
||||
|
||||
include_directories(${PROJECT_SOURCE_DIR}/include)
|
||||
|
||||
set(INCLUDE_FILES_PREFIX include/enet)
|
||||
set(INCLUDE_FILES
|
||||
${INCLUDE_FILES_PREFIX}/callbacks.h
|
||||
${INCLUDE_FILES_PREFIX}/enet.h
|
||||
${INCLUDE_FILES_PREFIX}/list.h
|
||||
${INCLUDE_FILES_PREFIX}/protocol.h
|
||||
${INCLUDE_FILES_PREFIX}/time.h
|
||||
${INCLUDE_FILES_PREFIX}/types.h
|
||||
${INCLUDE_FILES_PREFIX}/unix.h
|
||||
${INCLUDE_FILES_PREFIX}/utility.h
|
||||
${INCLUDE_FILES_PREFIX}/win32.h
|
||||
)
|
||||
|
||||
set(SOURCE_FILES
|
||||
callbacks.c
|
||||
compress.c
|
||||
host.c
|
||||
list.c
|
||||
packet.c
|
||||
peer.c
|
||||
protocol.c
|
||||
unix.c
|
||||
win32.c)
|
||||
|
||||
source_group(include FILES ${INCLUDE_FILES})
|
||||
source_group(source FILES ${SOURCE_FILES})
|
||||
|
||||
add_library(enet STATIC
|
||||
${INCLUDE_FILES}
|
||||
${SOURCE_FILES}
|
||||
)
|
||||
target_include_directories(enet SYSTEM PUBLIC include)
|
||||
|
||||
if (MINGW)
|
||||
target_link_libraries(enet winmm ws2_32)
|
||||
endif()
|
||||
|
||||
if(NOT ENET_NO_INSTALL)
|
||||
install(TARGETS enet
|
||||
RUNTIME DESTINATION bin
|
||||
ARCHIVE DESTINATION lib/static
|
||||
LIBRARY DESTINATION lib)
|
||||
|
||||
install(DIRECTORY include/
|
||||
DESTINATION include)
|
||||
endif()
|
||||
@@ -1,3 +1,38 @@
|
||||
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):
|
||||
|
||||
* miscellaneous bug fixes
|
||||
* added premake and cmake support
|
||||
* miscellaneous documentation cleanups
|
||||
|
||||
ENet 1.3.12 (April 24, 2014):
|
||||
|
||||
* added maximumPacketSize and maximumWaitingData fields to ENetHost to limit the amount of
|
||||
data waiting to be delivered on a peer (beware that the default maximumPacketSize is
|
||||
32MB and should be set higher if desired as should maximumWaitingData)
|
||||
|
||||
ENet 1.3.11 (December 26, 2013):
|
||||
|
||||
* allow an ENetHost to connect to itself
|
||||
|
||||
@@ -0,0 +1,191 @@
|
||||
<doxygenlayout version="1.0">
|
||||
<!-- Generated by doxygen 1.8.6 -->
|
||||
<!-- Navigation index tabs for HTML output -->
|
||||
<navindex>
|
||||
<tab type="mainpage" visible="yes" title="Home"/>
|
||||
<tab type="user" visible="yes" title="Features" url="@ref Features" />
|
||||
<tab type="user" visible="yes" title="Downloads" url="@ref Downloads" />
|
||||
<tab type="user" visible="yes" title="Installation" url="@ref Installation" />
|
||||
<tab type="user" visible="yes" title="Tutorial" url="@ref Tutorial" />
|
||||
<tab type="user" visible="yes" title="Mailing List" url="@ref MailingList" />
|
||||
<tab type="user" visible="yes" title="IRC Channel" url="@ref IRCChannel" />
|
||||
<tab type="user" visible="yes" title="FAQ" url="@ref FAQ" />
|
||||
<tab type="user" visible="yes" title="License" url="@ref License" />
|
||||
<tab type="usergroup" visible="yes" title="Documentation" briefdescription="Documentation">
|
||||
<tab type="modules" visible="yes" title="Functions" intro=""/>
|
||||
<tab type="classlist" visible="yes" title="Data Structures" intro=""/>
|
||||
<tab type="filelist" visible="yes" title="Files" intro=""/>
|
||||
<tab type="globals" visible="yes" title="" intro=""/>
|
||||
</tab>
|
||||
</navindex>
|
||||
|
||||
<!-- Layout definition for a class page -->
|
||||
<class>
|
||||
<briefdescription visible="yes"/>
|
||||
<includes visible="$SHOW_INCLUDE_FILES"/>
|
||||
<inheritancegraph visible="$CLASS_GRAPH"/>
|
||||
<collaborationgraph visible="$COLLABORATION_GRAPH"/>
|
||||
<memberdecl>
|
||||
<nestedclasses visible="yes" title=""/>
|
||||
<publictypes title=""/>
|
||||
<services title=""/>
|
||||
<interfaces title=""/>
|
||||
<publicslots title=""/>
|
||||
<signals title=""/>
|
||||
<publicmethods title=""/>
|
||||
<publicstaticmethods title=""/>
|
||||
<publicattributes title=""/>
|
||||
<publicstaticattributes title=""/>
|
||||
<protectedtypes title=""/>
|
||||
<protectedslots title=""/>
|
||||
<protectedmethods title=""/>
|
||||
<protectedstaticmethods title=""/>
|
||||
<protectedattributes title=""/>
|
||||
<protectedstaticattributes title=""/>
|
||||
<packagetypes title=""/>
|
||||
<packagemethods title=""/>
|
||||
<packagestaticmethods title=""/>
|
||||
<packageattributes title=""/>
|
||||
<packagestaticattributes title=""/>
|
||||
<properties title=""/>
|
||||
<events title=""/>
|
||||
<privatetypes title=""/>
|
||||
<privateslots title=""/>
|
||||
<privatemethods title=""/>
|
||||
<privatestaticmethods title=""/>
|
||||
<privateattributes title=""/>
|
||||
<privatestaticattributes title=""/>
|
||||
<friends title=""/>
|
||||
<related title="" subtitle=""/>
|
||||
<membergroups visible="yes"/>
|
||||
</memberdecl>
|
||||
<detaileddescription title=""/>
|
||||
<memberdef>
|
||||
<inlineclasses title=""/>
|
||||
<typedefs title=""/>
|
||||
<enums title=""/>
|
||||
<services title=""/>
|
||||
<interfaces title=""/>
|
||||
<constructors title=""/>
|
||||
<functions title=""/>
|
||||
<related title=""/>
|
||||
<variables title=""/>
|
||||
<properties title=""/>
|
||||
<events title=""/>
|
||||
</memberdef>
|
||||
<allmemberslink visible="yes"/>
|
||||
<usedfiles visible="$SHOW_USED_FILES"/>
|
||||
<authorsection visible="yes"/>
|
||||
</class>
|
||||
|
||||
<!-- Layout definition for a namespace page -->
|
||||
<namespace>
|
||||
<briefdescription visible="yes"/>
|
||||
<memberdecl>
|
||||
<nestednamespaces visible="yes" title=""/>
|
||||
<constantgroups visible="yes" title=""/>
|
||||
<classes visible="yes" title=""/>
|
||||
<typedefs title=""/>
|
||||
<enums title=""/>
|
||||
<functions title=""/>
|
||||
<variables title=""/>
|
||||
<membergroups visible="yes"/>
|
||||
</memberdecl>
|
||||
<detaileddescription title=""/>
|
||||
<memberdef>
|
||||
<inlineclasses title=""/>
|
||||
<typedefs title=""/>
|
||||
<enums title=""/>
|
||||
<functions title=""/>
|
||||
<variables title=""/>
|
||||
</memberdef>
|
||||
<authorsection visible="yes"/>
|
||||
</namespace>
|
||||
|
||||
<!-- Layout definition for a file page -->
|
||||
<file>
|
||||
<briefdescription visible="yes"/>
|
||||
<includes visible="$SHOW_INCLUDE_FILES"/>
|
||||
<includegraph visible="$INCLUDE_GRAPH"/>
|
||||
<includedbygraph visible="$INCLUDED_BY_GRAPH"/>
|
||||
<sourcelink visible="yes"/>
|
||||
<memberdecl>
|
||||
<classes visible="yes" title=""/>
|
||||
<namespaces visible="yes" title=""/>
|
||||
<constantgroups visible="yes" title=""/>
|
||||
<defines title=""/>
|
||||
<typedefs title=""/>
|
||||
<enums title=""/>
|
||||
<functions title=""/>
|
||||
<variables title=""/>
|
||||
<membergroups visible="yes"/>
|
||||
</memberdecl>
|
||||
<detaileddescription title=""/>
|
||||
<memberdef>
|
||||
<inlineclasses title=""/>
|
||||
<defines title=""/>
|
||||
<typedefs title=""/>
|
||||
<enums title=""/>
|
||||
<functions title=""/>
|
||||
<variables title=""/>
|
||||
</memberdef>
|
||||
<authorsection/>
|
||||
</file>
|
||||
|
||||
<!-- Layout definition for a group page -->
|
||||
<group>
|
||||
<briefdescription visible="yes"/>
|
||||
<groupgraph visible="$GROUP_GRAPHS"/>
|
||||
<memberdecl>
|
||||
<nestedgroups visible="yes" title=""/>
|
||||
<dirs visible="yes" title=""/>
|
||||
<files visible="yes" title=""/>
|
||||
<namespaces visible="yes" title=""/>
|
||||
<classes visible="yes" title=""/>
|
||||
<defines title=""/>
|
||||
<typedefs title=""/>
|
||||
<enums title=""/>
|
||||
<enumvalues title=""/>
|
||||
<functions title=""/>
|
||||
<variables title=""/>
|
||||
<signals title=""/>
|
||||
<publicslots title=""/>
|
||||
<protectedslots title=""/>
|
||||
<privateslots title=""/>
|
||||
<events title=""/>
|
||||
<properties title=""/>
|
||||
<friends title=""/>
|
||||
<membergroups visible="yes"/>
|
||||
</memberdecl>
|
||||
<detaileddescription title=""/>
|
||||
<memberdef>
|
||||
<pagedocs/>
|
||||
<inlineclasses title=""/>
|
||||
<defines title=""/>
|
||||
<typedefs title=""/>
|
||||
<enums title=""/>
|
||||
<enumvalues title=""/>
|
||||
<functions title=""/>
|
||||
<variables title=""/>
|
||||
<signals title=""/>
|
||||
<publicslots title=""/>
|
||||
<protectedslots title=""/>
|
||||
<privateslots title=""/>
|
||||
<events title=""/>
|
||||
<properties title=""/>
|
||||
<friends title=""/>
|
||||
</memberdef>
|
||||
<authorsection visible="yes"/>
|
||||
</group>
|
||||
|
||||
<!-- Layout definition for a directory page -->
|
||||
<directory>
|
||||
<briefdescription visible="yes"/>
|
||||
<directorygraph visible="yes"/>
|
||||
<memberdecl>
|
||||
<dirs visible="yes"/>
|
||||
<files visible="yes"/>
|
||||
</memberdecl>
|
||||
<detaileddescription title=""/>
|
||||
</directory>
|
||||
</doxygenlayout>
|
||||
@@ -1,4 +1,4 @@
|
||||
Copyright (c) 2002-2013 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 6:2:4
|
||||
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
|
||||
|
||||
+3
-1
@@ -1,4 +1,4 @@
|
||||
AC_INIT([libenet], [1.3.11])
|
||||
AC_INIT([libenet], [1.3.17])
|
||||
AC_CONFIG_SRCDIR([include/enet/enet.h])
|
||||
AM_INIT_AUTOMAKE([foreign])
|
||||
|
||||
@@ -7,6 +7,8 @@ AC_CONFIG_MACRO_DIR([m4])
|
||||
AC_PROG_CC
|
||||
AC_PROG_LIBTOOL
|
||||
|
||||
AC_CHECK_FUNC(getaddrinfo, [AC_DEFINE(HAS_GETADDRINFO)])
|
||||
AC_CHECK_FUNC(getnameinfo, [AC_DEFINE(HAS_GETNAMEINFO)])
|
||||
AC_CHECK_FUNC(gethostbyaddr_r, [AC_DEFINE(HAS_GETHOSTBYADDR_R)])
|
||||
AC_CHECK_FUNC(gethostbyname_r, [AC_DEFINE(HAS_GETHOSTBYNAME_R)])
|
||||
AC_CHECK_FUNC(poll, [AC_DEFINE(HAS_POLL)])
|
||||
|
||||
+2
-2
@@ -1,12 +1,12 @@
|
||||
/**
|
||||
@page FAQ Frequently Answered Questions
|
||||
|
||||
@section Q1 Is ENet thread safe?
|
||||
@section Q1 Is ENet thread-safe?
|
||||
|
||||
ENet does not use any significant global variables, the vast majority
|
||||
of state is encapsulated in the ENetHost structure. As such, as long
|
||||
as the application guards access to this structure, then ENet should
|
||||
operate fine in a multithreaded environment.
|
||||
operate fine in a multi-threaded environment.
|
||||
|
||||
@section Q2 Isn't ENet just re-inventing TCP?! What's the point?
|
||||
|
||||
|
||||
+2
-2
@@ -3,7 +3,7 @@
|
||||
|
||||
ENet evolved specifically as a UDP networking layer for the
|
||||
multiplayer first person shooter Cube. Cube necessitated low latency
|
||||
communcation with data sent out very frequently, so TCP was an
|
||||
communication with data sent out very frequently, so TCP was an
|
||||
unsuitable choice due to its high latency and stream orientation. UDP,
|
||||
however, lacks many sometimes necessary features from TCP such as
|
||||
reliability, sequencing, unrestricted packet sizes, and connection
|
||||
@@ -44,7 +44,7 @@ packet streams that simplify the transfer of various types of data.
|
||||
|
||||
ENet provides sequencing for all packets by assigning to each sent
|
||||
packet a sequence number that is incremented as packets are sent. ENet
|
||||
guarentees that no packet with a higher sequence number will be
|
||||
guarantees that no packet with a higher sequence number will be
|
||||
delivered before a packet with a lower sequence number, thus ensuring
|
||||
packets are delivered exactly in the order they are sent.
|
||||
|
||||
|
||||
+1
-2
@@ -2,8 +2,7 @@
|
||||
@page Installation Installation
|
||||
|
||||
ENet should be trivially simple to integrate with most applications.
|
||||
First, make sure you download the latest source distribution here @ref
|
||||
SourceDistro.
|
||||
First, make sure you download the latest source distribution at @ref Downloads.
|
||||
|
||||
@section Unix Unix-like Operating Systems
|
||||
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
@page License License
|
||||
|
||||
Copyright (c) 2002-2013 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
|
||||
|
||||
+12
-12
@@ -1,6 +1,4 @@
|
||||
/** @mainpage enet
|
||||
<center>http://enet.bespin.org</center>
|
||||
<hr>
|
||||
/** @mainpage ENet
|
||||
|
||||
ENet's purpose is to provide a relatively thin, simple and robust
|
||||
network communication layer on top of UDP (User Datagram Protocol).
|
||||
@@ -14,7 +12,7 @@ portable, and easily embeddable.
|
||||
|
||||
@ref Features
|
||||
|
||||
@ref SourceDistro
|
||||
@ref Downloads
|
||||
|
||||
@ref Installation
|
||||
|
||||
@@ -28,32 +26,34 @@ portable, and easily embeddable.
|
||||
|
||||
@ref License
|
||||
|
||||
<a class="el" href="usergroup0.html">Documentation</a>
|
||||
|
||||
*/
|
||||
|
||||
/**
|
||||
@page SourceDistro Source Distribution
|
||||
@page Downloads Downloads
|
||||
|
||||
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.11) can be downloaded <a href="http://enet.bespin.org/download/enet-1.3.11.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 href="http://enet.bespin.org/download/enet-1.2.5.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 href="https://github.com/lsalzman/enet">the github repository</a>.
|
||||
You can find the most recent ENet source at <a class="el" href="https://github.com/lsalzman/enet">the github repository</a>.
|
||||
|
||||
*/
|
||||
|
||||
/**
|
||||
@page MailingList ENet Mailing List
|
||||
@page MailingList Mailing List
|
||||
|
||||
The <a href="http://lists.cubik.org/mailman/listinfo/enet-discuss">enet-discuss</a> list is for discussion of ENet, including bug reports or feature requests.
|
||||
The <a class="el" href="http://lists.cubik.org/mailman/listinfo/enet-discuss">enet-discuss</a> list is for discussion of ENet, including bug reports or feature requests.
|
||||
|
||||
*/
|
||||
|
||||
/**
|
||||
@page IRCChannel ENet IRC Channel
|
||||
@page IRCChannel IRC Channel
|
||||
|
||||
Join the \#enet channel on the freenode IRC network (irc.freenode.net) 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.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
+13
-4
@@ -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)
|
||||
{
|
||||
@@ -127,6 +127,15 @@ enet_host_service() will return immediately if there are no events to
|
||||
dispatch. enet_host_service() will return 1 if an event was dispatched
|
||||
within the specified timeout.
|
||||
|
||||
Beware that most processing of the network with the ENet stack is done
|
||||
inside enet_host_service(). Both hosts that make up the sides of a connection
|
||||
must regularly call this function to ensure packets are actually sent and
|
||||
received. A common symptom of not actively calling enet_host_service()
|
||||
on both ends is that one side receives events while the other does not.
|
||||
The best way to schedule this activity to ensure adequate service is, for
|
||||
example, to call enet_host_service() with a 0 timeout (meaning non-blocking)
|
||||
at the beginning of every frame in a game loop.
|
||||
|
||||
Currently there are only four types of significant events in ENet:
|
||||
|
||||
An event of type ENET_EVENT_TYPE_NONE is returned if no event occurred
|
||||
@@ -182,7 +191,7 @@ disconnect event and must be explicitly reset.
|
||||
break;
|
||||
|
||||
case ENET_EVENT_TYPE_DISCONNECT:
|
||||
printf ("%s disconected.\n", event.peer -> data);
|
||||
printf ("%s disconnected.\n", event.peer -> data);
|
||||
|
||||
/* Reset the peer's client information. */
|
||||
|
||||
@@ -204,7 +213,7 @@ Certain flags may also be supplied to enet_packet_create() to control
|
||||
various packet features:
|
||||
|
||||
ENET_PACKET_FLAG_RELIABLE specifies that the packet must use reliable
|
||||
delivery. A reliable packet is guarenteed to be delivered, and a
|
||||
delivery. A reliable packet is guaranteed to be delivered, and a
|
||||
number of retry attempts will be made until an acknowledgement is
|
||||
received from the foreign host the packet is sent to. If a certain
|
||||
number of retry attempts is reached without any acknowledgement, ENet
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
|
||||
/** Creates a host for communicating to peers.
|
||||
|
||||
@param addressFamily the address family of the socket that should be created (ex: PF_INET/PF_INET6)
|
||||
@param address the address at which other peers may connect to this host. If NULL, then no peers may connect to the host.
|
||||
@param peerCount the maximum number of peers that should be allocated for the host.
|
||||
@param channelLimit the maximum number of channels allowed; if 0, then this is equivalent to ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT
|
||||
@@ -26,7 +27,7 @@
|
||||
at any given time.
|
||||
*/
|
||||
ENetHost *
|
||||
enet_host_create (const ENetAddress * address, size_t peerCount, size_t channelLimit, enet_uint32 incomingBandwidth, enet_uint32 outgoingBandwidth)
|
||||
enet_host_create (int addressFamily, const ENetAddress * address, size_t peerCount, size_t channelLimit, enet_uint32 incomingBandwidth, enet_uint32 outgoingBandwidth)
|
||||
{
|
||||
ENetHost * host;
|
||||
ENetPeer * currentPeer;
|
||||
@@ -48,7 +49,7 @@ enet_host_create (const ENetAddress * address, size_t peerCount, size_t channelL
|
||||
}
|
||||
memset (host -> peers, 0, peerCount * sizeof (ENetPeer));
|
||||
|
||||
host -> socket = enet_socket_create (ENET_SOCKET_TYPE_DATAGRAM);
|
||||
host -> socket = enet_socket_create (addressFamily, ENET_SOCKET_TYPE_DATAGRAM);
|
||||
if (host -> socket == ENET_SOCKET_NULL || (address != NULL && enet_socket_bind (host -> socket, address) < 0))
|
||||
{
|
||||
if (host -> socket != ENET_SOCKET_NULL)
|
||||
@@ -60,8 +61,9 @@ enet_host_create (const ENetAddress * address, size_t peerCount, size_t channelL
|
||||
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_BROADCAST, 1);
|
||||
enet_socket_set_option (host -> socket, ENET_SOCKOPT_RCVBUF, ENET_HOST_RECEIVE_BUFFER_SIZE);
|
||||
enet_socket_set_option (host -> socket, ENET_SOCKOPT_SNDBUF, ENET_HOST_SEND_BUFFER_SIZE);
|
||||
|
||||
@@ -87,8 +89,8 @@ enet_host_create (const ENetAddress * address, size_t peerCount, size_t channelL
|
||||
host -> commandCount = 0;
|
||||
host -> bufferCount = 0;
|
||||
host -> checksum = NULL;
|
||||
host -> receivedAddress.host = ENET_HOST_ANY;
|
||||
host -> receivedAddress.port = 0;
|
||||
memset(& host -> receivedPeerAddress, 0, sizeof (host -> receivedPeerAddress));
|
||||
memset(& host -> receivedLocalAddress, 0, sizeof (host -> receivedLocalAddress));
|
||||
host -> receivedData = NULL;
|
||||
host -> receivedDataLength = 0;
|
||||
|
||||
@@ -96,10 +98,13 @@ enet_host_create (const ENetAddress * address, size_t peerCount, size_t channelL
|
||||
host -> totalSentPackets = 0;
|
||||
host -> totalReceivedData = 0;
|
||||
host -> totalReceivedPackets = 0;
|
||||
host -> totalQueued = 0;
|
||||
|
||||
host -> connectedPeers = 0;
|
||||
host -> bandwidthLimitedPeers = 0;
|
||||
host -> duplicatePeers = ENET_PROTOCOL_MAXIMUM_PEER_ID;
|
||||
host -> maximumPacketSize = ENET_HOST_DEFAULT_MAXIMUM_PACKET_SIZE;
|
||||
host -> maximumWaitingData = ENET_HOST_DEFAULT_MAXIMUM_WAITING_DATA;
|
||||
|
||||
host -> compressor.context = NULL;
|
||||
host -> compressor.compress = NULL;
|
||||
@@ -121,9 +126,8 @@ enet_host_create (const ENetAddress * address, size_t peerCount, size_t channelL
|
||||
|
||||
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);
|
||||
@@ -159,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
|
||||
@@ -198,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;
|
||||
@@ -250,30 +265,6 @@ enet_host_connect (ENetHost * host, const ENetAddress * address, size_t channelC
|
||||
return currentPeer;
|
||||
}
|
||||
|
||||
/** Queues a packet to be sent to all peers associated with the host.
|
||||
@param host host on which to broadcast the packet
|
||||
@param channelID channel on which to broadcast
|
||||
@param packet packet to broadcast
|
||||
*/
|
||||
void
|
||||
enet_host_broadcast (ENetHost * host, enet_uint8 channelID, ENetPacket * packet)
|
||||
{
|
||||
ENetPeer * currentPeer;
|
||||
|
||||
for (currentPeer = host -> peers;
|
||||
currentPeer < & host -> peers [host -> peerCount];
|
||||
++ currentPeer)
|
||||
{
|
||||
if (currentPeer -> state != ENET_PEER_STATE_CONNECTED)
|
||||
continue;
|
||||
|
||||
enet_peer_send (currentPeer, channelID, packet);
|
||||
}
|
||||
|
||||
if (packet -> referenceCount == 0)
|
||||
enet_packet_destroy (packet);
|
||||
}
|
||||
|
||||
/** Sets the packet compressor the host should use to compress and decompress packets.
|
||||
@param host host to enable or disable compression for
|
||||
@param compressor callbacks for for the packet compressor; if NULL, then compression is disabled
|
||||
|
||||
+92
-90
@@ -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 11
|
||||
#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)
|
||||
@@ -62,7 +62,9 @@ typedef enum _ENetSocketOption
|
||||
ENET_SOCKOPT_RCVTIMEO = 6,
|
||||
ENET_SOCKOPT_SNDTIMEO = 7,
|
||||
ENET_SOCKOPT_ERROR = 8,
|
||||
ENET_SOCKOPT_NODELAY = 9
|
||||
ENET_SOCKOPT_NODELAY = 9,
|
||||
ENET_SOCKOPT_TTL = 10,
|
||||
ENET_SOCKOPT_QOS = 11,
|
||||
} ENetSocketOption;
|
||||
|
||||
typedef enum _ENetSocketShutdown
|
||||
@@ -72,24 +74,13 @@ typedef enum _ENetSocketShutdown
|
||||
ENET_SOCKET_SHUTDOWN_READ_WRITE = 2
|
||||
} ENetSocketShutdown;
|
||||
|
||||
#define ENET_HOST_ANY 0
|
||||
#define ENET_HOST_BROADCAST 0xFFFFFFFFU
|
||||
#define ENET_PORT_ANY 0
|
||||
|
||||
/**
|
||||
* Portable internet address structure.
|
||||
*
|
||||
* The host must be specified in network byte-order, and the port must be in host
|
||||
* byte-order. The constant ENET_HOST_ANY may be used to specify the default
|
||||
* server host. The constant ENET_HOST_BROADCAST may be used to specify the
|
||||
* broadcast address (255.255.255.255). This makes sense for enet_host_connect,
|
||||
* but not for enet_host_create. Once a server responds to a broadcast, the
|
||||
* address is updated from ENET_HOST_BROADCAST to the server's actual IP address.
|
||||
* Portable internet address structure.
|
||||
*/
|
||||
typedef struct _ENetAddress
|
||||
{
|
||||
enet_uint32 host;
|
||||
enet_uint16 port;
|
||||
socklen_t addressLength;
|
||||
struct sockaddr_storage address;
|
||||
} ENetAddress;
|
||||
|
||||
/**
|
||||
@@ -98,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
|
||||
@@ -125,20 +116,24 @@ 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
|
||||
|
||||
*
|
||||
* ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT - packet will be fragmented using unreliable
|
||||
* (instead of reliable) sends if it exceeds the MTU
|
||||
*
|
||||
* ENET_PACKET_FLAG_SENT - whether the packet has been sent from all queues it has been entered into
|
||||
@sa ENetPacketFlag
|
||||
*/
|
||||
typedef struct _ENetPacket
|
||||
@@ -165,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;
|
||||
@@ -174,7 +169,7 @@ typedef struct _ENetOutgoingCommand
|
||||
} ENetOutgoingCommand;
|
||||
|
||||
typedef struct _ENetIncomingCommand
|
||||
{
|
||||
{
|
||||
ENetListNode incomingCommandList;
|
||||
enet_uint16 reliableSequenceNumber;
|
||||
enet_uint16 unreliableSequenceNumber;
|
||||
@@ -196,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
|
||||
@@ -205,15 +200,26 @@ 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 = 1400,
|
||||
ENET_HOST_DEFAULT_MTU = 900,
|
||||
ENET_HOST_DEFAULT_MAXIMUM_PACKET_SIZE = 32 * 1024 * 1024,
|
||||
ENET_HOST_DEFAULT_MAXIMUM_WAITING_DATA = 32 * 1024 * 1024,
|
||||
|
||||
ENET_PEER_DEFAULT_ROUND_TRIP_TIME = 500,
|
||||
ENET_PEER_DEFAULT_PACKET_THROTTLE = 32,
|
||||
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,
|
||||
@@ -244,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;
|
||||
@@ -259,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;
|
||||
@@ -301,15 +314,16 @@ 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;
|
||||
|
||||
/** An ENet packet compressor for compressing UDP packets before socket sends or receives.
|
||||
@@ -331,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.
|
||||
@@ -341,7 +355,6 @@ typedef int (ENET_CALLBACK * ENetInterceptCallback) (struct _ENetHost * host, st
|
||||
@sa enet_host_connect()
|
||||
@sa enet_host_service()
|
||||
@sa enet_host_flush()
|
||||
@sa enet_host_broadcast()
|
||||
@sa enet_host_compress()
|
||||
@sa enet_host_compress_with_range_coder()
|
||||
@sa enet_host_channel_limit()
|
||||
@@ -351,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 */
|
||||
@@ -363,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];
|
||||
@@ -373,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 */
|
||||
@@ -384,6 +399,8 @@ typedef struct _ENetHost
|
||||
size_t connectedPeers;
|
||||
size_t bandwidthLimitedPeers;
|
||||
size_t duplicatePeers; /**< optional number of allowed peers from duplicate IPs, defaults to ENET_PROTOCOL_MAXIMUM_PEER_ID */
|
||||
size_t maximumPacketSize; /**< the maximum allowable packet size that may be sent or received on a peer */
|
||||
size_t maximumWaitingData; /**< the maximum aggregate amount of buffer space a peer may use waiting for packets to be delivered */
|
||||
} ENetHost;
|
||||
|
||||
/**
|
||||
@@ -392,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_pper_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
|
||||
@@ -419,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 */
|
||||
@@ -432,26 +449,26 @@ 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
|
||||
@param inits user-overriden callbacks where any NULL callbacks will use ENet's defaults
|
||||
@param inits user-overridden callbacks where any NULL callbacks will use ENet's defaults
|
||||
@returns 0 on success, < 0 on failure
|
||||
*/
|
||||
ENET_API int enet_initialize_with_callbacks (ENetVersion version, const ENetCallbacks * inits);
|
||||
|
||||
/**
|
||||
/**
|
||||
Shuts down ENet globally. Should be called when a program that has
|
||||
initialized ENet exits.
|
||||
*/
|
||||
@@ -459,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);
|
||||
|
||||
@@ -480,14 +497,14 @@ ENET_API void enet_time_set (enet_uint32);
|
||||
/** @defgroup socket ENet socket functions
|
||||
@{
|
||||
*/
|
||||
ENET_API ENetSocket enet_socket_create (ENetSocketType);
|
||||
ENET_API ENetSocket enet_socket_create (int, ENetSocketType);
|
||||
ENET_API int enet_socket_bind (ENetSocket, const ENetAddress *);
|
||||
ENET_API int enet_socket_get_address (ENetSocket, ENetAddress *);
|
||||
ENET_API int enet_socket_listen (ENetSocket, int);
|
||||
ENET_API ENetSocket enet_socket_accept (ENetSocket, ENetAddress *);
|
||||
ENET_API int enet_socket_connect (ENetSocket, const ENetAddress *);
|
||||
ENET_API int enet_socket_send (ENetSocket, const ENetAddress *, const ENetBuffer *, size_t);
|
||||
ENET_API int enet_socket_receive (ENetSocket, ENetAddress *, ENetBuffer *, size_t);
|
||||
ENET_API int enet_socket_send (ENetSocket, const ENetAddress *, const ENetAddress *, const ENetBuffer *, size_t);
|
||||
ENET_API int enet_socket_receive (ENetSocket, ENetAddress *, ENetAddress *, ENetBuffer *, size_t);
|
||||
ENET_API int enet_socket_wait (ENetSocket, enet_uint32 *, enet_uint32);
|
||||
ENET_API int enet_socket_set_option (ENetSocket, ENetSocketOption, int);
|
||||
ENET_API int enet_socket_get_option (ENetSocket, ENetSocketOption, int *);
|
||||
@@ -509,26 +526,10 @@ ENET_API int enet_socketset_select (ENetSocket, ENetSocketSet *, ENetSock
|
||||
@returns the address of the given hostName in address on success
|
||||
*/
|
||||
ENET_API int enet_address_set_host (ENetAddress * address, const char * hostName);
|
||||
|
||||
/** Gives the printable form of the ip address specified in the address parameter.
|
||||
@param address address printed
|
||||
@param hostName destination for name, must not be NULL
|
||||
@param nameLength maximum length of hostName.
|
||||
@returns the null-terminated name of the host in hostName on success
|
||||
@retval 0 on success
|
||||
@retval < 0 on failure
|
||||
*/
|
||||
ENET_API int enet_address_get_host_ip (const ENetAddress * address, char * hostName, size_t nameLength);
|
||||
|
||||
/** Attempts to do a reverse lookup of the host field in the address parameter.
|
||||
@param address address used for reverse lookup
|
||||
@param hostName destination for name, must not be NULL
|
||||
@param nameLength maximum length of hostName.
|
||||
@returns the null-terminated name of the host in hostName on success
|
||||
@retval 0 on success
|
||||
@retval < 0 on failure
|
||||
*/
|
||||
ENET_API int enet_address_get_host (const ENetAddress * address, char * hostName, size_t nameLength);
|
||||
ENET_API int enet_address_set_address (ENetAddress * address, struct sockaddr * addr, socklen_t addrlen);
|
||||
ENET_API int enet_address_set_port (ENetAddress * address, enet_uint16 port);
|
||||
ENET_API int enet_address_wildcard (const ENetAddress * address);
|
||||
ENET_API int enet_address_equal (ENetAddress * address1, ENetAddress * address2);
|
||||
|
||||
/** @} */
|
||||
|
||||
@@ -536,20 +537,20 @@ 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 (const ENetAddress *, size_t, size_t, enet_uint32, enet_uint32);
|
||||
|
||||
ENET_API ENetHost * enet_host_create (int, const ENetAddress *, size_t, size_t, enet_uint32, enet_uint32);
|
||||
ENET_API void enet_host_destroy (ENetHost *);
|
||||
ENET_API ENetPeer * enet_host_connect (ENetHost *, const ENetAddress *, size_t, enet_uint32);
|
||||
ENET_API int enet_host_check_events (ENetHost *, ENetEvent *);
|
||||
ENET_API int enet_host_service (ENetHost *, ENetEvent *, enet_uint32);
|
||||
ENET_API void enet_host_flush (ENetHost *);
|
||||
ENET_API void enet_host_broadcast (ENetHost *, enet_uint8, ENetPacket *);
|
||||
ENET_API void enet_host_compress (ENetHost *, const ENetCompressor *);
|
||||
ENET_API int enet_host_compress_with_range_coder (ENetHost * host);
|
||||
ENET_API void enet_host_channel_limit (ENetHost *, size_t);
|
||||
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);
|
||||
@@ -563,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 *, ENetPacket *, enet_uint32);
|
||||
extern ENetIncomingCommand * enet_peer_queue_incoming_command (ENetPeer *, const ENetProtocol *, const void *, size_t, enet_uint32, enet_uint32);
|
||||
extern ENetAcknowledgement * enet_peer_queue_acknowledgement (ENetPeer *, const ENetProtocol *, enet_uint16);
|
||||
extern void enet_peer_dispatch_incoming_unreliable_commands (ENetPeer *, ENetChannel *);
|
||||
extern void enet_peer_dispatch_incoming_reliable_commands (ENetPeer *, ENetChannel *);
|
||||
extern void enet_peer_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 *);
|
||||
|
||||
@@ -576,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,14 +10,17 @@
|
||||
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,
|
||||
ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT = 1,
|
||||
ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT = 255,
|
||||
ENET_PROTOCOL_MAXIMUM_PEER_ID = 0xFFF,
|
||||
ENET_PROTOCOL_MAXIMUM_PACKET_SIZE = 1024 * 1024 * 1024,
|
||||
ENET_PROTOCOL_MAXIMUM_FRAGMENT_COUNT = 1024 * 1024
|
||||
};
|
||||
|
||||
|
||||
@@ -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__ */
|
||||
|
||||
|
||||
@@ -7,16 +7,18 @@
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#ifdef ENET_BUILDING_LIB
|
||||
#pragma warning (disable: 4996) // 'strncpy' was declared deprecated
|
||||
#pragma warning (disable: 4267) // size_t to int conversion
|
||||
#pragma warning (disable: 4244) // 64bit to 32bit int
|
||||
#pragma warning (disable: 4018) // signed/unsigned mismatch
|
||||
#pragma warning (disable: 4146) // unary minus operator applied to unsigned type
|
||||
#define _CRT_SECURE_NO_DEPRECATE
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
|
||||
typedef SOCKET ENetSocket;
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
*/
|
||||
|
||||
/** Creates a packet that may be sent to a peer.
|
||||
@param dataContents initial contents of the packet's data; the packet's data will remain uninitialized if dataContents is NULL.
|
||||
@param data initial contents of the packet's data; the packet's data will remain uninitialized if data is NULL.
|
||||
@param dataLength size of the data allocated for this packet
|
||||
@param flags flags for this packet as described for the ENetPacket structure.
|
||||
@returns the packet on success, NULL on failure
|
||||
@@ -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,15 +106,16 @@ 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;
|
||||
|
||||
if (peer -> state != ENET_PEER_STATE_CONNECTED ||
|
||||
channelID >= peer -> channelCount ||
|
||||
packet -> dataLength > ENET_PROTOCOL_MAXIMUM_PACKET_SIZE)
|
||||
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);
|
||||
@@ -241,6 +249,8 @@ enet_peer_receive (ENetPeer * peer, enet_uint8 * channelID)
|
||||
|
||||
enet_free (incomingCommand);
|
||||
|
||||
peer -> totalWaitingData -= packet -> dataLength;
|
||||
|
||||
return packet;
|
||||
}
|
||||
|
||||
@@ -266,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;
|
||||
|
||||
@@ -276,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)
|
||||
@@ -296,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
|
||||
@@ -304,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)
|
||||
@@ -415,6 +427,8 @@ enet_peer_reset (ENetPeer * peer)
|
||||
peer -> incomingUnsequencedGroup = 0;
|
||||
peer -> outgoingUnsequencedGroup = 0;
|
||||
peer -> eventData = 0;
|
||||
peer -> totalWaitingData = 0;
|
||||
peer -> flags = 0;
|
||||
|
||||
memset (peer -> unsequencedWindow, 0, sizeof (peer -> unsequencedWindow));
|
||||
|
||||
@@ -424,7 +438,7 @@ enet_peer_reset (ENetPeer * peer)
|
||||
/** Sends a ping request to a peer.
|
||||
@param peer destination for the ping request
|
||||
@remarks ping requests factor into the mean round trip time as designated by the
|
||||
roundTripTime field in the ENetPeer structure. Enet automatically pings all connected
|
||||
roundTripTime field in the ENetPeer structure. ENet automatically pings all connected
|
||||
peers at regular intervals, however, this function may be called to ensure more
|
||||
frequent ping requests.
|
||||
*/
|
||||
@@ -486,7 +500,7 @@ enet_peer_timeout (ENetPeer * peer, enet_uint32 timeoutLimit, enet_uint32 timeou
|
||||
@param peer peer to disconnect
|
||||
@param data data describing the disconnection
|
||||
@remarks No ENET_EVENT_DISCONNECT event will be generated. The foreign peer is not
|
||||
guarenteed to receive the disconnect notification, and is reset immediately upon
|
||||
guaranteed to receive the disconnect notification, and is reset immediately upon
|
||||
return from this function.
|
||||
*/
|
||||
void
|
||||
@@ -557,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
|
||||
@@ -567,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;
|
||||
@@ -613,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)
|
||||
@@ -625,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)
|
||||
{
|
||||
@@ -665,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 *
|
||||
@@ -696,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;
|
||||
|
||||
@@ -721,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;
|
||||
@@ -749,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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -765,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;
|
||||
|
||||
@@ -806,19 +832,19 @@ 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 *
|
||||
enet_peer_queue_incoming_command (ENetPeer * peer, const ENetProtocol * command, ENetPacket * packet, enet_uint32 fragmentCount)
|
||||
enet_peer_queue_incoming_command (ENetPeer * peer, const ENetProtocol * command, const void * data, size_t dataLength, enet_uint32 flags, enet_uint32 fragmentCount)
|
||||
{
|
||||
static ENetIncomingCommand dummyCommand;
|
||||
|
||||
@@ -827,9 +853,10 @@ enet_peer_queue_incoming_command (ENetPeer * peer, const ENetProtocol * command,
|
||||
enet_uint16 reliableWindow, currentWindow;
|
||||
ENetIncomingCommand * incomingCommand;
|
||||
ENetListIterator currentCommand;
|
||||
ENetPacket * packet = NULL;
|
||||
|
||||
if (peer -> state == ENET_PEER_STATE_DISCONNECT_LATER)
|
||||
goto freePacket;
|
||||
goto discardCommand;
|
||||
|
||||
if ((command -> header.command & ENET_PROTOCOL_COMMAND_MASK) != ENET_PROTOCOL_COMMAND_SEND_UNSEQUENCED)
|
||||
{
|
||||
@@ -841,7 +868,7 @@ enet_peer_queue_incoming_command (ENetPeer * peer, const ENetProtocol * command,
|
||||
reliableWindow += ENET_PEER_RELIABLE_WINDOWS;
|
||||
|
||||
if (reliableWindow < currentWindow || reliableWindow >= currentWindow + ENET_PEER_FREE_RELIABLE_WINDOWS - 1)
|
||||
goto freePacket;
|
||||
goto discardCommand;
|
||||
}
|
||||
|
||||
switch (command -> header.command & ENET_PROTOCOL_COMMAND_MASK)
|
||||
@@ -849,7 +876,7 @@ enet_peer_queue_incoming_command (ENetPeer * peer, const ENetProtocol * command,
|
||||
case ENET_PROTOCOL_COMMAND_SEND_FRAGMENT:
|
||||
case ENET_PROTOCOL_COMMAND_SEND_RELIABLE:
|
||||
if (reliableSequenceNumber == channel -> incomingReliableSequenceNumber)
|
||||
goto freePacket;
|
||||
goto discardCommand;
|
||||
|
||||
for (currentCommand = enet_list_previous (enet_list_end (& channel -> incomingReliableCommands));
|
||||
currentCommand != enet_list_end (& channel -> incomingReliableCommands);
|
||||
@@ -871,7 +898,7 @@ enet_peer_queue_incoming_command (ENetPeer * peer, const ENetProtocol * command,
|
||||
if (incomingCommand -> reliableSequenceNumber < reliableSequenceNumber)
|
||||
break;
|
||||
|
||||
goto freePacket;
|
||||
goto discardCommand;
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -882,7 +909,7 @@ enet_peer_queue_incoming_command (ENetPeer * peer, const ENetProtocol * command,
|
||||
|
||||
if (reliableSequenceNumber == channel -> incomingReliableSequenceNumber &&
|
||||
unreliableSequenceNumber <= channel -> incomingUnreliableSequenceNumber)
|
||||
goto freePacket;
|
||||
goto discardCommand;
|
||||
|
||||
for (currentCommand = enet_list_previous (enet_list_end (& channel -> incomingUnreliableCommands));
|
||||
currentCommand != enet_list_end (& channel -> incomingUnreliableCommands);
|
||||
@@ -913,7 +940,7 @@ enet_peer_queue_incoming_command (ENetPeer * peer, const ENetProtocol * command,
|
||||
if (incomingCommand -> unreliableSequenceNumber < unreliableSequenceNumber)
|
||||
break;
|
||||
|
||||
goto freePacket;
|
||||
goto discardCommand;
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -923,9 +950,16 @@ enet_peer_queue_incoming_command (ENetPeer * peer, const ENetProtocol * command,
|
||||
break;
|
||||
|
||||
default:
|
||||
goto freePacket;
|
||||
goto discardCommand;
|
||||
}
|
||||
|
||||
if (peer -> totalWaitingData >= peer -> host -> maximumWaitingData)
|
||||
goto notifyError;
|
||||
|
||||
packet = enet_packet_create (data, dataLength, flags);
|
||||
if (packet == NULL)
|
||||
goto notifyError;
|
||||
|
||||
incomingCommand = (ENetIncomingCommand *) enet_malloc (sizeof (ENetIncomingCommand));
|
||||
if (incomingCommand == NULL)
|
||||
goto notifyError;
|
||||
@@ -952,7 +986,11 @@ enet_peer_queue_incoming_command (ENetPeer * peer, const ENetProtocol * command,
|
||||
}
|
||||
|
||||
if (packet != NULL)
|
||||
++ packet -> referenceCount;
|
||||
{
|
||||
++ packet -> referenceCount;
|
||||
|
||||
peer -> totalWaitingData += packet -> dataLength;
|
||||
}
|
||||
|
||||
enet_list_insert (enet_list_next (currentCommand), incomingCommand);
|
||||
|
||||
@@ -960,17 +998,17 @@ 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;
|
||||
}
|
||||
|
||||
return incomingCommand;
|
||||
|
||||
freePacket:
|
||||
discardCommand:
|
||||
if (fragmentCount > 0)
|
||||
goto notifyError;
|
||||
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
solution "enet"
|
||||
configurations { "Debug", "Release" }
|
||||
platforms { "x32", "x64" }
|
||||
|
||||
project "enet_static"
|
||||
kind "StaticLib"
|
||||
language "C"
|
||||
|
||||
files { "*.c" }
|
||||
|
||||
includedirs { "include/" }
|
||||
|
||||
configuration "Debug"
|
||||
targetsuffix "d"
|
||||
|
||||
defines({ "DEBUG" })
|
||||
|
||||
flags { "Symbols" }
|
||||
|
||||
configuration "Release"
|
||||
defines({ "NDEBUG" })
|
||||
|
||||
flags { "Optimize" }
|
||||
|
||||
configuration { "Debug", "x64" }
|
||||
targetsuffix "64d"
|
||||
|
||||
configuration { "Release", "x64" }
|
||||
targetsuffix "64"
|
||||
|
||||
project "enet"
|
||||
kind "SharedLib"
|
||||
language "C"
|
||||
|
||||
files { "*.c" }
|
||||
|
||||
includedirs { "include/" }
|
||||
|
||||
defines({"ENET_DLL=1" })
|
||||
|
||||
configuration "Debug"
|
||||
targetsuffix "d"
|
||||
|
||||
defines({ "DEBUG" })
|
||||
|
||||
flags { "Symbols" }
|
||||
|
||||
configuration "Release"
|
||||
defines({ "NDEBUG" })
|
||||
|
||||
flags { "Optimize" }
|
||||
|
||||
configuration { "Debug", "x64" }
|
||||
targetsuffix "64d"
|
||||
|
||||
configuration { "Release", "x64" }
|
||||
targetsuffix "64"
|
||||
|
||||
|
||||
+332
-295
File diff suppressed because it is too large
Load Diff
@@ -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/ioctl.h>
|
||||
#include <sys/select.h>
|
||||
#include <sys/time.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <netdb.h>
|
||||
#include <unistd.h>
|
||||
@@ -19,9 +28,12 @@
|
||||
#define ENET_BUILDING_LIB 1
|
||||
#include "enet/enet.h"
|
||||
|
||||
#ifdef __APPLE__
|
||||
#ifdef HAS_POLL
|
||||
#undef HAS_POLL
|
||||
#if defined(__APPLE__)
|
||||
#if !defined(IPV6_RECVPKTINFO) || !defined(IPV6_PKTINFO)
|
||||
#warning Missing IPv6 socket option definitions. Is __APPLE_USE_RFC_3542 defined?
|
||||
#endif
|
||||
#ifndef HAS_POLL
|
||||
#define HAS_POLL 1
|
||||
#endif
|
||||
#ifndef HAS_FCNTL
|
||||
#define HAS_FCNTL 1
|
||||
@@ -38,20 +50,152 @@
|
||||
#ifndef HAS_SOCKLEN_T
|
||||
#define HAS_SOCKLEN_T 1
|
||||
#endif
|
||||
#ifndef HAS_GETADDRINFO
|
||||
#define HAS_GETADDRINFO 1
|
||||
#endif
|
||||
#ifndef HAS_GETNAMEINFO
|
||||
#define HAS_GETNAMEINFO 1
|
||||
#endif
|
||||
#elif defined(__vita__)
|
||||
// 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
|
||||
#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
|
||||
#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
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAS_POLL
|
||||
#include <sys/poll.h>
|
||||
#ifdef HAS_IOCTL
|
||||
#include <sys/ioctl.h>
|
||||
#endif
|
||||
|
||||
#ifndef HAS_SOCKLEN_T
|
||||
#ifdef HAS_POLL
|
||||
#include <poll.h>
|
||||
#endif
|
||||
|
||||
#if !defined(HAS_SOCKLEN_T) && !defined(__socklen_t_defined) && !defined(__HAIKU__)
|
||||
typedef int socklen_t;
|
||||
#endif
|
||||
|
||||
#ifndef SOMAXCONN
|
||||
#define SOMAXCONN 128
|
||||
#endif
|
||||
|
||||
#ifndef MSG_NOSIGNAL
|
||||
#define MSG_NOSIGNAL 0
|
||||
#endif
|
||||
@@ -72,7 +216,11 @@ enet_deinitialize (void)
|
||||
enet_uint32
|
||||
enet_host_random_seed (void)
|
||||
{
|
||||
return (enet_uint32) time (NULL);
|
||||
struct timeval timeVal;
|
||||
|
||||
gettimeofday (& timeVal, NULL);
|
||||
|
||||
return (timeVal.tv_sec * 1000) ^ (timeVal.tv_usec / 1000);
|
||||
}
|
||||
|
||||
enet_uint32
|
||||
@@ -91,141 +239,223 @@ 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)
|
||||
{
|
||||
if (address1 -> address.ss_family != address2 -> address.ss_family)
|
||||
return 0;
|
||||
|
||||
switch (address1 -> address.ss_family)
|
||||
{
|
||||
case AF_INET:
|
||||
{
|
||||
struct sockaddr_in *sin1, *sin2;
|
||||
sin1 = (struct sockaddr_in *) & address1 -> address;
|
||||
sin2 = (struct sockaddr_in *) & address2 -> address;
|
||||
return sin1 -> sin_port == sin2 -> sin_port &&
|
||||
sin1 -> sin_addr.s_addr == sin2 -> sin_addr.s_addr;
|
||||
}
|
||||
#ifdef AF_INET6
|
||||
case AF_INET6:
|
||||
{
|
||||
struct sockaddr_in6 *sin6a, *sin6b;
|
||||
sin6a = (struct sockaddr_in6 *) & address1 -> address;
|
||||
sin6b = (struct sockaddr_in6 *) & address2 -> address;
|
||||
return sin6a -> sin6_port == sin6b -> sin6_port &&
|
||||
! memcmp (& sin6a -> sin6_addr, & sin6b -> sin6_addr, sizeof (sin6a -> sin6_addr));
|
||||
}
|
||||
#endif
|
||||
default:
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
enet_address_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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
enet_address_set_port (ENetAddress * address, enet_uint16 port)
|
||||
{
|
||||
if (address -> address.ss_family == AF_INET)
|
||||
{
|
||||
struct sockaddr_in *sin = (struct sockaddr_in *) &address -> address;
|
||||
sin -> sin_port = ENET_HOST_TO_NET_16 (port);
|
||||
return 0;
|
||||
}
|
||||
#ifdef AF_INET6
|
||||
else if (address -> address.ss_family == AF_INET6)
|
||||
{
|
||||
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) &address -> address;
|
||||
sin6 -> sin6_port = ENET_HOST_TO_NET_16 (port);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
enet_address_set_address (ENetAddress * address, struct sockaddr * addr, socklen_t addrlen)
|
||||
{
|
||||
if (addrlen > sizeof(struct sockaddr_storage))
|
||||
return -1;
|
||||
|
||||
memcpy (&address->address, addr, addrlen);
|
||||
address->addressLength = addrlen;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
enet_address_set_host (ENetAddress * address, const char * name)
|
||||
{
|
||||
struct hostent * hostEntry = NULL;
|
||||
#ifdef HAS_GETHOSTBYNAME_R
|
||||
struct hostent hostData;
|
||||
char buffer [2048];
|
||||
int errnum;
|
||||
struct addrinfo hints, * resultList = NULL, * result = NULL;
|
||||
|
||||
#if defined(linux) || defined(__linux) || defined(__linux__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
|
||||
gethostbyname_r (name, & hostData, buffer, sizeof (buffer), & hostEntry, & errnum);
|
||||
#else
|
||||
hostEntry = gethostbyname_r (name, & hostData, buffer, sizeof (buffer), & errnum);
|
||||
#endif
|
||||
#else
|
||||
hostEntry = gethostbyname (name);
|
||||
#endif
|
||||
memset (& hints, 0, sizeof (hints));
|
||||
hints.ai_family = AF_UNSPEC;
|
||||
hints.ai_flags = AI_ADDRCONFIG;
|
||||
|
||||
if (hostEntry == NULL ||
|
||||
hostEntry -> h_addrtype != AF_INET)
|
||||
if (getaddrinfo (name, NULL, & hints, & resultList) != 0)
|
||||
return -1;
|
||||
|
||||
for (result = resultList; result != NULL; result = result -> ai_next)
|
||||
{
|
||||
#ifdef HAS_INET_PTON
|
||||
if (! inet_pton (AF_INET, name, & address -> host))
|
||||
#else
|
||||
if (! inet_aton (name, (struct in_addr *) & address -> host))
|
||||
#endif
|
||||
return -1;
|
||||
memcpy (& address -> address, result -> ai_addr, result -> ai_addrlen);
|
||||
address -> addressLength = result -> ai_addrlen;
|
||||
|
||||
freeaddrinfo (resultList);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
address -> host = * (enet_uint32 *) hostEntry -> h_addr_list [0];
|
||||
if (resultList != NULL)
|
||||
freeaddrinfo (resultList);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
enet_address_get_host_ip (const ENetAddress * address, char * name, size_t nameLength)
|
||||
{
|
||||
#ifdef HAS_INET_NTOP
|
||||
if (inet_ntop (AF_INET, & address -> host, name, nameLength) == NULL)
|
||||
#else
|
||||
char * addr = inet_ntoa (* (struct in_addr *) & address -> host);
|
||||
if (addr != NULL)
|
||||
strncpy (name, addr, nameLength);
|
||||
else
|
||||
#endif
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
enet_address_get_host (const ENetAddress * address, char * name, size_t nameLength)
|
||||
{
|
||||
struct in_addr in;
|
||||
struct hostent * hostEntry = NULL;
|
||||
#ifdef HAS_GETHOSTBYADDR_R
|
||||
struct hostent hostData;
|
||||
char buffer [2048];
|
||||
int errnum;
|
||||
|
||||
in.s_addr = address -> host;
|
||||
|
||||
#if defined(linux) || defined(__linux) || defined(__linux__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
|
||||
gethostbyaddr_r ((char *) & in, sizeof (struct in_addr), AF_INET, & hostData, buffer, sizeof (buffer), & hostEntry, & errnum);
|
||||
#else
|
||||
hostEntry = gethostbyaddr_r ((char *) & in, sizeof (struct in_addr), AF_INET, & hostData, buffer, sizeof (buffer), & errnum);
|
||||
#endif
|
||||
#else
|
||||
in.s_addr = address -> host;
|
||||
|
||||
hostEntry = gethostbyaddr ((char *) & in, sizeof (struct in_addr), AF_INET);
|
||||
#endif
|
||||
|
||||
if (hostEntry == NULL)
|
||||
return enet_address_get_host_ip (address, name, nameLength);
|
||||
|
||||
strncpy (name, hostEntry -> h_name, nameLength);
|
||||
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
enet_socket_bind (ENetSocket socket, const ENetAddress * address)
|
||||
{
|
||||
struct sockaddr_in sin;
|
||||
|
||||
memset (& sin, 0, sizeof (struct sockaddr_in));
|
||||
|
||||
sin.sin_family = AF_INET;
|
||||
|
||||
if (address != NULL)
|
||||
{
|
||||
sin.sin_port = ENET_HOST_TO_NET_16 (address -> port);
|
||||
sin.sin_addr.s_addr = address -> host;
|
||||
}
|
||||
else
|
||||
{
|
||||
sin.sin_port = 0;
|
||||
sin.sin_addr.s_addr = INADDR_ANY;
|
||||
}
|
||||
|
||||
return bind (socket,
|
||||
(struct sockaddr *) & sin,
|
||||
sizeof (struct sockaddr_in));
|
||||
(struct sockaddr *) & address -> address,
|
||||
address -> addressLength);
|
||||
}
|
||||
|
||||
int
|
||||
enet_socket_get_address (ENetSocket socket, ENetAddress * address)
|
||||
{
|
||||
struct sockaddr_in sin;
|
||||
socklen_t sinLength = sizeof (struct sockaddr_in);
|
||||
address -> addressLength = sizeof (address -> address);
|
||||
|
||||
if (getsockname (socket, (struct sockaddr *) & sin, & sinLength) == -1)
|
||||
if (getsockname (socket, (struct sockaddr *) & address -> address, & address -> addressLength) == -1)
|
||||
return -1;
|
||||
|
||||
address -> host = (enet_uint32) sin.sin_addr.s_addr;
|
||||
address -> port = ENET_NET_TO_HOST_16 (sin.sin_port);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
int
|
||||
enet_socket_listen (ENetSocket socket, int backlog)
|
||||
{
|
||||
return listen (socket, backlog < 0 ? SOMAXCONN : backlog);
|
||||
}
|
||||
|
||||
ENetSocket
|
||||
enet_socket_create (ENetSocketType type)
|
||||
enet_socket_create (int af, ENetSocketType type)
|
||||
{
|
||||
return socket (PF_INET, type == ENET_SOCKET_TYPE_DATAGRAM ? SOCK_DGRAM : SOCK_STREAM, 0);
|
||||
ENetSocket sock = socket (af, type == ENET_SOCKET_TYPE_DATAGRAM ? SOCK_DGRAM : SOCK_STREAM, 0);
|
||||
if (sock < 0) {
|
||||
return sock;
|
||||
}
|
||||
|
||||
#ifdef IPV6_V6ONLY
|
||||
if (af == AF_INET6) {
|
||||
int off = 0;
|
||||
|
||||
// Some OSes don't support dual-stack sockets, so ignore failures
|
||||
setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&off, sizeof(off));
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef IP_PKTINFO
|
||||
{
|
||||
// We turn this on for all sockets because it may be required for IPv4
|
||||
// traffic on dual-stack sockets on some OSes.
|
||||
int on = 1;
|
||||
setsockopt(sock, IPPROTO_IP, IP_PKTINFO, (char *)&on, sizeof(on));
|
||||
}
|
||||
#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
|
||||
@@ -236,14 +466,14 @@ enet_socket_set_option (ENetSocket socket, ENetSocketOption option, int value)
|
||||
{
|
||||
case ENET_SOCKOPT_NONBLOCK:
|
||||
#ifdef HAS_FCNTL
|
||||
result = fcntl (socket, F_SETFL, O_NONBLOCK | fcntl (socket, F_GETFL));
|
||||
result = fcntl (socket, F_SETFL, (value ? O_NONBLOCK : 0) | (fcntl (socket, F_GETFL, 0) & ~O_NONBLOCK));
|
||||
#else
|
||||
#ifdef HAS_IOCTL
|
||||
result = ioctl (socket, FIONBIO, & value);
|
||||
#else
|
||||
result = setsockopt (socket, SOL_SOCKET, SO_NONBLOCK, (char *) & value, sizeof(int));
|
||||
#endif
|
||||
#endif
|
||||
break;
|
||||
|
||||
case ENET_SOCKOPT_BROADCAST:
|
||||
result = setsockopt (socket, SOL_SOCKET, SO_BROADCAST, (char *) & value, sizeof (int));
|
||||
break;
|
||||
|
||||
case ENET_SOCKOPT_REUSEADDR:
|
||||
@@ -258,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;
|
||||
@@ -275,11 +506,39 @@ enet_socket_set_option (ENetSocket socket, ENetSocketOption option, int value)
|
||||
result = setsockopt (socket, SOL_SOCKET, SO_SNDTIMEO, (char *) & timeVal, sizeof (struct timeval));
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
case ENET_SOCKOPT_NODELAY:
|
||||
result = setsockopt (socket, IPPROTO_TCP, TCP_NODELAY, (char *) & value, sizeof (int));
|
||||
break;
|
||||
|
||||
case ENET_SOCKOPT_QOS:
|
||||
#ifdef SO_NET_SERVICE_TYPE
|
||||
// iOS/macOS
|
||||
value = value ? NET_SERVICE_TYPE_VO : NET_SERVICE_TYPE_BE;
|
||||
result = setsockopt (socket, SOL_SOCKET, SO_NET_SERVICE_TYPE, (char *) & value, sizeof (int));
|
||||
#endif
|
||||
#ifdef IP_TOS
|
||||
// UNIX - IPv4
|
||||
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 | 0x01): 0; // DSCP: Expedited Forwarding + ECT(1) (L4S)
|
||||
result = setsockopt (socket, IPPROTO_IPV6, IPV6_TCLASS, (char *) & value, sizeof (int));
|
||||
#endif
|
||||
#ifdef SO_PRIORITY
|
||||
// Linux
|
||||
value = value ? 6 : 0; // Max priority without NET_CAP_ADMIN
|
||||
result = setsockopt (socket, SOL_SOCKET, SO_PRIORITY, (char *) & value, sizeof (int));
|
||||
#endif
|
||||
break;
|
||||
|
||||
case ENET_SOCKOPT_TTL:
|
||||
result = setsockopt (socket, IPPROTO_IP, IP_TTL, (char *) & value, sizeof (int));
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -298,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;
|
||||
}
|
||||
@@ -307,16 +571,9 @@ enet_socket_get_option (ENetSocket socket, ENetSocketOption option, int * value)
|
||||
int
|
||||
enet_socket_connect (ENetSocket socket, const ENetAddress * address)
|
||||
{
|
||||
struct sockaddr_in sin;
|
||||
int result;
|
||||
|
||||
memset (& sin, 0, sizeof (struct sockaddr_in));
|
||||
|
||||
sin.sin_family = AF_INET;
|
||||
sin.sin_port = ENET_HOST_TO_NET_16 (address -> port);
|
||||
sin.sin_addr.s_addr = address -> host;
|
||||
|
||||
result = connect (socket, (struct sockaddr *) & sin, sizeof (struct sockaddr_in));
|
||||
result = connect (socket, (struct sockaddr *) & address -> address, address -> addressLength);
|
||||
if (result == -1 && errno == EINPROGRESS)
|
||||
return 0;
|
||||
|
||||
@@ -327,25 +584,20 @@ ENetSocket
|
||||
enet_socket_accept (ENetSocket socket, ENetAddress * address)
|
||||
{
|
||||
int result;
|
||||
struct sockaddr_in sin;
|
||||
socklen_t sinLength = sizeof (struct sockaddr_in);
|
||||
|
||||
result = accept (socket,
|
||||
address != NULL ? (struct sockaddr *) & sin : NULL,
|
||||
address != NULL ? & sinLength : NULL);
|
||||
|
||||
if (address != NULL)
|
||||
address -> addressLength = sizeof (address -> address);
|
||||
|
||||
result = accept (socket,
|
||||
address != NULL ? (struct sockaddr *) & address -> address : NULL,
|
||||
address != NULL ? & address -> addressLength : NULL);
|
||||
|
||||
if (result == -1)
|
||||
return ENET_SOCKET_NULL;
|
||||
|
||||
if (address != NULL)
|
||||
{
|
||||
address -> host = (enet_uint32) sin.sin_addr.s_addr;
|
||||
address -> port = ENET_NET_TO_HOST_16 (sin.sin_port);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int
|
||||
enet_socket_shutdown (ENetSocket socket, ENetSocketShutdown how)
|
||||
{
|
||||
@@ -361,39 +613,145 @@ enet_socket_destroy (ENetSocket socket)
|
||||
|
||||
int
|
||||
enet_socket_send (ENetSocket socket,
|
||||
const ENetAddress * address,
|
||||
const ENetAddress * peerAddress,
|
||||
const ENetAddress * localAddress,
|
||||
const ENetBuffer * buffers,
|
||||
size_t bufferCount)
|
||||
{
|
||||
struct msghdr msgHdr;
|
||||
struct sockaddr_in sin;
|
||||
int sentLength;
|
||||
|
||||
#ifdef NO_MSGAPI
|
||||
void* sendBuffer;
|
||||
size_t sendLength;
|
||||
|
||||
if (bufferCount > 1)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
sendLength = 0;
|
||||
for (i = 0; i < bufferCount; i++)
|
||||
{
|
||||
sendLength += buffers[i].dataLength;
|
||||
}
|
||||
|
||||
sendBuffer = malloc (sendLength);
|
||||
if (sendBuffer == NULL)
|
||||
return -1;
|
||||
|
||||
sendLength = 0;
|
||||
for (i = 0; i < bufferCount; i++)
|
||||
{
|
||||
memcpy (& ((unsigned char *)sendBuffer)[sendLength], buffers[i].data, buffers[i].dataLength);
|
||||
sendLength += buffers[i].dataLength;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sendBuffer = buffers[0].data;
|
||||
sendLength = buffers[0].dataLength;
|
||||
}
|
||||
|
||||
sentLength = sendto (socket, sendBuffer, sendLength, MSG_NOSIGNAL,
|
||||
(struct sockaddr *) & peerAddress -> address, peerAddress -> addressLength);
|
||||
|
||||
if (bufferCount > 1)
|
||||
free(sendBuffer);
|
||||
#else
|
||||
struct msghdr msgHdr;
|
||||
char controlBufData[1024];
|
||||
|
||||
memset (& msgHdr, 0, sizeof (struct msghdr));
|
||||
|
||||
if (address != NULL)
|
||||
if (peerAddress != NULL)
|
||||
{
|
||||
memset (& sin, 0, sizeof (struct sockaddr_in));
|
||||
|
||||
sin.sin_family = AF_INET;
|
||||
sin.sin_port = ENET_HOST_TO_NET_16 (address -> port);
|
||||
sin.sin_addr.s_addr = address -> host;
|
||||
|
||||
msgHdr.msg_name = & sin;
|
||||
msgHdr.msg_namelen = sizeof (struct sockaddr_in);
|
||||
msgHdr.msg_name = (void*) & peerAddress -> address;
|
||||
msgHdr.msg_namelen = peerAddress -> addressLength;
|
||||
}
|
||||
|
||||
msgHdr.msg_iov = (struct iovec *) buffers;
|
||||
msgHdr.msg_iovlen = bufferCount;
|
||||
|
||||
// We always send traffic from the same local address as we last received
|
||||
// from this peer to ensure it correctly recognizes our responses as
|
||||
// coming from the expected host.
|
||||
if (localAddress != NULL) {
|
||||
#ifdef IP_PKTINFO
|
||||
if (localAddress->address.ss_family == AF_INET) {
|
||||
struct in_pktinfo pktInfo;
|
||||
|
||||
pktInfo.ipi_spec_dst = ((struct sockaddr_in*)&localAddress->address)->sin_addr;
|
||||
pktInfo.ipi_ifindex = 0; // Unspecified
|
||||
|
||||
msgHdr.msg_control = controlBufData;
|
||||
msgHdr.msg_controllen = CMSG_SPACE(sizeof(pktInfo));
|
||||
|
||||
struct cmsghdr *chdr = CMSG_FIRSTHDR(&msgHdr);
|
||||
chdr->cmsg_level = IPPROTO_IP;
|
||||
chdr->cmsg_type = IP_PKTINFO;
|
||||
chdr->cmsg_len = CMSG_LEN(sizeof(pktInfo));
|
||||
memcpy(CMSG_DATA(chdr), &pktInfo, sizeof(pktInfo));
|
||||
}
|
||||
#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;
|
||||
@@ -401,24 +759,45 @@ enet_socket_send (ENetSocket socket,
|
||||
|
||||
int
|
||||
enet_socket_receive (ENetSocket socket,
|
||||
ENetAddress * address,
|
||||
ENetAddress * peerAddress,
|
||||
ENetAddress * localAddress,
|
||||
ENetBuffer * buffers,
|
||||
size_t bufferCount)
|
||||
{
|
||||
struct msghdr msgHdr;
|
||||
struct sockaddr_in sin;
|
||||
int recvLength;
|
||||
|
||||
#ifdef NO_MSGAPI
|
||||
// This will ONLY work with a single buffer!
|
||||
|
||||
peerAddress -> addressLength = sizeof (peerAddress -> address);
|
||||
recvLength = recvfrom (socket, buffers[0].data, buffers[0].dataLength, MSG_NOSIGNAL,
|
||||
(struct sockaddr *) & peerAddress -> address, & peerAddress -> addressLength);
|
||||
|
||||
if (recvLength == -1)
|
||||
{
|
||||
if (errno == EWOULDBLOCK)
|
||||
return 0;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
return recvLength;
|
||||
#else
|
||||
struct msghdr msgHdr;
|
||||
char controlBufData[1024];
|
||||
|
||||
memset (& msgHdr, 0, sizeof (struct msghdr));
|
||||
|
||||
if (address != NULL)
|
||||
if (peerAddress != NULL)
|
||||
{
|
||||
msgHdr.msg_name = & sin;
|
||||
msgHdr.msg_namelen = sizeof (struct sockaddr_in);
|
||||
msgHdr.msg_name = & peerAddress -> address;
|
||||
msgHdr.msg_namelen = sizeof (peerAddress -> address);
|
||||
}
|
||||
|
||||
msgHdr.msg_iov = (struct iovec *) buffers;
|
||||
msgHdr.msg_iovlen = bufferCount;
|
||||
msgHdr.msg_control = controlBufData;
|
||||
msgHdr.msg_controllen = sizeof(controlBufData);
|
||||
|
||||
recvLength = recvmsg (socket, & msgHdr, MSG_NOSIGNAL);
|
||||
|
||||
@@ -432,16 +811,65 @@ enet_socket_receive (ENetSocket socket,
|
||||
|
||||
#ifdef HAS_MSGHDR_FLAGS
|
||||
if (msgHdr.msg_flags & MSG_TRUNC)
|
||||
return -1;
|
||||
return -2;
|
||||
#endif
|
||||
|
||||
if (address != NULL)
|
||||
{
|
||||
address -> host = (enet_uint32) sin.sin_addr.s_addr;
|
||||
address -> port = ENET_NET_TO_HOST_16 (sin.sin_port);
|
||||
// Retrieve the local address that this traffic was received on
|
||||
// to ensure we respond from the correct address/interface.
|
||||
if (localAddress != NULL) {
|
||||
for (struct cmsghdr *chdr = CMSG_FIRSTHDR(&msgHdr); chdr != NULL; chdr = CMSG_NXTHDR(&msgHdr, chdr)) {
|
||||
#ifdef IP_PKTINFO
|
||||
if (chdr->cmsg_level == IPPROTO_IP && chdr->cmsg_type == IP_PKTINFO) {
|
||||
struct sockaddr_in *localAddr = (struct sockaddr_in*)&localAddress->address;
|
||||
|
||||
localAddr->sin_family = AF_INET;
|
||||
localAddr->sin_addr = ((struct in_pktinfo*)CMSG_DATA(chdr))->ipi_addr;
|
||||
|
||||
localAddress->addressLength = sizeof(*localAddr);
|
||||
break;
|
||||
}
|
||||
#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
|
||||
}
|
||||
|
||||
int
|
||||
@@ -461,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;
|
||||
|
||||
@@ -471,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)
|
||||
{
|
||||
@@ -492,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;
|
||||
|
||||
@@ -524,7 +963,7 @@ enet_socket_wait (ENetSocket socket, enet_uint32 * condition, enet_uint32 timeou
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -544,4 +983,3 @@ enet_socket_wait (ENetSocket socket, enet_uint32 * condition, enet_uint32 timeou
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1,148 +1,261 @@
|
||||
/**
|
||||
/**
|
||||
@file win32.c
|
||||
@brief ENet Win32 system specific functions
|
||||
*/
|
||||
#ifdef _WIN32
|
||||
#if defined(_WIN32) && !defined(NXDK)
|
||||
|
||||
#include <time.h>
|
||||
#define ENET_BUILDING_LIB 1
|
||||
#include "enet/enet.h"
|
||||
#include <windows.h>
|
||||
#include <mswsock.h>
|
||||
#ifndef HAS_QOS_FLOWID
|
||||
typedef UINT32 QOS_FLOWID;
|
||||
#endif
|
||||
#ifndef HAS_PQOS_FLOWID
|
||||
typedef UINT32 *PQOS_FLOWID;
|
||||
#endif
|
||||
#include <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 (1, 1);
|
||||
WORD versionRequested = MAKEWORD (2, 0);
|
||||
WSADATA wsaData;
|
||||
|
||||
|
||||
if (WSAStartup (versionRequested, & wsaData))
|
||||
return -1;
|
||||
|
||||
if (LOBYTE (wsaData.wVersion) != 1||
|
||||
HIBYTE (wsaData.wVersion) != 1)
|
||||
if (LOBYTE (wsaData.wVersion) != 2||
|
||||
HIBYTE (wsaData.wVersion) != 0)
|
||||
{
|
||||
WSACleanup ();
|
||||
|
||||
|
||||
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)
|
||||
{
|
||||
timeEndPeriod (1);
|
||||
#ifdef HAS_QWAVE
|
||||
qosAddedFlow = FALSE;
|
||||
qosFlowId = 0;
|
||||
enableEcn = FALSE;
|
||||
|
||||
if (qosHandle != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
pfnQOSCloseHandle(qosHandle);
|
||||
qosHandle = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
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
|
||||
enet_address_set_port (ENetAddress * address, enet_uint16 port)
|
||||
{
|
||||
if (address -> address.ss_family == AF_INET)
|
||||
{
|
||||
struct sockaddr_in *sin = (struct sockaddr_in *) &address -> address;
|
||||
sin -> sin_port = ENET_HOST_TO_NET_16 (port);
|
||||
return 0;
|
||||
}
|
||||
else if (address -> address.ss_family == AF_INET6)
|
||||
{
|
||||
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) &address -> address;
|
||||
sin6 -> sin6_port = ENET_HOST_TO_NET_16 (port);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
enet_address_set_address (ENetAddress * address, struct sockaddr * addr, socklen_t addrlen)
|
||||
{
|
||||
if (addrlen > sizeof(struct sockaddr_storage))
|
||||
return -1;
|
||||
|
||||
memcpy (&address->address, addr, addrlen);
|
||||
address->addressLength = addrlen;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
enet_address_equal (ENetAddress * address1, ENetAddress * address2)
|
||||
{
|
||||
if (address1 -> address.ss_family != address2 -> address.ss_family)
|
||||
return 0;
|
||||
|
||||
switch (address1 -> address.ss_family)
|
||||
{
|
||||
case AF_INET:
|
||||
{
|
||||
struct sockaddr_in *sin1, *sin2;
|
||||
sin1 = (struct sockaddr_in *) & address1 -> address;
|
||||
sin2 = (struct sockaddr_in *) & address2 -> address;
|
||||
return sin1 -> sin_port == sin2 -> sin_port &&
|
||||
sin1 -> sin_addr.S_un.S_addr == sin2 -> sin_addr.S_un.S_addr;
|
||||
}
|
||||
case AF_INET6:
|
||||
{
|
||||
struct sockaddr_in6 *sin6a, *sin6b;
|
||||
sin6a = (struct sockaddr_in6 *) & address1 -> address;
|
||||
sin6b = (struct sockaddr_in6 *) & address2 -> address;
|
||||
return sin6a -> sin6_port == sin6b -> sin6_port &&
|
||||
! memcmp (& sin6a -> sin6_addr, & sin6b -> sin6_addr, sizeof (sin6a -> sin6_addr));
|
||||
}
|
||||
default:
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
enet_address_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)
|
||||
{
|
||||
struct hostent * hostEntry;
|
||||
struct addrinfo hints, * resultList = NULL, * result = NULL;
|
||||
|
||||
hostEntry = gethostbyname (name);
|
||||
if (hostEntry == NULL ||
|
||||
hostEntry -> h_addrtype != AF_INET)
|
||||
memset (& hints, 0, sizeof (hints));
|
||||
hints.ai_family = AF_UNSPEC;
|
||||
hints.ai_flags = AI_ADDRCONFIG;
|
||||
|
||||
if (getaddrinfo (name, NULL, & hints, & resultList) != 0)
|
||||
return -1;
|
||||
|
||||
for (result = resultList; result != NULL; result = result -> ai_next)
|
||||
{
|
||||
unsigned long host = inet_addr (name);
|
||||
if (host == INADDR_NONE)
|
||||
return -1;
|
||||
address -> host = host;
|
||||
memcpy (& address -> address, result -> ai_addr, result -> ai_addrlen);
|
||||
address -> addressLength = result -> ai_addrlen;
|
||||
|
||||
freeaddrinfo (resultList);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
address -> host = * (enet_uint32 *) hostEntry -> h_addr_list [0];
|
||||
if (resultList != NULL)
|
||||
freeaddrinfo (resultList);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
enet_address_get_host_ip (const ENetAddress * address, char * name, size_t nameLength)
|
||||
{
|
||||
char * addr = inet_ntoa (* (struct in_addr *) & address -> host);
|
||||
if (addr == NULL)
|
||||
return -1;
|
||||
strncpy (name, addr, nameLength);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
enet_address_get_host (const ENetAddress * address, char * name, size_t nameLength)
|
||||
{
|
||||
struct in_addr in;
|
||||
struct hostent * hostEntry;
|
||||
|
||||
in.s_addr = address -> host;
|
||||
|
||||
hostEntry = gethostbyaddr ((char *) & in, sizeof (struct in_addr), AF_INET);
|
||||
if (hostEntry == NULL)
|
||||
return enet_address_get_host_ip (address, name, nameLength);
|
||||
|
||||
strncpy (name, hostEntry -> h_name, nameLength);
|
||||
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
enet_socket_bind (ENetSocket socket, const ENetAddress * address)
|
||||
{
|
||||
struct sockaddr_in sin;
|
||||
|
||||
memset (& sin, 0, sizeof (struct sockaddr_in));
|
||||
|
||||
sin.sin_family = AF_INET;
|
||||
|
||||
if (address != NULL)
|
||||
{
|
||||
sin.sin_port = ENET_HOST_TO_NET_16 (address -> port);
|
||||
sin.sin_addr.s_addr = address -> host;
|
||||
}
|
||||
else
|
||||
{
|
||||
sin.sin_port = 0;
|
||||
sin.sin_addr.s_addr = INADDR_ANY;
|
||||
}
|
||||
|
||||
return bind (socket,
|
||||
(struct sockaddr *) & sin,
|
||||
sizeof (struct sockaddr_in)) == SOCKET_ERROR ? -1 : 0;
|
||||
(struct sockaddr *) & address -> address,
|
||||
address -> addressLength);
|
||||
}
|
||||
|
||||
int
|
||||
enet_socket_get_address (ENetSocket socket, ENetAddress * address)
|
||||
{
|
||||
struct sockaddr_in sin;
|
||||
int sinLength = sizeof (struct sockaddr_in);
|
||||
address -> addressLength = sizeof (address -> address);
|
||||
|
||||
if (getsockname (socket, (struct sockaddr *) & sin, & sinLength) == -1)
|
||||
if (getsockname (socket, (struct sockaddr *) & address -> address, & address -> addressLength) == -1)
|
||||
return -1;
|
||||
|
||||
address -> host = (enet_uint32) sin.sin_addr.s_addr;
|
||||
address -> port = ENET_NET_TO_HOST_16 (sin.sin_port);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -153,9 +266,48 @@ enet_socket_listen (ENetSocket socket, int backlog)
|
||||
}
|
||||
|
||||
ENetSocket
|
||||
enet_socket_create (ENetSocketType type)
|
||||
enet_socket_create (int af, ENetSocketType type)
|
||||
{
|
||||
return socket (PF_INET, type == ENET_SOCKET_TYPE_DATAGRAM ? SOCK_DGRAM : SOCK_STREAM, 0);
|
||||
SOCKET sock = socket (af, type == ENET_SOCKET_TYPE_DATAGRAM ? SOCK_DGRAM : SOCK_STREAM, 0);
|
||||
if (sock == INVALID_SOCKET)
|
||||
return INVALID_SOCKET;
|
||||
|
||||
DWORD bytesReturned;
|
||||
GUID wsaRecvMsgGuid = WSAID_WSARECVMSG;
|
||||
if (WSAIoctl(sock, SIO_GET_EXTENSION_FUNCTION_POINTER, &wsaRecvMsgGuid, sizeof(wsaRecvMsgGuid),
|
||||
&pfnWSARecvMsg, sizeof(pfnWSARecvMsg), &bytesReturned, NULL, NULL) == SOCKET_ERROR) {
|
||||
closesocket(sock);
|
||||
return INVALID_SOCKET;
|
||||
}
|
||||
|
||||
BOOL val;
|
||||
|
||||
// Enable dual-stack operation for IPv6 sockets
|
||||
if (af == AF_INET6) {
|
||||
val = FALSE;
|
||||
if (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&val, sizeof(val)) == SOCKET_ERROR) {
|
||||
closesocket(sock);
|
||||
return INVALID_SOCKET;
|
||||
}
|
||||
}
|
||||
|
||||
// Enable returning local address info for IPv4 and dual-stack sockets
|
||||
val = TRUE;
|
||||
if (setsockopt(sock, IPPROTO_IP, IP_PKTINFO, (char*)&val, sizeof(val)) == SOCKET_ERROR) {
|
||||
closesocket(sock);
|
||||
return INVALID_SOCKET;
|
||||
}
|
||||
|
||||
// Enable returning local address info for IPv6 and dual-stack sockets
|
||||
if (af == AF_INET6) {
|
||||
val = TRUE;
|
||||
if (setsockopt(sock, IPPROTO_IPV6, IPV6_PKTINFO, (char*)&val, sizeof(val)) == SOCKET_ERROR) {
|
||||
closesocket(sock);
|
||||
return INVALID_SOCKET;
|
||||
}
|
||||
}
|
||||
|
||||
return sock;
|
||||
}
|
||||
|
||||
int
|
||||
@@ -171,10 +323,6 @@ enet_socket_set_option (ENetSocket socket, ENetSocketOption option, int value)
|
||||
break;
|
||||
}
|
||||
|
||||
case ENET_SOCKOPT_BROADCAST:
|
||||
result = setsockopt (socket, SOL_SOCKET, SO_BROADCAST, (char *) & value, sizeof (int));
|
||||
break;
|
||||
|
||||
case ENET_SOCKOPT_REUSEADDR:
|
||||
result = setsockopt (socket, SOL_SOCKET, SO_REUSEADDR, (char *) & value, sizeof (int));
|
||||
break;
|
||||
@@ -199,6 +347,40 @@ enet_socket_set_option (ENetSocket socket, ENetSocketOption option, int value)
|
||||
result = setsockopt (socket, IPPROTO_TCP, TCP_NODELAY, (char *) & value, sizeof (int));
|
||||
break;
|
||||
|
||||
case ENET_SOCKOPT_QOS:
|
||||
{
|
||||
// Enable ECN marking on Windows 10 if QOS is enabled
|
||||
enableEcn = value != 0 && IsWindows10OrGreater();
|
||||
|
||||
#ifdef HAS_QWAVE
|
||||
if (value)
|
||||
{
|
||||
QOS_VERSION qosVersion;
|
||||
|
||||
qosVersion.MajorVersion = 1;
|
||||
qosVersion.MinorVersion = 0;
|
||||
if (pfnQOSCreateHandle == NULL || !pfnQOSCreateHandle(&qosVersion, &qosHandle))
|
||||
{
|
||||
qosHandle = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
}
|
||||
else if (qosHandle != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
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;
|
||||
}
|
||||
@@ -216,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;
|
||||
}
|
||||
@@ -225,16 +412,9 @@ enet_socket_get_option (ENetSocket socket, ENetSocketOption option, int * value)
|
||||
int
|
||||
enet_socket_connect (ENetSocket socket, const ENetAddress * address)
|
||||
{
|
||||
struct sockaddr_in sin;
|
||||
int result;
|
||||
|
||||
memset (& sin, 0, sizeof (struct sockaddr_in));
|
||||
|
||||
sin.sin_family = AF_INET;
|
||||
sin.sin_port = ENET_HOST_TO_NET_16 (address -> port);
|
||||
sin.sin_addr.s_addr = address -> host;
|
||||
|
||||
result = connect (socket, (struct sockaddr *) & sin, sizeof (struct sockaddr_in));
|
||||
result = connect (socket, (struct sockaddr *) & address -> address, address -> addressLength);
|
||||
if (result == SOCKET_ERROR && WSAGetLastError () != WSAEWOULDBLOCK)
|
||||
return -1;
|
||||
|
||||
@@ -244,22 +424,17 @@ enet_socket_connect (ENetSocket socket, const ENetAddress * address)
|
||||
ENetSocket
|
||||
enet_socket_accept (ENetSocket socket, ENetAddress * address)
|
||||
{
|
||||
SOCKET result;
|
||||
struct sockaddr_in sin;
|
||||
int sinLength = sizeof (struct sockaddr_in);
|
||||
|
||||
result = accept (socket,
|
||||
address != NULL ? (struct sockaddr *) & sin : NULL,
|
||||
address != NULL ? & sinLength : NULL);
|
||||
|
||||
if (result == INVALID_SOCKET)
|
||||
return ENET_SOCKET_NULL;
|
||||
int result;
|
||||
|
||||
if (address != NULL)
|
||||
{
|
||||
address -> host = (enet_uint32) sin.sin_addr.s_addr;
|
||||
address -> port = ENET_NET_TO_HOST_16 (sin.sin_port);
|
||||
}
|
||||
address -> addressLength = sizeof (address -> address);
|
||||
|
||||
result = accept (socket,
|
||||
address != NULL ? (struct sockaddr *) & address -> address : NULL,
|
||||
address != NULL ? & address -> addressLength : NULL);
|
||||
|
||||
if (result == -1)
|
||||
return ENET_SOCKET_NULL;
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -279,36 +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)
|
||||
{
|
||||
struct sockaddr_in sin;
|
||||
DWORD sentLength;
|
||||
WSAMSG msg = { 0 };
|
||||
char controlBufData[1024];
|
||||
PWSACMSGHDR chdr = NULL;
|
||||
|
||||
if (address != NULL)
|
||||
#ifdef HAS_QWAVE
|
||||
if (!qosAddedFlow && qosHandle != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
memset (& sin, 0, sizeof (struct sockaddr_in));
|
||||
BOOL isV4MappedV6Addr =
|
||||
peerAddress->address.ss_family == AF_INET6 &&
|
||||
IN6_IS_ADDR_V4MAPPED(&((PSOCKADDR_IN6)&peerAddress->address)->sin6_addr);
|
||||
|
||||
sin.sin_family = AF_INET;
|
||||
sin.sin_port = ENET_HOST_TO_NET_16 (address -> port);
|
||||
sin.sin_addr.s_addr = address -> host;
|
||||
// qWAVE doesn't properly support IPv4-mapped IPv6 addresses, nor does it
|
||||
// correctly support IPv4 addresses on a dual-stack socket (despite MSDN's
|
||||
// claims to the contrary). To get proper QoS tagging when hosting in dual
|
||||
// stack mode, we will temporarily connect() the socket to allow qWAVE to
|
||||
// successfully initialize a flow, then disconnect it again so WSASendMsg()
|
||||
// works later on.
|
||||
if (isV4MappedV6Addr) {
|
||||
connect(socket, (PSOCKADDR)&peerAddress->address, peerAddress->addressLength);
|
||||
}
|
||||
|
||||
qosFlowId = 0; // Must be initialized to 0
|
||||
pfnQOSAddSocketToFlow(qosHandle,
|
||||
socket,
|
||||
isV4MappedV6Addr ? NULL : (struct sockaddr *)&peerAddress->address,
|
||||
QOSTrafficTypeControl,
|
||||
QOS_NON_ADAPTIVE_FLOW,
|
||||
&qosFlowId);
|
||||
|
||||
if (isV4MappedV6Addr) {
|
||||
SOCKADDR_IN6 empty = { 0 };
|
||||
empty.sin6_family = AF_INET6;
|
||||
connect(socket, (PSOCKADDR)&empty, sizeof(empty));
|
||||
}
|
||||
|
||||
// Even if we failed, don't try again
|
||||
qosAddedFlow = TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
msg.name = (struct sockaddr *) & peerAddress -> address;
|
||||
msg.namelen = peerAddress -> addressLength;
|
||||
msg.lpBuffers = (LPWSABUF) buffers;
|
||||
msg.dwBufferCount = (DWORD) bufferCount;
|
||||
|
||||
// We always send traffic from the same local address as we last received
|
||||
// from this peer to ensure it correctly recognizes our responses as
|
||||
// coming from the expected host.
|
||||
if (localAddress != NULL) {
|
||||
if (localAddress->address.ss_family == AF_INET) {
|
||||
IN_PKTINFO pktInfo;
|
||||
|
||||
pktInfo.ipi_addr = ((PSOCKADDR_IN)&localAddress->address)->sin_addr;
|
||||
pktInfo.ipi_ifindex = 0; // Unspecified
|
||||
|
||||
msg.Control.buf = controlBufData;
|
||||
msg.Control.len += WSA_CMSG_SPACE(sizeof(pktInfo));
|
||||
if (chdr == NULL) {
|
||||
chdr = WSA_CMSG_FIRSTHDR(&msg);
|
||||
}
|
||||
else {
|
||||
chdr = WSA_CMSG_NXTHDR(&msg, chdr);
|
||||
}
|
||||
|
||||
chdr->cmsg_level = IPPROTO_IP;
|
||||
chdr->cmsg_type = IP_PKTINFO;
|
||||
chdr->cmsg_len = WSA_CMSG_LEN(sizeof(pktInfo));
|
||||
memcpy(WSA_CMSG_DATA(chdr), &pktInfo, sizeof(pktInfo));
|
||||
}
|
||||
else if (localAddress->address.ss_family == AF_INET6) {
|
||||
IN6_PKTINFO pktInfo;
|
||||
|
||||
pktInfo.ipi6_addr = ((PSOCKADDR_IN6)&localAddress->address)->sin6_addr;
|
||||
pktInfo.ipi6_ifindex = 0; // Unspecified
|
||||
|
||||
msg.Control.buf = controlBufData;
|
||||
msg.Control.len += WSA_CMSG_SPACE(sizeof(pktInfo));
|
||||
if (chdr == NULL) {
|
||||
chdr = WSA_CMSG_FIRSTHDR(&msg);
|
||||
}
|
||||
else {
|
||||
chdr = WSA_CMSG_NXTHDR(&msg, chdr);
|
||||
}
|
||||
|
||||
chdr->cmsg_level = IPPROTO_IPV6;
|
||||
chdr->cmsg_type = IPV6_PKTINFO;
|
||||
chdr->cmsg_len = WSA_CMSG_LEN(sizeof(pktInfo));
|
||||
memcpy(WSA_CMSG_DATA(chdr), &pktInfo, sizeof(pktInfo));
|
||||
}
|
||||
}
|
||||
|
||||
if (WSASendTo (socket,
|
||||
(LPWSABUF) buffers,
|
||||
(DWORD) bufferCount,
|
||||
& sentLength,
|
||||
0,
|
||||
address != NULL ? (struct sockaddr *) & sin : NULL,
|
||||
address != NULL ? sizeof (struct sockaddr_in) : 0,
|
||||
NULL,
|
||||
NULL) == SOCKET_ERROR)
|
||||
{
|
||||
if (WSAGetLastError () == WSAEWOULDBLOCK)
|
||||
return 0;
|
||||
// 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);
|
||||
|
||||
return -1;
|
||||
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)
|
||||
{
|
||||
switch (WSAGetLastError ())
|
||||
{
|
||||
case WSAEWOULDBLOCK:
|
||||
return 0;
|
||||
|
||||
// These errors are treated as possible transient
|
||||
// conditions that could be caused by a network
|
||||
// interruption. We'll ignore them and allow the
|
||||
// socket timeout to kill us if the connection
|
||||
// is permanently interrupted.
|
||||
case WSAEADDRNOTAVAIL:
|
||||
case WSAENETDOWN:
|
||||
case WSAENETUNREACH:
|
||||
case WSAEHOSTDOWN:
|
||||
case WSAEHOSTUNREACH:
|
||||
return 0;
|
||||
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return (int) sentLength;
|
||||
@@ -316,44 +614,69 @@ enet_socket_send (ENetSocket socket,
|
||||
|
||||
int
|
||||
enet_socket_receive (ENetSocket socket,
|
||||
ENetAddress * address,
|
||||
ENetAddress * peerAddress,
|
||||
ENetAddress * localAddress,
|
||||
ENetBuffer * buffers,
|
||||
size_t bufferCount)
|
||||
{
|
||||
INT sinLength = sizeof (struct sockaddr_in);
|
||||
DWORD flags = 0,
|
||||
recvLength;
|
||||
struct sockaddr_in sin;
|
||||
DWORD recvLength;
|
||||
WSAMSG msg = { 0 };
|
||||
char controlBufData[1024];
|
||||
|
||||
if (WSARecvFrom (socket,
|
||||
(LPWSABUF) buffers,
|
||||
(DWORD) bufferCount,
|
||||
& recvLength,
|
||||
& flags,
|
||||
address != NULL ? (struct sockaddr *) & sin : NULL,
|
||||
address != NULL ? & sinLength : NULL,
|
||||
NULL,
|
||||
NULL) == SOCKET_ERROR)
|
||||
msg.name = peerAddress != NULL ? (struct sockaddr *) & peerAddress -> address : NULL;
|
||||
msg.namelen = peerAddress != NULL ? sizeof (peerAddress -> address) : 0;
|
||||
msg.lpBuffers = (LPWSABUF) buffers;
|
||||
msg.dwBufferCount = (DWORD) bufferCount;
|
||||
msg.Control.buf = controlBufData;
|
||||
msg.Control.len = sizeof(controlBufData);
|
||||
|
||||
if (pfnWSARecvMsg (socket,
|
||||
& msg,
|
||||
& recvLength,
|
||||
NULL,
|
||||
NULL) == SOCKET_ERROR)
|
||||
{
|
||||
switch (WSAGetLastError ())
|
||||
{
|
||||
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;
|
||||
|
||||
if (address != NULL)
|
||||
{
|
||||
address -> host = (enet_uint32) sin.sin_addr.s_addr;
|
||||
address -> port = ENET_NET_TO_HOST_16 (sin.sin_port);
|
||||
// Retrieve the local address that this traffic was received on
|
||||
// to ensure we respond from the correct address/interface.
|
||||
if (localAddress != NULL) {
|
||||
for (PWSACMSGHDR chdr = WSA_CMSG_FIRSTHDR(&msg); chdr != NULL; chdr = WSA_CMSG_NXTHDR(&msg, chdr)) {
|
||||
if (chdr->cmsg_level == IPPROTO_IP && chdr->cmsg_type == IP_PKTINFO) {
|
||||
PSOCKADDR_IN localAddr = (PSOCKADDR_IN)&localAddress->address;
|
||||
|
||||
localAddr->sin_family = AF_INET;
|
||||
localAddr->sin_addr = ((IN_PKTINFO*)WSA_CMSG_DATA(chdr))->ipi_addr;
|
||||
|
||||
localAddress->addressLength = sizeof(*localAddr);
|
||||
break;
|
||||
}
|
||||
else if (chdr->cmsg_level == IPPROTO_IPV6 && chdr->cmsg_type == IPV6_PKTINFO) {
|
||||
PSOCKADDR_IN6 localAddr = (PSOCKADDR_IN6)&localAddress->address;
|
||||
|
||||
localAddr->sin6_family = AF_INET6;
|
||||
localAddr->sin6_addr = ((IN6_PKTINFO*)WSA_CMSG_DATA(chdr))->ipi6_addr;
|
||||
|
||||
localAddress->addressLength = sizeof(*localAddr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
peerAddress->addressLength = msg.namelen;
|
||||
return (int) recvLength;
|
||||
}
|
||||
|
||||
@@ -374,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);
|
||||
|
||||
@@ -399,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