| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| Copyright (c) 2002-2015 Lee Salzman | ||
|
|
||
| Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: | ||
|
|
||
| The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. | ||
|
|
||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| pkgconfigdir = $(libdir)/pkgconfig | ||
| nodist_pkgconfig_DATA = libenet.pc | ||
|
|
||
| enetincludedir=$(includedir)/enet | ||
| enetinclude_HEADERS = \ | ||
| include/enet/callbacks.h \ | ||
| include/enet/enet.h \ | ||
| include/enet/list.h \ | ||
| include/enet/protocol.h \ | ||
| include/enet/time.h \ | ||
| include/enet/types.h \ | ||
| include/enet/unix.h \ | ||
| include/enet/utility.h \ | ||
| include/enet/win32.h | ||
|
|
||
| lib_LTLIBRARIES = libenet.la | ||
| libenet_la_SOURCES = callbacks.c compress.c host.c list.c packet.c peer.c protocol.c unix.c win32.c | ||
| # see info '(libtool) Updating version info' before making a release | ||
| libenet_la_LDFLAGS = $(AM_LDFLAGS) -version-info 7:0:0 | ||
| AM_CPPFLAGS = -I$(top_srcdir)/include | ||
|
|
||
| ACLOCAL_AMFLAGS = -Im4 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| Please visit the ENet homepage at http://enet.bespin.org for installation | ||
| and usage instructions. | ||
|
|
||
| If you obtained this package from github, the quick description on how to build | ||
| is: | ||
|
|
||
| # Generate the build system. | ||
|
|
||
| autoreconf -vfi | ||
|
|
||
| # Compile and install the library. | ||
|
|
||
| ./configure && make && make install | ||
|
|
||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,53 @@ | ||
| /** | ||
| @file callbacks.c | ||
| @brief ENet callback functions | ||
| */ | ||
| #define ENET_BUILDING_LIB 1 | ||
| #include "enet/enet.h" | ||
|
|
||
| static ENetCallbacks callbacks = { malloc, free, abort }; | ||
|
|
||
| int | ||
| enet_initialize_with_callbacks (ENetVersion version, const ENetCallbacks * inits) | ||
| { | ||
| if (version < ENET_VERSION_CREATE (1, 3, 0)) | ||
| return -1; | ||
|
|
||
| if (inits -> malloc != NULL || inits -> free != NULL) | ||
| { | ||
| if (inits -> malloc == NULL || inits -> free == NULL) | ||
| return -1; | ||
|
|
||
| callbacks.malloc = inits -> malloc; | ||
| callbacks.free = inits -> free; | ||
| } | ||
|
|
||
| if (inits -> no_memory != NULL) | ||
| callbacks.no_memory = inits -> no_memory; | ||
|
|
||
| return enet_initialize (); | ||
| } | ||
|
|
||
| ENetVersion | ||
| enet_linked_version (void) | ||
| { | ||
| return ENET_VERSION; | ||
| } | ||
|
|
||
| void * | ||
| enet_malloc (size_t size) | ||
| { | ||
| void * memory = callbacks.malloc (size); | ||
|
|
||
| if (memory == NULL) | ||
| callbacks.no_memory (); | ||
|
|
||
| return memory; | ||
| } | ||
|
|
||
| void | ||
| enet_free (void * memory) | ||
| { | ||
| callbacks.free (memory); | ||
| } | ||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| AC_INIT([libenet], [1.3.12]) | ||
| AC_CONFIG_SRCDIR([include/enet/enet.h]) | ||
| AM_INIT_AUTOMAKE([foreign]) | ||
|
|
||
| AC_CONFIG_MACRO_DIR([m4]) | ||
|
|
||
| AC_PROG_CC | ||
| AC_PROG_LIBTOOL | ||
|
|
||
| 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)]) | ||
| AC_CHECK_FUNC(fcntl, [AC_DEFINE(HAS_FCNTL)]) | ||
| AC_CHECK_FUNC(inet_pton, [AC_DEFINE(HAS_INET_PTON)]) | ||
| AC_CHECK_FUNC(inet_ntop, [AC_DEFINE(HAS_INET_NTOP)]) | ||
|
|
||
| AC_CHECK_MEMBER(struct msghdr.msg_flags, [AC_DEFINE(HAS_MSGHDR_FLAGS)], , [#include <sys/socket.h>]) | ||
|
|
||
| AC_CHECK_TYPE(socklen_t, [AC_DEFINE(HAS_SOCKLEN_T)], , | ||
| #include <sys/types.h> | ||
| #include <sys/socket.h> | ||
| ) | ||
|
|
||
| AC_CONFIG_FILES([Makefile | ||
| libenet.pc]) | ||
| AC_OUTPUT |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| /** | ||
| @page FAQ Frequently Answered Questions | ||
|
|
||
| @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 multi-threaded environment. | ||
|
|
||
| @section Q2 Isn't ENet just re-inventing TCP?! What's the point? | ||
|
|
||
| In a perfect world, that would be true. But as many have found, using | ||
| TCP either in lieu of or in conjunction with UDP can lead to all kinds | ||
| of nightmares. TCP is a good, solid protocol, however it simply isn't | ||
| up to the task of real-time games. Too much of TCP's implementation | ||
| dictates a policy that isn't practical for games. If you want to use | ||
| TCP, then do so -- this library is for people that either don't want | ||
| to use TCP or have tried and ended up being discouraged with the | ||
| performance. | ||
|
|
||
| */ | ||
|
|
||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,126 @@ | ||
| /** | ||
| @page Features Features and Architecture | ||
|
|
||
| ENet evolved specifically as a UDP networking layer for the | ||
| multiplayer first person shooter Cube. Cube necessitated low latency | ||
| 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 | ||
| management. So UDP by itself was not suitable as a network protocol | ||
| either. No suitable freely available networking libraries existed at | ||
| the time of ENet's creation to fill this niche. | ||
|
|
||
| UDP and TCP could have been used together in Cube to benefit somewhat | ||
| from both of their features, however, the resulting combinations of | ||
| protocols still leaves much to be desired. TCP lacks multiple streams | ||
| of communication without resorting to opening many sockets and | ||
| complicates delineation of packets due to its buffering behavior. UDP | ||
| lacks sequencing, connection management, management of bandwidth | ||
| resources, and imposes limitations on the size of packets. A | ||
| significant investment is required to integrate these two protocols, | ||
| and the end result is worse off in features and performance than the | ||
| uniform protocol presented by ENet. | ||
|
|
||
| ENet thus attempts to address these issues and provide a single, | ||
| uniform protocol layered over UDP to the developer with the best | ||
| features of UDP and TCP as well as some useful features neither | ||
| provide, with a much cleaner integration than any resulting from a | ||
| mixture of UDP and TCP. | ||
|
|
||
| @section CM Connection Management | ||
|
|
||
| ENet provides a simple connection interface over which to communicate | ||
| with a foreign host. The liveness of the connection is actively | ||
| monitored by pinging the foreign host at frequent intervals, and also | ||
| monitors the network conditions from the local host to the foreign | ||
| host such as the mean round trip time and packet loss in this fashion. | ||
|
|
||
| @section Sequencing Sequencing | ||
|
|
||
| Rather than a single byte stream that complicates the delineation of | ||
| packets, ENet presents connections as multiple, properly sequenced | ||
| packet streams that simplify the transfer of various types of data. | ||
|
|
||
| ENet provides sequencing for all packets by assigning to each sent | ||
| packet a sequence number that is incremented as packets are sent. ENet | ||
| 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. | ||
|
|
||
| For unreliable packets, ENet will simply discard the lower sequence | ||
| number packet if a packet with a higher sequence number has already | ||
| been delivered. This allows the packets to be dispatched immediately | ||
| as they arrive, and reduce latency of unreliable packets to an | ||
| absolute minimum. For reliable packets, if a higher sequence number | ||
| packet arrives, but the preceding packets in the sequence have not yet | ||
| arrived, ENet will stall delivery of the higher sequence number | ||
| packets until its predecessors have arrived. | ||
|
|
||
| @section Channels Channels | ||
|
|
||
| Since ENet will stall delivery of reliable packets to ensure proper | ||
| sequencing, and consequently any packets of higher sequence number | ||
| whether reliable or unreliable, in the event the reliable packet's | ||
| predecessors have not yet arrived, this can introduce latency into the | ||
| delivery of other packets which may not need to be as strictly ordered | ||
| with respect to the packet that stalled their delivery. | ||
|
|
||
| To combat this latency and reduce the ordering restrictions on | ||
| packets, ENet provides multiple channels of communication over a given | ||
| connection. Each channel is independently sequenced, and so the | ||
| delivery status of a packet in one channel will not stall the delivery | ||
| of other packets in another channel. | ||
|
|
||
| @section Reliability Reliability | ||
|
|
||
| ENet provides optional reliability of packet delivery by ensuring the | ||
| foreign host acknowledges receipt of all reliable packets. ENet will | ||
| attempt to resend the packet up to a reasonable amount of times, if no | ||
| acknowledgement of the packet's receipt happens within a specified | ||
| timeout. Retry timeouts are progressive and become more lenient with | ||
| every failed attempt to allow for temporary turbulence in network | ||
| conditions. | ||
|
|
||
| @section FaR Fragmentation and Reassembly | ||
|
|
||
| ENet will send and deliver packets regardless of size. Large packets | ||
| are fragmented into many smaller packets of suitable size, and | ||
| reassembled on the foreign host to recover the original packet for | ||
| delivery. The process is entirely transparent to the developer. | ||
|
|
||
| @section Aggregation Aggregation | ||
|
|
||
| ENet aggregates all protocol commands, including acknowledgements and | ||
| packet transfer, into larger protocol packets to ensure the proper | ||
| utilization of the connection and to limit the opportunities for | ||
| packet loss that might otherwise result in further delivery latency. | ||
|
|
||
| @section Adaptability Adaptability | ||
|
|
||
| ENet provides an in-flight data window for reliable packets to ensure | ||
| connections are not overwhelmed by volumes of packets. It also | ||
| provides a static bandwidth allocation mechanism to ensure the total | ||
| volume of packets sent and received to a host don't exceed the host's | ||
| capabilities. Further, ENet also provides a dynamic throttle that | ||
| responds to deviations from normal network connections to rectify | ||
| various types of network congestion by further limiting the volume of | ||
| packets sent. | ||
|
|
||
| @section Portability Portability | ||
|
|
||
| ENet works on Windows and any other Unix or Unix-like platform | ||
| providing a BSD sockets interface. The library has a small and stable | ||
| code base that can easily be extended to support other platforms and | ||
| integrates easily. ENet makes no assumptions about the underlying | ||
| platform's endianess or word size. | ||
|
|
||
| @section Freedom Freedom | ||
|
|
||
| ENet demands no royalties and doesn't carry a viral license that would | ||
| restrict you in how you might use it in your programs. ENet is | ||
| licensed under a short-and-sweet MIT-style license, which gives you | ||
| the freedom to do anything you want with it (well, almost anything). | ||
|
|
||
| */ | ||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,63 @@ | ||
| /** | ||
| @page Installation Installation | ||
|
|
||
| ENet should be trivially simple to integrate with most applications. | ||
| First, make sure you download the latest source distribution at @ref Downloads. | ||
|
|
||
| @section Unix Unix-like Operating Systems | ||
|
|
||
| If you are using an ENet release, then you should simply be able to build it | ||
| by doing the following: | ||
|
|
||
| ./configure && make && make install | ||
|
|
||
| If you obtained the package from github, you must have automake and autoconf | ||
| available to generate the build system first by doing the following command | ||
| before using the above mentioned build procedure: | ||
|
|
||
| autoreconf -vfi | ||
|
|
||
|
|
||
| @subsection SolarisBSD Solaris and BSD | ||
|
|
||
| When building ENet under Solaris, you must specify the -lsocket and | ||
| -lnsl parameters to your compiler to ensure that the sockets library | ||
| is linked in. | ||
|
|
||
| @section Windows Microsoft Windows | ||
|
|
||
| You may simply use the included "enet.lib" or "enet64.lib" static libraries. | ||
| However, if you wish to build the library yourself, then the following | ||
| instructions apply: | ||
|
|
||
| There is an included MSVC 6 project (enet.dsp) which you may use to | ||
| build a suitable library file. Alternatively, you may simply drag all | ||
| the ENet source files into your main project. | ||
|
|
||
| You will have to link to the Winsock2 libraries, so make sure to add | ||
| ws2_32.lib and winmm.lib to your library list (Project Settings | Link | | ||
| Object/library modules). | ||
|
|
||
| @subsection enet.dsp Building with the included enet.dsp | ||
|
|
||
| Load the included enet.dsp. MSVC may ask you to convert it if you | ||
| are on a newer version of MSVC - just allow the conversion and save | ||
| the resulting project as "enet" or similar. After you build this | ||
| project, it will output an "enet.lib" file to either the "Debug/" | ||
| or "Release/" directory, depending on which configuration you have | ||
| selected to build. By default, it should produce "Debug/enet.lib". | ||
|
|
||
| You may then copy the resulting "enet.lib" file and the header files | ||
| found in the "include/" directory to your other projects and add it to | ||
| their library lists. Make sure to also link against "ws2_32.lib" and | ||
| "winmm.lib" as described above. | ||
|
|
||
| @subsection DLL DLL | ||
|
|
||
| If you wish to build ENet as a DLL you must first define ENET_DLL | ||
| within the project (Project Settings | C/C++ | Preprocessor | | ||
| Preprocessor definitions) or, more invasively, simply define ENET_DLL | ||
| at the top of enet.h. | ||
|
|
||
| */ | ||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| /** | ||
| @page License License | ||
|
|
||
| Copyright (c) 2002-2015 Lee Salzman | ||
|
|
||
| Permission is hereby granted, free of charge, to any person obtaining | ||
| a copy of this software and associated documentation files (the | ||
| "Software"), to deal in the Software without restriction, including | ||
| without limitation the rights to use, copy, modify, merge, publish, | ||
| distribute, sublicense, and/or sell copies of the Software, and to | ||
| permit persons to whom the Software is furnished to do so, subject to | ||
| the following conditions: | ||
|
|
||
| The above copyright notice and this permission notice shall be | ||
| included in all copies or substantial portions of the Software. | ||
|
|
||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||
| EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||
| MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||
| NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE | ||
| LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION | ||
| OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | ||
| WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
|
|
||
| */ | ||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,59 @@ | ||
| /** @mainpage ENet | ||
|
|
||
| ENet's purpose is to provide a relatively thin, simple and robust | ||
| network communication layer on top of UDP (User Datagram Protocol). | ||
| The primary feature it provides is optional reliable, in-order | ||
| delivery of packets. | ||
|
|
||
| ENet omits certain higher level networking features such as authentication, | ||
| lobbying, server discovery, encryption, or other similar tasks that are | ||
| particularly application specific so that the library remains flexible, | ||
| portable, and easily embeddable. | ||
|
|
||
| @ref Features | ||
|
|
||
| @ref Downloads | ||
|
|
||
| @ref Installation | ||
|
|
||
| @ref Tutorial | ||
|
|
||
| @ref MailingList | ||
|
|
||
| @ref IRCChannel | ||
|
|
||
| @ref FAQ | ||
|
|
||
| @ref License | ||
|
|
||
| <a class="el" href="usergroup0.html">Documentation</a> | ||
|
|
||
| */ | ||
|
|
||
| /** | ||
| @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.12) can be downloaded <a class="el" href="download/enet-1.3.12.tar.gz">here</a>. | ||
| The last release that is protocol compatible with the 1.2 series or earlier (1.2.5) can be downloaded <a class="el" href="download/enet-1.2.5.tar.gz">here</a>. | ||
|
|
||
| You can find the most recent ENet source at <a class="el" href="https://github.com/lsalzman/enet">the github repository</a>. | ||
|
|
||
| */ | ||
|
|
||
| /** | ||
| @page MailingList Mailing List | ||
|
|
||
| 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 IRC Channel | ||
|
|
||
| Join the \#enet channel on the <a class="el" href="http://freenode.net">freenode IRC network (irc.freenode.net)</a> for real-time discussion about the ENet library. | ||
|
|
||
| */ | ||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,366 @@ | ||
| /** | ||
| @page Tutorial Tutorial | ||
|
|
||
| @ref Initialization | ||
|
|
||
| @ref CreateServer | ||
|
|
||
| @ref CreateClient | ||
|
|
||
| @ref ManageHost | ||
|
|
||
| @ref SendingPacket | ||
|
|
||
| @ref Disconnecting | ||
|
|
||
| @ref Connecting | ||
|
|
||
| @section Initialization Initialization | ||
|
|
||
| You should include the file <enet/enet.h> when using ENet. Do not | ||
| include <enet.h> without the directory prefix, as this may cause | ||
| file name conflicts on some systems. | ||
|
|
||
| Before using ENet, you must call enet_initialize() to initialize the | ||
| library. Upon program exit, you should call enet_deinitialize() so | ||
| that the library may clean up any used resources. | ||
|
|
||
| @code | ||
| #include <enet/enet.h> | ||
|
|
||
| int | ||
| main (int argc, char ** argv) | ||
| { | ||
| if (enet_initialize () != 0) | ||
| { | ||
| fprintf (stderr, "An error occurred while initializing ENet.\n"); | ||
| return EXIT_FAILURE; | ||
| } | ||
| atexit (enet_deinitialize); | ||
| ... | ||
| ... | ||
| ... | ||
| } | ||
| @endcode | ||
|
|
||
| @section CreateServer Creating an ENet server | ||
|
|
||
| Servers in ENet are constructed with enet_host_create(). You must | ||
| specify an address on which to receive data and new connections, as | ||
| well as the maximum allowable numbers of connected peers. You may | ||
| optionally specify the incoming and outgoing bandwidth of the server | ||
| in bytes per second so that ENet may try to statically manage | ||
| bandwidth resources among connected peers in addition to its dynamic | ||
| throttling algorithm; specifying 0 for these two options will cause | ||
| ENet to rely entirely upon its dynamic throttling algorithm to manage | ||
| bandwidth. | ||
|
|
||
| When done with a host, the host may be destroyed with | ||
| enet_host_destroy(). All connected peers to the host will be reset, | ||
| and the resources used by the host will be freed. | ||
|
|
||
| @code | ||
| ENetAddress address; | ||
| ENetHost * server; | ||
|
|
||
| /* Bind the server to the default localhost. */ | ||
| /* A specific host address can be specified by */ | ||
| /* enet_address_set_host (& address, "x.x.x.x"); */ | ||
|
|
||
| address.host = ENET_HOST_ANY; | ||
| /* Bind the server to port 1234. */ | ||
| address.port = 1234; | ||
|
|
||
| server = enet_host_create (& address /* the address to bind the server host to */, | ||
| 32 /* allow up to 32 clients and/or outgoing connections */, | ||
| 2 /* allow up to 2 channels to be used, 0 and 1 */, | ||
| 0 /* assume any amount of incoming bandwidth */, | ||
| 0 /* assume any amount of outgoing bandwidth */); | ||
| if (server == NULL) | ||
| { | ||
| fprintf (stderr, | ||
| "An error occurred while trying to create an ENet server host.\n"); | ||
| exit (EXIT_FAILURE); | ||
| } | ||
| ... | ||
| ... | ||
| ... | ||
| enet_host_destroy(server); | ||
| @endcode | ||
|
|
||
| @section CreateClient Creating an ENet client | ||
|
|
||
| Clients in ENet are similarly constructed with enet_host_create() when | ||
| no address is specified to bind the host to. Bandwidth may be | ||
| specified for the client host as in the above example. The peer count | ||
| controls the maximum number of connections to other server hosts that | ||
| may be simultaneously open. | ||
|
|
||
| @code | ||
| ENetHost * client; | ||
|
|
||
| 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 */); | ||
|
|
||
| if (client == NULL) | ||
| { | ||
| fprintf (stderr, | ||
| "An error occurred while trying to create an ENet client host.\n"); | ||
| exit (EXIT_FAILURE); | ||
| } | ||
| ... | ||
| ... | ||
| ... | ||
| enet_host_destroy(client); | ||
| @endcode | ||
|
|
||
| @section ManageHost Managing an ENet host | ||
|
|
||
| ENet uses a polled event model to notify the programmer of significant | ||
| events. ENet hosts are polled for events with enet_host_service(), | ||
| where an optional timeout value in milliseconds may be specified to | ||
| control how long ENet will poll; if a timeout of 0 is specified, | ||
| 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 | ||
| within the specified time limit. enet_host_service() will return 0 | ||
| with this event. | ||
|
|
||
| An event of type ENET_EVENT_TYPE_CONNECT is returned when either a new client | ||
| host has connected to the server host or when an attempt to establish a | ||
| connection with a foreign host has succeeded. Only the "peer" field of the | ||
| event structure is valid for this event and contains the newly connected peer. | ||
|
|
||
| An event of type ENET_EVENT_TYPE_RECEIVE is returned when a packet is received | ||
| from a connected peer. The "peer" field contains the peer the packet was | ||
| received from, "channelID" is the channel on which the packet was sent, and | ||
| "packet" is the packet that was sent. The packet contained in the "packet" | ||
| field must be destroyed with enet_packet_destroy() when you are done | ||
| inspecting its contents. | ||
|
|
||
| An event of type ENET_EVENT_TYPE_DISCONNECT is returned when a connected peer | ||
| has either explicitly disconnected or timed out. Only the "peer" field of the | ||
| event structure is valid for this event and contains the peer that | ||
| disconnected. Only the "data" field of the peer is still valid on a | ||
| disconnect event and must be explicitly reset. | ||
|
|
||
| @code | ||
| ENetEvent event; | ||
|
|
||
| /* Wait up to 1000 milliseconds for an event. */ | ||
| while (enet_host_service (client, & event, 1000) > 0) | ||
| { | ||
| switch (event.type) | ||
| { | ||
| case ENET_EVENT_TYPE_CONNECT: | ||
| printf ("A new client connected from %x:%u.\n", | ||
| event.peer -> address.host, | ||
| event.peer -> address.port); | ||
|
|
||
| /* Store any relevant client information here. */ | ||
| event.peer -> data = "Client information"; | ||
|
|
||
| break; | ||
|
|
||
| case ENET_EVENT_TYPE_RECEIVE: | ||
| printf ("A packet of length %u containing %s was received from %s on channel %u.\n", | ||
| event.packet -> dataLength, | ||
| event.packet -> data, | ||
| event.peer -> data, | ||
| event.channelID); | ||
|
|
||
| /* Clean up the packet now that we're done using it. */ | ||
| enet_packet_destroy (event.packet); | ||
|
|
||
| break; | ||
|
|
||
| case ENET_EVENT_TYPE_DISCONNECT: | ||
| printf ("%s disconnected.\n", event.peer -> data); | ||
|
|
||
| /* Reset the peer's client information. */ | ||
|
|
||
| event.peer -> data = NULL; | ||
| } | ||
| } | ||
| ... | ||
| ... | ||
| ... | ||
| @endcode | ||
|
|
||
| @section SendingPacket Sending a packet to an ENet peer | ||
|
|
||
| Packets in ENet are created with enet_packet_create(), where the size | ||
| of the packet must be specified. Optionally, initial data may be | ||
| specified to copy into the packet. | ||
|
|
||
| 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 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 | ||
| will assume the peer has disconnected and forcefully reset the | ||
| connection. If this flag is not specified, the packet is assumed an | ||
| unreliable packet, and no retry attempts will be made nor | ||
| acknowledgements generated. | ||
|
|
||
| A packet may be resized (extended or truncated) with | ||
| enet_packet_resize(). | ||
|
|
||
| A packet is sent to a foreign host with | ||
| enet_peer_send(). enet_peer_send() accepts a channel id over which to | ||
| send the packet to a given peer. Once the packet is handed over to | ||
| ENet with enet_peer_send(), ENet will handle its deallocation and | ||
| enet_packet_destroy() should not be used upon it. | ||
|
|
||
| One may also use enet_host_broadcast() to send a packet to all | ||
| connected peers on a given host over a specified channel id, as with | ||
| enet_peer_send(). | ||
|
|
||
| Queued packets will be sent on a call to enet_host_service(). | ||
| Alternatively, enet_host_flush() will send out queued packets without | ||
| dispatching any events. | ||
|
|
||
| @code | ||
| /* Create a reliable packet of size 7 containing "packet\0" */ | ||
| ENetPacket * packet = enet_packet_create ("packet", | ||
| strlen ("packet") + 1, | ||
| ENET_PACKET_FLAG_RELIABLE); | ||
|
|
||
| /* Extend the packet so and append the string "foo", so it now */ | ||
| /* contains "packetfoo\0" */ | ||
| enet_packet_resize (packet, strlen ("packetfoo") + 1); | ||
| strcpy (& packet -> data [strlen ("packet")], "foo"); | ||
|
|
||
| /* Send the packet to the peer over channel id 0. */ | ||
| /* One could also broadcast the packet by */ | ||
| /* enet_host_broadcast (host, 0, packet); */ | ||
| enet_peer_send (peer, 0, packet); | ||
| ... | ||
| ... | ||
| ... | ||
| /* One could just use enet_host_service() instead. */ | ||
| enet_host_flush (host); | ||
| @endcode | ||
|
|
||
| @section Disconnecting Disconnecting an ENet peer | ||
|
|
||
| Peers may be gently disconnected with enet_peer_disconnect(). A | ||
| disconnect request will be sent to the foreign host, and ENet will | ||
| wait for an acknowledgement from the foreign host before finally | ||
| disconnecting. An event of type ENET_EVENT_TYPE_DISCONNECT will be | ||
| generated once the disconnection succeeds. Normally timeouts apply to | ||
| the disconnect acknowledgement, and so if no acknowledgement is | ||
| received after a length of time the peer will be forcefully | ||
| disconnected. | ||
|
|
||
| enet_peer_reset() will forcefully disconnect a peer. The foreign host | ||
| will get no notification of a disconnect and will time out on the | ||
| foreign host. No event is generated. | ||
|
|
||
| @code | ||
| ENetEvent event; | ||
|
|
||
| enet_peer_disconnect (peer, 0); | ||
|
|
||
| /* Allow up to 3 seconds for the disconnect to succeed | ||
| * and drop any packets received packets. | ||
| */ | ||
| while (enet_host_service (client, & event, 3000) > 0) | ||
| { | ||
| switch (event.type) | ||
| { | ||
| case ENET_EVENT_TYPE_RECEIVE: | ||
| enet_packet_destroy (event.packet); | ||
| break; | ||
|
|
||
| case ENET_EVENT_TYPE_DISCONNECT: | ||
| puts ("Disconnection succeeded."); | ||
| return; | ||
| ... | ||
| ... | ||
| ... | ||
| } | ||
| } | ||
|
|
||
| /* We've arrived here, so the disconnect attempt didn't */ | ||
| /* succeed yet. Force the connection down. */ | ||
| enet_peer_reset (peer); | ||
| ... | ||
| ... | ||
| ... | ||
| @endcode | ||
|
|
||
| @section Connecting Connecting to an ENet host | ||
|
|
||
| A connection to a foreign host is initiated with enet_host_connect(). | ||
| It accepts the address of a foreign host to connect to, and the number | ||
| of channels that should be allocated for communication. If N channels | ||
| are allocated for use, their channel ids will be numbered 0 through | ||
| N-1. A peer representing the connection attempt is returned, or NULL | ||
| if there were no available peers over which to initiate the | ||
| connection. When the connection attempt succeeds, an event of type | ||
| ENET_EVENT_TYPE_CONNECT will be generated. If the connection attempt | ||
| times out or otherwise fails, an event of type | ||
| ENET_EVENT_TYPE_DISCONNECT will be generated. | ||
|
|
||
| @code | ||
| ENetAddress address; | ||
| ENetEvent event; | ||
| ENetPeer *peer; | ||
|
|
||
| /* Connect to some.server.net:1234. */ | ||
| enet_address_set_host (& address, "some.server.net"); | ||
| address.port = 1234; | ||
|
|
||
| /* Initiate the connection, allocating the two channels 0 and 1. */ | ||
| peer = enet_host_connect (client, & address, 2, 0); | ||
|
|
||
| if (peer == NULL) | ||
| { | ||
| fprintf (stderr, | ||
| "No available peers for initiating an ENet connection.\n"); | ||
| exit (EXIT_FAILURE); | ||
| } | ||
|
|
||
| /* Wait up to 5 seconds for the connection attempt to succeed. */ | ||
| if (enet_host_service (client, & event, 5000) > 0 && | ||
| event.type == ENET_EVENT_TYPE_CONNECT) | ||
| { | ||
| puts ("Connection to some.server.net:1234 succeeded."); | ||
| ... | ||
| ... | ||
| ... | ||
| } | ||
| else | ||
| { | ||
| /* Either the 5 seconds are up or a disconnect event was */ | ||
| /* received. Reset the peer in the event the 5 seconds */ | ||
| /* had run out without any significant event. */ | ||
| enet_peer_reset (peer); | ||
|
|
||
| puts ("Connection to some.server.net:1234 failed."); | ||
| } | ||
| ... | ||
| ... | ||
| ... | ||
| @endcode | ||
| */ |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,87 @@ | ||
| <?xml version="1.0" encoding="utf-8"?> | ||
| <Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | ||
| <ItemGroup Label="ProjectConfigurations"> | ||
| <ProjectConfiguration Include="Debug|Win32"> | ||
| <Configuration>Debug</Configuration> | ||
| <Platform>Win32</Platform> | ||
| </ProjectConfiguration> | ||
| <ProjectConfiguration Include="Debug|x64"> | ||
| <Configuration>Debug</Configuration> | ||
| <Platform>x64</Platform> | ||
| </ProjectConfiguration> | ||
| <ProjectConfiguration Include="Release|Win32"> | ||
| <Configuration>Release</Configuration> | ||
| <Platform>Win32</Platform> | ||
| </ProjectConfiguration> | ||
| <ProjectConfiguration Include="Release|x64"> | ||
| <Configuration>Release</Configuration> | ||
| <Platform>x64</Platform> | ||
| </ProjectConfiguration> | ||
| </ItemGroup> | ||
| <ItemGroup> | ||
| <ClInclude Include="include\enet\callbacks.h" /> | ||
| <ClInclude Include="include\enet\enet.h" /> | ||
| <ClInclude Include="include\enet\list.h" /> | ||
| <ClInclude Include="include\enet\protocol.h" /> | ||
| <ClInclude Include="include\enet\time.h" /> | ||
| <ClInclude Include="include\enet\types.h" /> | ||
| <ClInclude Include="include\enet\unix.h" /> | ||
| <ClInclude Include="include\enet\utility.h" /> | ||
| <ClInclude Include="include\enet\win32.h" /> | ||
| </ItemGroup> | ||
| <ItemGroup> | ||
| <ClCompile Include="callbacks.c" /> | ||
| <ClCompile Include="compress.c" /> | ||
| <ClCompile Include="host.c" /> | ||
| <ClCompile Include="list.c" /> | ||
| <ClCompile Include="packet.c" /> | ||
| <ClCompile Include="peer.c" /> | ||
| <ClCompile Include="protocol.c" /> | ||
| <ClCompile Include="unix.c" /> | ||
| <ClCompile Include="win32.c" /> | ||
| </ItemGroup> | ||
| <ItemGroup> | ||
| <Text Include="CMakeLists.txt" /> | ||
| </ItemGroup> | ||
| <ItemGroup> | ||
| <None Include="LICENSE" /> | ||
| <None Include="README" /> | ||
| </ItemGroup> | ||
| <PropertyGroup Label="Globals"> | ||
| <ProjectGuid>{CBC76802-C128-4B17-BF6C-23B08C313E5E}</ProjectGuid> | ||
| </PropertyGroup> | ||
| <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> | ||
| <PropertyGroup Label="Configuration"> | ||
| <ConfigurationType>StaticLibrary</ConfigurationType> | ||
| <PlatformToolset>v120</PlatformToolset> | ||
| <CharacterSet>Unicode</CharacterSet> | ||
| </PropertyGroup> | ||
| <PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration"> | ||
| <UseDebugLibraries>true</UseDebugLibraries> | ||
| </PropertyGroup> | ||
| <PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration"> | ||
| <UseDebugLibraries>false</UseDebugLibraries> | ||
| </PropertyGroup> | ||
| <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> | ||
| <ImportGroup Label="ExtensionSettings"> | ||
| </ImportGroup> | ||
| <ImportGroup Label="PropertySheets"> | ||
| <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> | ||
| <Import Project="..\..\Source\VSProps\Base.props" /> | ||
| </ImportGroup> | ||
| <PropertyGroup Label="UserMacros" /> | ||
| <PropertyGroup /> | ||
| <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> | ||
| <ClCompile> | ||
| <AdditionalIncludeDirectories>$(ExternalsDir)enet\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> | ||
| </ClCompile> | ||
| </ItemDefinitionGroup> | ||
| <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> | ||
| <ClCompile> | ||
| <AdditionalIncludeDirectories>$(ExternalsDir)enet\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> | ||
| </ClCompile> | ||
| </ItemDefinitionGroup> | ||
| <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> | ||
| <ImportGroup Label="ExtensionTargets"> | ||
| </ImportGroup> | ||
| </Project> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,55 @@ | ||
| <?xml version="1.0" encoding="utf-8"?> | ||
| <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | ||
| <ItemGroup> | ||
| <Filter Include="include"> | ||
| <UniqueIdentifier>{a5756b80-36f2-45f6-b1f1-b67082477376}</UniqueIdentifier> | ||
| </Filter> | ||
| </ItemGroup> | ||
| <ItemGroup> | ||
| <ClInclude Include="include\enet\callbacks.h"> | ||
| <Filter>include</Filter> | ||
| </ClInclude> | ||
| <ClInclude Include="include\enet\enet.h"> | ||
| <Filter>include</Filter> | ||
| </ClInclude> | ||
| <ClInclude Include="include\enet\list.h"> | ||
| <Filter>include</Filter> | ||
| </ClInclude> | ||
| <ClInclude Include="include\enet\protocol.h"> | ||
| <Filter>include</Filter> | ||
| </ClInclude> | ||
| <ClInclude Include="include\enet\time.h"> | ||
| <Filter>include</Filter> | ||
| </ClInclude> | ||
| <ClInclude Include="include\enet\types.h"> | ||
| <Filter>include</Filter> | ||
| </ClInclude> | ||
| <ClInclude Include="include\enet\unix.h"> | ||
| <Filter>include</Filter> | ||
| </ClInclude> | ||
| <ClInclude Include="include\enet\utility.h"> | ||
| <Filter>include</Filter> | ||
| </ClInclude> | ||
| <ClInclude Include="include\enet\win32.h"> | ||
| <Filter>include</Filter> | ||
| </ClInclude> | ||
| </ItemGroup> | ||
| <ItemGroup> | ||
| <ClCompile Include="callbacks.c" /> | ||
| <ClCompile Include="compress.c" /> | ||
| <ClCompile Include="host.c" /> | ||
| <ClCompile Include="list.c" /> | ||
| <ClCompile Include="packet.c" /> | ||
| <ClCompile Include="peer.c" /> | ||
| <ClCompile Include="protocol.c" /> | ||
| <ClCompile Include="unix.c" /> | ||
| <ClCompile Include="win32.c" /> | ||
| </ItemGroup> | ||
| <ItemGroup> | ||
| <Text Include="CMakeLists.txt" /> | ||
| </ItemGroup> | ||
| <ItemGroup> | ||
| <None Include="LICENSE" /> | ||
| <None Include="README" /> | ||
| </ItemGroup> | ||
| </Project> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,86 @@ | ||
| <?xml version="1.0" encoding="UTF-8" standalone="yes" ?> | ||
| <CodeBlocks_project_file> | ||
| <FileVersion major="1" minor="6" /> | ||
| <Project> | ||
| <Option title="enet_dll" /> | ||
| <Option pch_mode="2" /> | ||
| <Option compiler="gcc" /> | ||
| <Build> | ||
| <Target title="Debug"> | ||
| <Option output="bin\Debug\libenet" prefix_auto="1" extension_auto="1" /> | ||
| <Option object_output="obj\Debug\" /> | ||
| <Option type="3" /> | ||
| <Option compiler="gcc" /> | ||
| <Option createDefFile="1" /> | ||
| <Option createStaticLib="1" /> | ||
| <Compiler> | ||
| <Add option="-g" /> | ||
| </Compiler> | ||
| </Target> | ||
| <Target title="Release"> | ||
| <Option output="bin\Release\libenet" prefix_auto="1" extension_auto="1" /> | ||
| <Option object_output="obj\Release\" /> | ||
| <Option type="3" /> | ||
| <Option compiler="gcc" /> | ||
| <Option createDefFile="1" /> | ||
| <Option createStaticLib="1" /> | ||
| <Compiler> | ||
| <Add option="-O2" /> | ||
| </Compiler> | ||
| <Linker> | ||
| <Add option="-s" /> | ||
| </Linker> | ||
| </Target> | ||
| </Build> | ||
| <Compiler> | ||
| <Add option="-Wall" /> | ||
| <Add option="-DENET_DLL" /> | ||
| <Add directory="include" /> | ||
| </Compiler> | ||
| <Linker> | ||
| <Add library="ws2_32" /> | ||
| <Add library="Winmm" /> | ||
| </Linker> | ||
| <Unit filename="callbacks.c"> | ||
| <Option compilerVar="CC" /> | ||
| </Unit> | ||
| <Unit filename="compress.c"> | ||
| <Option compilerVar="CC" /> | ||
| </Unit> | ||
| <Unit filename="host.c"> | ||
| <Option compilerVar="CC" /> | ||
| </Unit> | ||
| <Unit filename="include\enet\callbacks.h" /> | ||
| <Unit filename="include\enet\enet.h" /> | ||
| <Unit filename="include\enet\list.h" /> | ||
| <Unit filename="include\enet\protocol.h" /> | ||
| <Unit filename="include\enet\time.h" /> | ||
| <Unit filename="include\enet\types.h" /> | ||
| <Unit filename="include\enet\unix.h" /> | ||
| <Unit filename="include\enet\utility.h" /> | ||
| <Unit filename="include\enet\win32.h" /> | ||
| <Unit filename="list.c"> | ||
| <Option compilerVar="CC" /> | ||
| </Unit> | ||
| <Unit filename="packet.c"> | ||
| <Option compilerVar="CC" /> | ||
| </Unit> | ||
| <Unit filename="peer.c"> | ||
| <Option compilerVar="CC" /> | ||
| </Unit> | ||
| <Unit filename="protocol.c"> | ||
| <Option compilerVar="CC" /> | ||
| </Unit> | ||
| <Unit filename="unix.c"> | ||
| <Option compilerVar="CC" /> | ||
| </Unit> | ||
| <Unit filename="win32.c"> | ||
| <Option compilerVar="CC" /> | ||
| </Unit> | ||
| <Extensions> | ||
| <code_completion /> | ||
| <envvars /> | ||
| <debugger /> | ||
| </Extensions> | ||
| </Project> | ||
| </CodeBlocks_project_file> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| /** | ||
| @file callbacks.h | ||
| @brief ENet callbacks | ||
| */ | ||
| #ifndef __ENET_CALLBACKS_H__ | ||
| #define __ENET_CALLBACKS_H__ | ||
|
|
||
| #include <stdlib.h> | ||
|
|
||
| typedef struct _ENetCallbacks | ||
| { | ||
| void * (ENET_CALLBACK * malloc) (size_t size); | ||
| void (ENET_CALLBACK * free) (void * memory); | ||
| void (ENET_CALLBACK * no_memory) (void); | ||
| } ENetCallbacks; | ||
|
|
||
| /** @defgroup callbacks ENet internal callbacks | ||
| @{ | ||
| @ingroup private | ||
| */ | ||
| extern void * enet_malloc (size_t); | ||
| extern void enet_free (void *); | ||
|
|
||
| /** @} */ | ||
|
|
||
| #endif /* __ENET_CALLBACKS_H__ */ | ||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| /** | ||
| @file list.h | ||
| @brief ENet list management | ||
| */ | ||
| #ifndef __ENET_LIST_H__ | ||
| #define __ENET_LIST_H__ | ||
|
|
||
| #include <stdlib.h> | ||
|
|
||
| typedef struct _ENetListNode | ||
| { | ||
| struct _ENetListNode * next; | ||
| struct _ENetListNode * previous; | ||
| } ENetListNode; | ||
|
|
||
| typedef ENetListNode * ENetListIterator; | ||
|
|
||
| typedef struct _ENetList | ||
| { | ||
| ENetListNode sentinel; | ||
| } ENetList; | ||
|
|
||
| extern void enet_list_clear (ENetList *); | ||
|
|
||
| extern ENetListIterator enet_list_insert (ENetListIterator, void *); | ||
| extern void * enet_list_remove (ENetListIterator); | ||
| extern ENetListIterator enet_list_move (ENetListIterator, void *, void *); | ||
|
|
||
| extern size_t enet_list_size (ENetList *); | ||
|
|
||
| #define enet_list_begin(list) ((list) -> sentinel.next) | ||
| #define enet_list_end(list) (& (list) -> sentinel) | ||
|
|
||
| #define enet_list_empty(list) (enet_list_begin (list) == enet_list_end (list)) | ||
|
|
||
| #define enet_list_next(iterator) ((iterator) -> next) | ||
| #define enet_list_previous(iterator) ((iterator) -> previous) | ||
|
|
||
| #define enet_list_front(list) ((void *) (list) -> sentinel.next) | ||
| #define enet_list_back(list) ((void *) (list) -> sentinel.previous) | ||
|
|
||
| #endif /* __ENET_LIST_H__ */ | ||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,198 @@ | ||
| /** | ||
| @file protocol.h | ||
| @brief ENet protocol | ||
| */ | ||
| #ifndef __ENET_PROTOCOL_H__ | ||
| #define __ENET_PROTOCOL_H__ | ||
|
|
||
| #include "types.h" | ||
|
|
||
| enum | ||
| { | ||
| ENET_PROTOCOL_MINIMUM_MTU = 576, | ||
| ENET_PROTOCOL_MAXIMUM_MTU = 4096, | ||
| 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_FRAGMENT_COUNT = 1024 * 1024 | ||
| }; | ||
|
|
||
| typedef enum _ENetProtocolCommand | ||
| { | ||
| ENET_PROTOCOL_COMMAND_NONE = 0, | ||
| ENET_PROTOCOL_COMMAND_ACKNOWLEDGE = 1, | ||
| ENET_PROTOCOL_COMMAND_CONNECT = 2, | ||
| ENET_PROTOCOL_COMMAND_VERIFY_CONNECT = 3, | ||
| ENET_PROTOCOL_COMMAND_DISCONNECT = 4, | ||
| ENET_PROTOCOL_COMMAND_PING = 5, | ||
| ENET_PROTOCOL_COMMAND_SEND_RELIABLE = 6, | ||
| ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE = 7, | ||
| ENET_PROTOCOL_COMMAND_SEND_FRAGMENT = 8, | ||
| ENET_PROTOCOL_COMMAND_SEND_UNSEQUENCED = 9, | ||
| ENET_PROTOCOL_COMMAND_BANDWIDTH_LIMIT = 10, | ||
| ENET_PROTOCOL_COMMAND_THROTTLE_CONFIGURE = 11, | ||
| ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE_FRAGMENT = 12, | ||
| ENET_PROTOCOL_COMMAND_COUNT = 13, | ||
|
|
||
| ENET_PROTOCOL_COMMAND_MASK = 0x0F | ||
| } ENetProtocolCommand; | ||
|
|
||
| typedef enum _ENetProtocolFlag | ||
| { | ||
| ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE = (1 << 7), | ||
| ENET_PROTOCOL_COMMAND_FLAG_UNSEQUENCED = (1 << 6), | ||
|
|
||
| ENET_PROTOCOL_HEADER_FLAG_COMPRESSED = (1 << 14), | ||
| ENET_PROTOCOL_HEADER_FLAG_SENT_TIME = (1 << 15), | ||
| ENET_PROTOCOL_HEADER_FLAG_MASK = ENET_PROTOCOL_HEADER_FLAG_COMPRESSED | ENET_PROTOCOL_HEADER_FLAG_SENT_TIME, | ||
|
|
||
| ENET_PROTOCOL_HEADER_SESSION_MASK = (3 << 12), | ||
| ENET_PROTOCOL_HEADER_SESSION_SHIFT = 12 | ||
| } ENetProtocolFlag; | ||
|
|
||
| #ifdef _MSC_VER | ||
| #pragma pack(push, 1) | ||
| #define ENET_PACKED | ||
| #elif defined(__GNUC__) || defined(__clang__) | ||
| #define ENET_PACKED __attribute__ ((packed)) | ||
| #else | ||
| #define ENET_PACKED | ||
| #endif | ||
|
|
||
| typedef struct _ENetProtocolHeader | ||
| { | ||
| enet_uint16 peerID; | ||
| enet_uint16 sentTime; | ||
| } ENET_PACKED ENetProtocolHeader; | ||
|
|
||
| typedef struct _ENetProtocolCommandHeader | ||
| { | ||
| enet_uint8 command; | ||
| enet_uint8 channelID; | ||
| enet_uint16 reliableSequenceNumber; | ||
| } ENET_PACKED ENetProtocolCommandHeader; | ||
|
|
||
| typedef struct _ENetProtocolAcknowledge | ||
| { | ||
| ENetProtocolCommandHeader header; | ||
| enet_uint16 receivedReliableSequenceNumber; | ||
| enet_uint16 receivedSentTime; | ||
| } ENET_PACKED ENetProtocolAcknowledge; | ||
|
|
||
| typedef struct _ENetProtocolConnect | ||
| { | ||
| ENetProtocolCommandHeader header; | ||
| enet_uint16 outgoingPeerID; | ||
| enet_uint8 incomingSessionID; | ||
| enet_uint8 outgoingSessionID; | ||
| enet_uint32 mtu; | ||
| enet_uint32 windowSize; | ||
| enet_uint32 channelCount; | ||
| enet_uint32 incomingBandwidth; | ||
| enet_uint32 outgoingBandwidth; | ||
| enet_uint32 packetThrottleInterval; | ||
| enet_uint32 packetThrottleAcceleration; | ||
| enet_uint32 packetThrottleDeceleration; | ||
| enet_uint32 connectID; | ||
| enet_uint32 data; | ||
| } ENET_PACKED ENetProtocolConnect; | ||
|
|
||
| typedef struct _ENetProtocolVerifyConnect | ||
| { | ||
| ENetProtocolCommandHeader header; | ||
| enet_uint16 outgoingPeerID; | ||
| enet_uint8 incomingSessionID; | ||
| enet_uint8 outgoingSessionID; | ||
| enet_uint32 mtu; | ||
| enet_uint32 windowSize; | ||
| enet_uint32 channelCount; | ||
| enet_uint32 incomingBandwidth; | ||
| enet_uint32 outgoingBandwidth; | ||
| enet_uint32 packetThrottleInterval; | ||
| enet_uint32 packetThrottleAcceleration; | ||
| enet_uint32 packetThrottleDeceleration; | ||
| enet_uint32 connectID; | ||
| } ENET_PACKED ENetProtocolVerifyConnect; | ||
|
|
||
| typedef struct _ENetProtocolBandwidthLimit | ||
| { | ||
| ENetProtocolCommandHeader header; | ||
| enet_uint32 incomingBandwidth; | ||
| enet_uint32 outgoingBandwidth; | ||
| } ENET_PACKED ENetProtocolBandwidthLimit; | ||
|
|
||
| typedef struct _ENetProtocolThrottleConfigure | ||
| { | ||
| ENetProtocolCommandHeader header; | ||
| enet_uint32 packetThrottleInterval; | ||
| enet_uint32 packetThrottleAcceleration; | ||
| enet_uint32 packetThrottleDeceleration; | ||
| } ENET_PACKED ENetProtocolThrottleConfigure; | ||
|
|
||
| typedef struct _ENetProtocolDisconnect | ||
| { | ||
| ENetProtocolCommandHeader header; | ||
| enet_uint32 data; | ||
| } ENET_PACKED ENetProtocolDisconnect; | ||
|
|
||
| typedef struct _ENetProtocolPing | ||
| { | ||
| ENetProtocolCommandHeader header; | ||
| } ENET_PACKED ENetProtocolPing; | ||
|
|
||
| typedef struct _ENetProtocolSendReliable | ||
| { | ||
| ENetProtocolCommandHeader header; | ||
| enet_uint16 dataLength; | ||
| } ENET_PACKED ENetProtocolSendReliable; | ||
|
|
||
| typedef struct _ENetProtocolSendUnreliable | ||
| { | ||
| ENetProtocolCommandHeader header; | ||
| enet_uint16 unreliableSequenceNumber; | ||
| enet_uint16 dataLength; | ||
| } ENET_PACKED ENetProtocolSendUnreliable; | ||
|
|
||
| typedef struct _ENetProtocolSendUnsequenced | ||
| { | ||
| ENetProtocolCommandHeader header; | ||
| enet_uint16 unsequencedGroup; | ||
| enet_uint16 dataLength; | ||
| } ENET_PACKED ENetProtocolSendUnsequenced; | ||
|
|
||
| typedef struct _ENetProtocolSendFragment | ||
| { | ||
| ENetProtocolCommandHeader header; | ||
| enet_uint16 startSequenceNumber; | ||
| enet_uint16 dataLength; | ||
| enet_uint32 fragmentCount; | ||
| enet_uint32 fragmentNumber; | ||
| enet_uint32 totalLength; | ||
| enet_uint32 fragmentOffset; | ||
| } ENET_PACKED ENetProtocolSendFragment; | ||
|
|
||
| typedef union _ENetProtocol | ||
| { | ||
| ENetProtocolCommandHeader header; | ||
| ENetProtocolAcknowledge acknowledge; | ||
| ENetProtocolConnect connect; | ||
| ENetProtocolVerifyConnect verifyConnect; | ||
| ENetProtocolDisconnect disconnect; | ||
| ENetProtocolPing ping; | ||
| ENetProtocolSendReliable sendReliable; | ||
| ENetProtocolSendUnreliable sendUnreliable; | ||
| ENetProtocolSendUnsequenced sendUnsequenced; | ||
| ENetProtocolSendFragment sendFragment; | ||
| ENetProtocolBandwidthLimit bandwidthLimit; | ||
| ENetProtocolThrottleConfigure throttleConfigure; | ||
| } ENET_PACKED ENetProtocol; | ||
|
|
||
| #ifdef _MSC_VER | ||
| #pragma pack(pop) | ||
| #endif | ||
|
|
||
| #endif /* __ENET_PROTOCOL_H__ */ | ||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| /** | ||
| @file time.h | ||
| @brief ENet time constants and macros | ||
| */ | ||
| #ifndef __ENET_TIME_H__ | ||
| #define __ENET_TIME_H__ | ||
|
|
||
| #define ENET_TIME_OVERFLOW 86400000 | ||
|
|
||
| #define ENET_TIME_LESS(a, b) ((a) - (b) >= ENET_TIME_OVERFLOW) | ||
| #define ENET_TIME_GREATER(a, b) ((b) - (a) >= ENET_TIME_OVERFLOW) | ||
| #define ENET_TIME_LESS_EQUAL(a, b) (! ENET_TIME_GREATER (a, b)) | ||
| #define ENET_TIME_GREATER_EQUAL(a, b) (! ENET_TIME_LESS (a, b)) | ||
|
|
||
| #define ENET_TIME_DIFFERENCE(a, b) ((a) - (b) >= ENET_TIME_OVERFLOW ? (b) - (a) : (a) - (b)) | ||
|
|
||
| #endif /* __ENET_TIME_H__ */ | ||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| /** | ||
| @file types.h | ||
| @brief type definitions for ENet | ||
| */ | ||
| #ifndef __ENET_TYPES_H__ | ||
| #define __ENET_TYPES_H__ | ||
|
|
||
| typedef unsigned char enet_uint8; /**< unsigned 8-bit type */ | ||
| typedef unsigned short enet_uint16; /**< unsigned 16-bit type */ | ||
| typedef unsigned int enet_uint32; /**< unsigned 32-bit type */ | ||
|
|
||
| #endif /* __ENET_TYPES_H__ */ | ||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,47 @@ | ||
| /** | ||
| @file unix.h | ||
| @brief ENet Unix header | ||
| */ | ||
| #ifndef __ENET_UNIX_H__ | ||
| #define __ENET_UNIX_H__ | ||
|
|
||
| #include <stdlib.h> | ||
| #include <sys/time.h> | ||
| #include <sys/types.h> | ||
| #include <sys/socket.h> | ||
| #include <netinet/in.h> | ||
| #include <unistd.h> | ||
|
|
||
| #ifdef MSG_MAXIOVLEN | ||
| #define ENET_BUFFER_MAXIMUM MSG_MAXIOVLEN | ||
| #endif | ||
|
|
||
| typedef int ENetSocket; | ||
|
|
||
| #define ENET_SOCKET_NULL -1 | ||
|
|
||
| #define ENET_HOST_TO_NET_16(value) (htons (value)) /**< macro that converts host to net byte-order of a 16-bit value */ | ||
| #define ENET_HOST_TO_NET_32(value) (htonl (value)) /**< macro that converts host to net byte-order of a 32-bit value */ | ||
|
|
||
| #define ENET_NET_TO_HOST_16(value) (ntohs (value)) /**< macro that converts net to host byte-order of a 16-bit value */ | ||
| #define ENET_NET_TO_HOST_32(value) (ntohl (value)) /**< macro that converts net to host byte-order of a 32-bit value */ | ||
|
|
||
| typedef struct | ||
| { | ||
| void * data; | ||
| size_t dataLength; | ||
| } ENetBuffer; | ||
|
|
||
| #define ENET_CALLBACK | ||
|
|
||
| #define ENET_API extern | ||
|
|
||
| typedef fd_set ENetSocketSet; | ||
|
|
||
| #define ENET_SOCKETSET_EMPTY(sockset) FD_ZERO (& (sockset)) | ||
| #define ENET_SOCKETSET_ADD(sockset, socket) FD_SET (socket, & (sockset)) | ||
| #define ENET_SOCKETSET_REMOVE(sockset, socket) FD_CLR (socket, & (sockset)) | ||
| #define ENET_SOCKETSET_CHECK(sockset, socket) FD_ISSET (socket, & (sockset)) | ||
|
|
||
| #endif /* __ENET_UNIX_H__ */ | ||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| /** | ||
| @file utility.h | ||
| @brief ENet utility header | ||
| */ | ||
| #ifndef __ENET_UTILITY_H__ | ||
| #define __ENET_UTILITY_H__ | ||
|
|
||
| #define ENET_MAX(x, y) ((x) > (y) ? (x) : (y)) | ||
| #define ENET_MIN(x, y) ((x) < (y) ? (x) : (y)) | ||
|
|
||
| #endif /* __ENET_UTILITY_H__ */ | ||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,57 @@ | ||
| /** | ||
| @file win32.h | ||
| @brief ENet Win32 header | ||
| */ | ||
| #ifndef __ENET_WIN32_H__ | ||
| #define __ENET_WIN32_H__ | ||
|
|
||
| #ifdef _MSC_VER | ||
| #ifdef ENET_BUILDING_LIB | ||
| #pragma warning (disable: 4267) // size_t to int conversion | ||
| #pragma warning (disable: 4244) // 64bit to 32bit int | ||
| #pragma warning (disable: 4018) // signed/unsigned mismatch | ||
| #pragma warning (disable: 4146) // unary minus operator applied to unsigned type | ||
| #endif | ||
| #endif | ||
|
|
||
| #include <stdlib.h> | ||
| #include <winsock2.h> | ||
|
|
||
| typedef SOCKET ENetSocket; | ||
|
|
||
| #define ENET_SOCKET_NULL INVALID_SOCKET | ||
|
|
||
| #define ENET_HOST_TO_NET_16(value) (htons (value)) | ||
| #define ENET_HOST_TO_NET_32(value) (htonl (value)) | ||
|
|
||
| #define ENET_NET_TO_HOST_16(value) (ntohs (value)) | ||
| #define ENET_NET_TO_HOST_32(value) (ntohl (value)) | ||
|
|
||
| typedef struct | ||
| { | ||
| size_t dataLength; | ||
| void * data; | ||
| } ENetBuffer; | ||
|
|
||
| #define ENET_CALLBACK __cdecl | ||
|
|
||
| #ifdef ENET_DLL | ||
| #ifdef ENET_BUILDING_LIB | ||
| #define ENET_API __declspec( dllexport ) | ||
| #else | ||
| #define ENET_API __declspec( dllimport ) | ||
| #endif /* ENET_BUILDING_LIB */ | ||
| #else /* !ENET_DLL */ | ||
| #define ENET_API extern | ||
| #endif /* ENET_DLL */ | ||
|
|
||
| typedef fd_set ENetSocketSet; | ||
|
|
||
| #define ENET_SOCKETSET_EMPTY(sockset) FD_ZERO (& (sockset)) | ||
| #define ENET_SOCKETSET_ADD(sockset, socket) FD_SET (socket, & (sockset)) | ||
| #define ENET_SOCKETSET_REMOVE(sockset, socket) FD_CLR (socket, & (sockset)) | ||
| #define ENET_SOCKETSET_CHECK(sockset, socket) FD_ISSET (socket, & (sockset)) | ||
|
|
||
| #endif /* __ENET_WIN32_H__ */ | ||
|
|
||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| prefix=@prefix@ | ||
| exec_prefix=@exec_prefix@ | ||
| libdir=@libdir@ | ||
| includedir=@includedir@ | ||
|
|
||
| Name: @PACKAGE_NAME@ | ||
| Description: Low-latency UDP networking library supporting optional reliability | ||
| Version: @PACKAGE_VERSION@ | ||
| Cflags: -I${includedir} | ||
| Libs: -L${libdir} -lenet |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,75 @@ | ||
| /** | ||
| @file list.c | ||
| @brief ENet linked list functions | ||
| */ | ||
| #define ENET_BUILDING_LIB 1 | ||
| #include "enet/enet.h" | ||
|
|
||
| /** | ||
| @defgroup list ENet linked list utility functions | ||
| @ingroup private | ||
| @{ | ||
| */ | ||
| void | ||
| enet_list_clear (ENetList * list) | ||
| { | ||
| list -> sentinel.next = & list -> sentinel; | ||
| list -> sentinel.previous = & list -> sentinel; | ||
| } | ||
|
|
||
| ENetListIterator | ||
| enet_list_insert (ENetListIterator position, void * data) | ||
| { | ||
| ENetListIterator result = (ENetListIterator) data; | ||
|
|
||
| result -> previous = position -> previous; | ||
| result -> next = position; | ||
|
|
||
| result -> previous -> next = result; | ||
| position -> previous = result; | ||
|
|
||
| return result; | ||
| } | ||
|
|
||
| void * | ||
| enet_list_remove (ENetListIterator position) | ||
| { | ||
| position -> previous -> next = position -> next; | ||
| position -> next -> previous = position -> previous; | ||
|
|
||
| return position; | ||
| } | ||
|
|
||
| ENetListIterator | ||
| enet_list_move (ENetListIterator position, void * dataFirst, void * dataLast) | ||
| { | ||
| ENetListIterator first = (ENetListIterator) dataFirst, | ||
| last = (ENetListIterator) dataLast; | ||
|
|
||
| first -> previous -> next = last -> next; | ||
| last -> next -> previous = first -> previous; | ||
|
|
||
| first -> previous = position -> previous; | ||
| last -> next = position; | ||
|
|
||
| first -> previous -> next = first; | ||
| position -> previous = last; | ||
|
|
||
| return first; | ||
| } | ||
|
|
||
| size_t | ||
| enet_list_size (ENetList * list) | ||
| { | ||
| size_t size = 0; | ||
| ENetListIterator position; | ||
|
|
||
| for (position = enet_list_begin (list); | ||
| position != enet_list_end (list); | ||
| position = enet_list_next (position)) | ||
| ++ size; | ||
|
|
||
| return size; | ||
| } | ||
|
|
||
| /** @} */ |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,165 @@ | ||
| /** | ||
| @file packet.c | ||
| @brief ENet packet management functions | ||
| */ | ||
| #include <string.h> | ||
| #define ENET_BUILDING_LIB 1 | ||
| #include "enet/enet.h" | ||
|
|
||
| /** @defgroup Packet ENet packet functions | ||
| @{ | ||
| */ | ||
|
|
||
| /** Creates a packet that may be sent to a peer. | ||
| @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 | ||
| */ | ||
| ENetPacket * | ||
| enet_packet_create (const void * data, size_t dataLength, enet_uint32 flags) | ||
| { | ||
| ENetPacket * packet = (ENetPacket *) enet_malloc (sizeof (ENetPacket)); | ||
| if (packet == NULL) | ||
| return NULL; | ||
|
|
||
| if (flags & ENET_PACKET_FLAG_NO_ALLOCATE) | ||
| packet -> data = (enet_uint8 *) data; | ||
| else | ||
| if (dataLength <= 0) | ||
| packet -> data = NULL; | ||
| else | ||
| { | ||
| packet -> data = (enet_uint8 *) enet_malloc (dataLength); | ||
| if (packet -> data == NULL) | ||
| { | ||
| enet_free (packet); | ||
| return NULL; | ||
| } | ||
|
|
||
| if (data != NULL) | ||
| memcpy (packet -> data, data, dataLength); | ||
| } | ||
|
|
||
| packet -> referenceCount = 0; | ||
| packet -> flags = flags; | ||
| packet -> dataLength = dataLength; | ||
| packet -> freeCallback = NULL; | ||
| packet -> userData = NULL; | ||
|
|
||
| return packet; | ||
| } | ||
|
|
||
| /** Destroys the packet and deallocates its data. | ||
| @param packet packet to be destroyed | ||
| */ | ||
| void | ||
| enet_packet_destroy (ENetPacket * packet) | ||
| { | ||
| if (packet == NULL) | ||
| return; | ||
|
|
||
| if (packet -> freeCallback != NULL) | ||
| (* packet -> freeCallback) (packet); | ||
| if (! (packet -> flags & ENET_PACKET_FLAG_NO_ALLOCATE) && | ||
| packet -> data != NULL) | ||
| enet_free (packet -> data); | ||
| enet_free (packet); | ||
| } | ||
|
|
||
| /** Attempts to resize the data in the packet to length specified in the | ||
| dataLength parameter | ||
| @param packet packet to resize | ||
| @param dataLength new size for the packet data | ||
| @returns 0 on success, < 0 on failure | ||
| */ | ||
| int | ||
| enet_packet_resize (ENetPacket * packet, size_t dataLength) | ||
| { | ||
| enet_uint8 * newData; | ||
|
|
||
| if (dataLength <= packet -> dataLength || (packet -> flags & ENET_PACKET_FLAG_NO_ALLOCATE)) | ||
| { | ||
| packet -> dataLength = dataLength; | ||
|
|
||
| return 0; | ||
| } | ||
|
|
||
| newData = (enet_uint8 *) enet_malloc (dataLength); | ||
| if (newData == NULL) | ||
| return -1; | ||
|
|
||
| memcpy (newData, packet -> data, packet -> dataLength); | ||
| enet_free (packet -> data); | ||
|
|
||
| packet -> data = newData; | ||
| packet -> dataLength = dataLength; | ||
|
|
||
| return 0; | ||
| } | ||
|
|
||
| static int initializedCRC32 = 0; | ||
| static enet_uint32 crcTable [256]; | ||
|
|
||
| static enet_uint32 | ||
| reflect_crc (int val, int bits) | ||
| { | ||
| int result = 0, bit; | ||
|
|
||
| for (bit = 0; bit < bits; bit ++) | ||
| { | ||
| if(val & 1) result |= 1 << (bits - 1 - bit); | ||
| val >>= 1; | ||
| } | ||
|
|
||
| return result; | ||
| } | ||
|
|
||
| static void | ||
| initialize_crc32 (void) | ||
| { | ||
| int byte; | ||
|
|
||
| for (byte = 0; byte < 256; ++ byte) | ||
| { | ||
| enet_uint32 crc = reflect_crc (byte, 8) << 24; | ||
| int offset; | ||
|
|
||
| for(offset = 0; offset < 8; ++ offset) | ||
| { | ||
| if (crc & 0x80000000) | ||
| crc = (crc << 1) ^ 0x04c11db7; | ||
| else | ||
| crc <<= 1; | ||
| } | ||
|
|
||
| crcTable [byte] = reflect_crc (crc, 32); | ||
| } | ||
|
|
||
| initializedCRC32 = 1; | ||
| } | ||
|
|
||
| enet_uint32 | ||
| enet_crc32 (const ENetBuffer * buffers, size_t bufferCount) | ||
| { | ||
| enet_uint32 crc = 0xFFFFFFFF; | ||
|
|
||
| if (! initializedCRC32) initialize_crc32 (); | ||
|
|
||
| while (bufferCount -- > 0) | ||
| { | ||
| const enet_uint8 * data = (const enet_uint8 *) buffers -> data, | ||
| * dataEnd = & data [buffers -> dataLength]; | ||
|
|
||
| while (data < dataEnd) | ||
| { | ||
| crc = (crc >> 8) ^ crcTable [(crc & 0xFF) ^ *data++]; | ||
| } | ||
|
|
||
| ++ buffers; | ||
| } | ||
|
|
||
| return ENET_HOST_TO_NET_32 (~ crc); | ||
| } | ||
|
|
||
| /** @} */ |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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" | ||
|
|
||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,356 @@ | ||
| // This file is public domain, in case it's useful to anyone. -comex | ||
|
|
||
| #include "Common/Timer.h" | ||
| #include "Common/TraversalClient.h" | ||
|
|
||
| static void GetRandomishBytes(u8* buf, size_t size) | ||
| { | ||
| // We don't need high quality random numbers (which might not be available), | ||
| // just non-repeating numbers! | ||
| srand(enet_time_get()); | ||
| for (size_t i = 0; i < size; i++) | ||
| buf[i] = rand() & 0xff; | ||
| } | ||
|
|
||
| TraversalClient::TraversalClient(ENetHost* netHost, const std::string& server, const u16 port) | ||
| : m_NetHost(netHost) | ||
| , m_Client(nullptr) | ||
| , m_FailureReason(0) | ||
| , m_ConnectRequestId(0) | ||
| , m_PendingConnect(false) | ||
| , m_Server(server) | ||
| , m_port(port) | ||
| , m_PingTime(0) | ||
| { | ||
| netHost->intercept = TraversalClient::InterceptCallback; | ||
|
|
||
| Reset(); | ||
|
|
||
| ReconnectToServer(); | ||
| } | ||
|
|
||
| TraversalClient::~TraversalClient() | ||
| { | ||
| } | ||
|
|
||
| void TraversalClient::ReconnectToServer() | ||
| { | ||
| if (enet_address_set_host(&m_ServerAddress, m_Server.c_str())) | ||
| { | ||
| OnFailure(BadHost); | ||
| return; | ||
| } | ||
| m_ServerAddress.port = m_port; | ||
|
|
||
| m_State = Connecting; | ||
|
|
||
| TraversalPacket hello = {}; | ||
| hello.type = TraversalPacketHelloFromClient; | ||
| hello.helloFromClient.protoVersion = TraversalProtoVersion; | ||
| SendTraversalPacket(hello); | ||
| if (m_Client) | ||
| m_Client->OnTraversalStateChanged(); | ||
| } | ||
|
|
||
| static ENetAddress MakeENetAddress(TraversalInetAddress* address) | ||
| { | ||
| ENetAddress eaddr; | ||
| if (address->isIPV6) | ||
| { | ||
| eaddr.port = 0; // no support yet :( | ||
| } | ||
| else | ||
| { | ||
| eaddr.host = address->address[0]; | ||
| eaddr.port = ntohs(address->port); | ||
| } | ||
| return eaddr; | ||
| } | ||
|
|
||
| void TraversalClient::ConnectToClient(const std::string& host) | ||
| { | ||
| if (host.size() > sizeof(TraversalHostId)) | ||
| { | ||
| PanicAlert("host too long"); | ||
| return; | ||
| } | ||
| TraversalPacket packet = {}; | ||
| packet.type = TraversalPacketConnectPlease; | ||
| memcpy(packet.connectPlease.hostId.data(), host.c_str(), host.size()); | ||
| m_ConnectRequestId = SendTraversalPacket(packet); | ||
| m_PendingConnect = true; | ||
| } | ||
|
|
||
| bool TraversalClient::TestPacket(u8* data, size_t size, ENetAddress* from) | ||
| { | ||
| if (from->host == m_ServerAddress.host && | ||
| from->port == m_ServerAddress.port) | ||
| { | ||
| if (size < sizeof(TraversalPacket)) | ||
| { | ||
| ERROR_LOG(NETPLAY, "Received too-short traversal packet."); | ||
| } | ||
| else | ||
| { | ||
| HandleServerPacket((TraversalPacket*) data); | ||
| return true; | ||
| } | ||
| } | ||
| return false; | ||
| } | ||
|
|
||
| //--Temporary until more of the old netplay branch is moved over | ||
| void TraversalClient::Update() | ||
| { | ||
| ENetEvent netEvent; | ||
| if (enet_host_service(m_NetHost, &netEvent, 4) > 0) | ||
| { | ||
| switch (netEvent.type) | ||
| { | ||
| case ENET_EVENT_TYPE_RECEIVE: | ||
| TestPacket(netEvent.packet->data, netEvent.packet->dataLength, &netEvent.peer->address); | ||
|
|
||
| enet_packet_destroy(netEvent.packet); | ||
| break; | ||
| default: | ||
| break; | ||
| } | ||
| } | ||
| HandleResends(); | ||
| } | ||
|
|
||
| void TraversalClient::HandleServerPacket(TraversalPacket* packet) | ||
| { | ||
| u8 ok = 1; | ||
| switch (packet->type) | ||
| { | ||
| case TraversalPacketAck: | ||
| if (!packet->ack.ok) | ||
| { | ||
| OnFailure(ServerForgotAboutUs); | ||
| break; | ||
| } | ||
| for (auto it = m_OutgoingTraversalPackets.begin(); it != m_OutgoingTraversalPackets.end(); ++it) | ||
| { | ||
| if (it->packet.requestId == packet->requestId) | ||
| { | ||
| m_OutgoingTraversalPackets.erase(it); | ||
| break; | ||
| } | ||
| } | ||
| break; | ||
| case TraversalPacketHelloFromServer: | ||
| if (m_State != Connecting) | ||
| break; | ||
| if (!packet->helloFromServer.ok) | ||
| { | ||
| OnFailure(VersionTooOld); | ||
| break; | ||
| } | ||
| m_HostId = packet->helloFromServer.yourHostId; | ||
| m_State = Connected; | ||
| if (m_Client) | ||
| m_Client->OnTraversalStateChanged(); | ||
| break; | ||
| case TraversalPacketPleaseSendPacket: | ||
| { | ||
| // security is overrated. | ||
| ENetAddress addr = MakeENetAddress(&packet->pleaseSendPacket.address); | ||
| if (addr.port != 0) | ||
| { | ||
| char message[] = "Hello from Dolphin Netplay..."; | ||
| ENetBuffer buf; | ||
| buf.data = message; | ||
| buf.dataLength = sizeof(message) - 1; | ||
| enet_socket_send(m_NetHost->socket, &addr, &buf, 1); | ||
| } | ||
| else | ||
| { | ||
| // invalid IPV6 | ||
| ok = 0; | ||
| } | ||
| break; | ||
| } | ||
| case TraversalPacketConnectReady: | ||
| case TraversalPacketConnectFailed: | ||
| { | ||
| if (!m_PendingConnect || packet->connectReady.requestId != m_ConnectRequestId) | ||
| break; | ||
|
|
||
| m_PendingConnect = false; | ||
|
|
||
| if (!m_Client) | ||
| break; | ||
|
|
||
| if (packet->type == TraversalPacketConnectReady) | ||
| m_Client->OnConnectReady(MakeENetAddress(&packet->connectReady.address)); | ||
| else | ||
| m_Client->OnConnectFailed(packet->connectFailed.reason); | ||
| break; | ||
| } | ||
| default: | ||
| WARN_LOG(NETPLAY, "Received unknown packet with type %d", packet->type); | ||
| break; | ||
| } | ||
| if (packet->type != TraversalPacketAck) | ||
| { | ||
| TraversalPacket ack = {}; | ||
| ack.type = TraversalPacketAck; | ||
| ack.requestId = packet->requestId; | ||
| ack.ack.ok = ok; | ||
|
|
||
| ENetBuffer buf; | ||
| buf.data = &ack; | ||
| buf.dataLength = sizeof(ack); | ||
| if (enet_socket_send(m_NetHost->socket, &m_ServerAddress, &buf, 1) == -1) | ||
| OnFailure(SocketSendError); | ||
| } | ||
| } | ||
|
|
||
| void TraversalClient::OnFailure(FailureReason reason) | ||
| { | ||
| m_State = Failure; | ||
| m_FailureReason = reason; | ||
|
|
||
| switch (reason) | ||
| { | ||
| case TraversalClient::BadHost: | ||
| { | ||
| PanicAlertT("Couldn't look up central server %s", m_Server.c_str()); | ||
| break; | ||
| } | ||
| case TraversalClient::VersionTooOld: | ||
| PanicAlertT("Dolphin too old for traversal server"); | ||
| break; | ||
| case TraversalClient::ServerForgotAboutUs: | ||
| PanicAlertT("Disconnected from traversal server"); | ||
| break; | ||
| case TraversalClient::SocketSendError: | ||
| PanicAlertT("Socket error sending to traversal server"); | ||
| break; | ||
| case TraversalClient::ResendTimeout: | ||
| PanicAlertT("Timeout connecting to traversal server"); | ||
| break; | ||
| } | ||
|
|
||
| if (m_Client) | ||
| m_Client->OnTraversalStateChanged(); | ||
| } | ||
|
|
||
| void TraversalClient::ResendPacket(OutgoingTraversalPacketInfo* info) | ||
| { | ||
| info->sendTime = enet_time_get(); | ||
| info->tries++; | ||
| ENetBuffer buf; | ||
| buf.data = &info->packet; | ||
| buf.dataLength = sizeof(info->packet); | ||
| if (enet_socket_send(m_NetHost->socket, &m_ServerAddress, &buf, 1) == -1) | ||
| OnFailure(SocketSendError); | ||
| } | ||
|
|
||
| void TraversalClient::HandleResends() | ||
| { | ||
| enet_uint32 now = enet_time_get(); | ||
| for (auto& tpi : m_OutgoingTraversalPackets) | ||
| { | ||
| if (now - tpi.sendTime >= (u32) (300 * tpi.tries)) | ||
| { | ||
| if (tpi.tries >= 5) | ||
| { | ||
| OnFailure(ResendTimeout); | ||
| m_OutgoingTraversalPackets.clear(); | ||
| break; | ||
| } | ||
| else | ||
| { | ||
| ResendPacket(&tpi); | ||
| } | ||
| } | ||
| } | ||
| HandlePing(); | ||
| } | ||
|
|
||
| void TraversalClient::HandlePing() | ||
| { | ||
| enet_uint32 now = enet_time_get(); | ||
| if (m_State == Connected && now - m_PingTime >= 500) | ||
| { | ||
| TraversalPacket ping = {}; | ||
| ping.type = TraversalPacketPing; | ||
| ping.ping.hostId = m_HostId; | ||
| SendTraversalPacket(ping); | ||
| m_PingTime = now; | ||
| } | ||
| } | ||
|
|
||
| TraversalRequestId TraversalClient::SendTraversalPacket(const TraversalPacket& packet) | ||
| { | ||
| OutgoingTraversalPacketInfo info; | ||
| info.packet = packet; | ||
| GetRandomishBytes((u8*) &info.packet.requestId, sizeof(info.packet.requestId)); | ||
| info.tries = 0; | ||
| m_OutgoingTraversalPackets.push_back(info); | ||
| ResendPacket(&m_OutgoingTraversalPackets.back()); | ||
| return info.packet.requestId; | ||
| } | ||
|
|
||
| void TraversalClient::Reset() | ||
| { | ||
| m_PendingConnect = false; | ||
| m_Client = nullptr; | ||
| } | ||
|
|
||
| int ENET_CALLBACK TraversalClient::InterceptCallback(ENetHost* host, ENetEvent* event) | ||
| { | ||
| auto traversalClient = g_TraversalClient.get(); | ||
| if (traversalClient->TestPacket(host->receivedData, host->receivedDataLength, &host->receivedAddress)) | ||
| { | ||
| event->type = (ENetEventType)42; | ||
| return 1; | ||
| } | ||
| return 0; | ||
| } | ||
|
|
||
| std::unique_ptr<TraversalClient> g_TraversalClient; | ||
| std::unique_ptr<ENetHost> g_MainNetHost; | ||
|
|
||
| // The settings at the previous TraversalClient reset - notably, we | ||
| // need to know not just what port it's on, but whether it was | ||
| // explicitly requested. | ||
| static std::string g_OldServer; | ||
| static u16 g_OldPort; | ||
|
|
||
| bool EnsureTraversalClient(const std::string& server, u16 port) | ||
| { | ||
|
|
||
| if (!g_MainNetHost || !g_TraversalClient || server != g_OldServer || port != g_OldPort) | ||
| { | ||
| g_OldServer = server; | ||
| g_OldPort = port ; | ||
|
|
||
| ENetAddress addr = { ENET_HOST_ANY, 0 }; | ||
| ENetHost* host = enet_host_create( | ||
| &addr, // address | ||
| 50, // peerCount | ||
| 1, // channelLimit | ||
| 0, // incomingBandwidth | ||
| 0); // outgoingBandwidth | ||
| if (!host) | ||
| { | ||
| g_MainNetHost.reset(); | ||
| return false; | ||
| } | ||
| g_MainNetHost.reset(host); | ||
| g_TraversalClient.reset(new TraversalClient(g_MainNetHost.get(), server, port)); | ||
| } | ||
| return true; | ||
| } | ||
|
|
||
| void ReleaseTraversalClient() | ||
| { | ||
| if (!g_TraversalClient) | ||
| return; | ||
|
|
||
| g_TraversalClient.release(); | ||
| g_MainNetHost.release(); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,81 @@ | ||
| // This file is public domain, in case it's useful to anyone. -comex | ||
|
|
||
| #pragma once | ||
| #include <functional> | ||
| #include <list> | ||
| #include <memory> | ||
| #include <enet/include/enet/enet.h> | ||
| #include "Common/Common.h" | ||
| #include "Common/Thread.h" | ||
| #include "Common/TraversalProto.h" | ||
|
|
||
| class TraversalClientClient | ||
| { | ||
| public: | ||
| virtual ~TraversalClientClient(){}; | ||
| virtual void OnTraversalStateChanged()=0; | ||
| virtual void OnConnectReady(ENetAddress addr)=0; | ||
| virtual void OnConnectFailed(u8 reason)=0; | ||
| }; | ||
|
|
||
| class TraversalClient | ||
| { | ||
| public: | ||
| enum State | ||
| { | ||
| Connecting, | ||
| Connected, | ||
| Failure | ||
| }; | ||
| enum FailureReason | ||
| { | ||
| BadHost = 0x300, | ||
| VersionTooOld, | ||
| ServerForgotAboutUs, | ||
| SocketSendError, | ||
| ResendTimeout, | ||
| ConnectFailedError = 0x400, | ||
| }; | ||
| TraversalClient(ENetHost* netHost, const std::string& server, const u16 port); | ||
| ~TraversalClient(); | ||
| void Reset(); | ||
| void ConnectToClient(const std::string& host); | ||
| void ReconnectToServer(); | ||
| void Update(); | ||
| // called from NetHost | ||
| bool TestPacket(u8* data, size_t size, ENetAddress* from); | ||
| void HandleResends(); | ||
|
|
||
| ENetHost* m_NetHost; | ||
| TraversalClientClient* m_Client; | ||
| TraversalHostId m_HostId; | ||
| State m_State; | ||
| int m_FailureReason; | ||
|
|
||
| private: | ||
| struct OutgoingTraversalPacketInfo | ||
| { | ||
| TraversalPacket packet; | ||
| int tries; | ||
| enet_uint32 sendTime; | ||
| }; | ||
| void HandleServerPacket(TraversalPacket* packet); | ||
| void ResendPacket(OutgoingTraversalPacketInfo* info); | ||
| TraversalRequestId SendTraversalPacket(const TraversalPacket& packet); | ||
| void OnFailure(FailureReason reason); | ||
| void HandlePing(); | ||
| static int ENET_CALLBACK InterceptCallback(ENetHost* host, ENetEvent* event); | ||
| TraversalRequestId m_ConnectRequestId; | ||
| bool m_PendingConnect; | ||
| std::list<OutgoingTraversalPacketInfo> m_OutgoingTraversalPackets; | ||
| ENetAddress m_ServerAddress; | ||
| std::string m_Server; | ||
| u16 m_port; | ||
| enet_uint32 m_PingTime; | ||
| }; | ||
| extern std::unique_ptr<TraversalClient> g_TraversalClient; | ||
| // the NetHost connected to the TraversalClient. | ||
| extern std::unique_ptr<ENetHost> g_MainNetHost; | ||
| // Create g_TraversalClient and g_MainNetHost if necessary. | ||
| bool EnsureTraversalClient(const std::string& server, u16 port); | ||
| void ReleaseTraversalClient(); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,96 @@ | ||
| // This file is public domain, in case it's useful to anyone. -comex | ||
|
|
||
| #pragma once | ||
| #include <array> | ||
| #include "Common/CommonTypes.h" | ||
|
|
||
| #define NETPLAY_CODE_SIZE 8 | ||
| typedef std::array<char, NETPLAY_CODE_SIZE> TraversalHostId; | ||
| typedef u64 TraversalRequestId; | ||
|
|
||
| enum TraversalPacketType | ||
| { | ||
| // [*->*] | ||
| TraversalPacketAck = 0, | ||
| // [c->s] | ||
| TraversalPacketPing = 1, | ||
| // [c->s] | ||
| TraversalPacketHelloFromClient = 2, | ||
| // [s->c] | ||
| TraversalPacketHelloFromServer = 3, | ||
| // [c->s] When connecting, first the client asks the central server... | ||
| TraversalPacketConnectPlease = 4, | ||
| // [s->c] ...who asks the game host to send a UDP packet to the | ||
| // client... (an ack implies success) | ||
| TraversalPacketPleaseSendPacket = 5, | ||
| // [s->c] ...which the central server relays back to the client. | ||
| TraversalPacketConnectReady = 6, | ||
| // [s->c] Alternately, the server might not have heard of this host. | ||
| TraversalPacketConnectFailed = 7 | ||
| }; | ||
|
|
||
| enum | ||
| { | ||
| TraversalProtoVersion = 0 | ||
| }; | ||
|
|
||
| enum TraversalConnectFailedReason | ||
| { | ||
| TraversalConnectFailedClientDidntRespond = 0, | ||
| TraversalConnectFailedClientFailure, | ||
| TraversalConnectFailedNoSuchClient | ||
| }; | ||
|
|
||
| #pragma pack(push, 1) | ||
| struct TraversalInetAddress | ||
| { | ||
| u8 isIPV6; | ||
| u32 address[4]; | ||
| u16 port; | ||
| }; | ||
| struct TraversalPacket | ||
| { | ||
| u8 type; | ||
| TraversalRequestId requestId; | ||
| union | ||
| { | ||
| struct | ||
| { | ||
| u8 ok; | ||
| } ack; | ||
| struct | ||
| { | ||
| TraversalHostId hostId; | ||
| } ping; | ||
| struct | ||
| { | ||
| u8 protoVersion; | ||
| } helloFromClient; | ||
| struct | ||
| { | ||
| u8 ok; | ||
| TraversalHostId yourHostId; | ||
| TraversalInetAddress yourAddress; // currently unused | ||
| } helloFromServer; | ||
| struct | ||
| { | ||
| TraversalHostId hostId; | ||
| } connectPlease; | ||
| struct | ||
| { | ||
| TraversalInetAddress address; | ||
| } pleaseSendPacket; | ||
| struct | ||
| { | ||
| TraversalRequestId requestId; | ||
| TraversalInetAddress address; | ||
| } connectReady; | ||
| struct | ||
| { | ||
| TraversalRequestId requestId; | ||
| u8 reason; | ||
| } connectFailed; | ||
| }; | ||
| }; | ||
| #pragma pack(pop) | ||
|
|