1 /**
2  * include/enet.h - a Single-Header auto-generated variant of enet.h library.
3  *
4  * Usage:
5  * #define ENET_IMPLEMENTATION exactly in ONE source file right BEFORE including the library, like:
6  *
7  * #define ENET_IMPLEMENTATION
8  * #include <enet.h>
9  *
10  * License:
11  * The MIT License (MIT)
12  *
13  * Copyright (c) 2002-2016 Lee Salzman
14  * Copyright (c) 2017-2018 Vladyslav Hrytsenko, Dominik Madarász
15  *
16  * Permission is hereby granted, free of charge, to any person obtaining a copy
17  * of this software and associated documentation files (the "Software"), to deal
18  * in the Software without restriction, including without limitation the rights
19  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
20  * copies of the Software, and to permit persons to whom the Software is
21  * furnished to do so, subject to the following conditions:
22  *
23  * The above copyright notice and this permission notice shall be included in all
24  * copies or substantial portions of the Software.
25  *
26  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
27  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
28  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
29  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
30  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
31  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
32  * SOFTWARE.
33  *
34  */
35 #ifndef ENET_INCLUDE_H
36 #define ENET_INCLUDE_H
37 
38 #include <stdlib.h>
39 #include <stdbool.h>
40 #include <stdint.h>
41 #include <time.h>
42 
43 #define ENET_VERSION_MAJOR 2
44 #define ENET_VERSION_MINOR 2
45 #define ENET_VERSION_PATCH 0
46 #define ENET_VERSION_CREATE(major, minor, patch) (((major)<<16) | ((minor)<<8) | (patch))
47 #define ENET_VERSION_GET_MAJOR(version) (((version)>>16)&0xFF)
48 #define ENET_VERSION_GET_MINOR(version) (((version)>>8)&0xFF)
49 #define ENET_VERSION_GET_PATCH(version) ((version)&0xFF)
50 #define ENET_VERSION ENET_VERSION_CREATE(ENET_VERSION_MAJOR, ENET_VERSION_MINOR, ENET_VERSION_PATCH)
51 
52 #define ENET_TIME_OVERFLOW 86400000
53 #define ENET_TIME_LESS(a, b) ((a) - (b) >= ENET_TIME_OVERFLOW)
54 #define ENET_TIME_GREATER(a, b) ((b) - (a) >= ENET_TIME_OVERFLOW)
55 #define ENET_TIME_LESS_EQUAL(a, b) (! ENET_TIME_GREATER (a, b))
56 #define ENET_TIME_GREATER_EQUAL(a, b) (! ENET_TIME_LESS (a, b))
57 #define ENET_TIME_DIFFERENCE(a, b) ((a) - (b) >= ENET_TIME_OVERFLOW ? (b) - (a) : (a) - (b))
58 
59 // =======================================================================//
60 // !
61 // ! System differences
62 // !
63 // =======================================================================//
64 
65 #if defined(_WIN32)
66     #if defined(_MSC_VER) && defined(ENET_IMPLEMENTATION)
67         #pragma warning (disable: 4267) // size_t to int conversion
68         #pragma warning (disable: 4244) // 64bit to 32bit int
69         #pragma warning (disable: 4018) // signed/unsigned mismatch
70         #pragma warning (disable: 4146) // unary minus operator applied to unsigned type
71     #endif
72 
73     #if _MSC_VER
74         #ifndef ENET_NO_PRAGMA_LINK
75             #pragma comment(lib, "ws2_32.lib")
76             #pragma comment(lib, "winmm.lib")
77         #endif
78     #endif
79 
80     #if _MSC_VER >= 1910
81     /* It looks like there were changes as of Visual Studio 2017 and there are no 32/64 bit
82        versions of _InterlockedExchange[operation], only InterlockedExchange[operation]
83        (without leading underscore), so we have to distinguish between compiler versions */
84     #define NOT_UNDERSCORED_INTERLOCKED_EXCHANGE
85     #endif
86 
87     #ifdef __GNUC__
88     #if (_WIN32_WINNT < 0x0501)
89     #undef _WIN32_WINNT
90     #define _WIN32_WINNT 0x0501
91     #endif
92     #endif
93 
94     #include <winsock2.h>
95     #include <ws2tcpip.h>
96     #include <mmsystem.h>
97 
98     #include <intrin.h>
99 
100     #if defined(_WIN32) && defined(_MSC_VER)
101     #if _MSC_VER < 1900
102     typedef struct timespec {
103         long tv_sec;
104         long tv_nsec;
105     };
106     #endif
107     #define CLOCK_MONOTONIC 0
108     #endif
109 
110     typedef SOCKET ENetSocket;
111     #define ENET_SOCKET_NULL INVALID_SOCKET
112 
113     #define ENET_HOST_TO_NET_16(value) (htons(value))
114     #define ENET_HOST_TO_NET_32(value) (htonl(value))
115 
116     #define ENET_NET_TO_HOST_16(value) (ntohs(value))
117     #define ENET_NET_TO_HOST_32(value) (ntohl(value))
118 
119     typedef struct {
120         size_t dataLength;
121         void * data;
122     } ENetBuffer;
123 
124     #define ENET_CALLBACK __cdecl
125 
126     #ifdef ENET_DLL
127     #ifdef ENET_IMPLEMENTATION
128     #define ENET_API __declspec( dllexport )
129     #else
130     #define ENET_API __declspec( dllimport )
131     #endif // ENET_IMPLEMENTATION
132     #else
133     #define ENET_API extern
134     #endif // ENET_DLL
135 
136     typedef fd_set ENetSocketSet;
137 
138     #define ENET_SOCKETSET_EMPTY(sockset)          FD_ZERO(&(sockset))
139     #define ENET_SOCKETSET_ADD(sockset, socket)    FD_SET(socket, &(sockset))
140     #define ENET_SOCKETSET_REMOVE(sockset, socket) FD_CLR(socket, &(sockset))
141     #define ENET_SOCKETSET_CHECK(sockset, socket)  FD_ISSET(socket, &(sockset))
142 #else
143     #include <sys/types.h>
144     #include <sys/ioctl.h>
145     #include <sys/time.h>
146     #include <sys/socket.h>
147     #include <poll.h>
148     #include <arpa/inet.h>
149     #include <netinet/in.h>
150     #include <netinet/tcp.h>
151     #include <netdb.h>
152     #include <unistd.h>
153     #include <string.h>
154     #include <errno.h>
155     #include <fcntl.h>
156 
157     #ifdef __APPLE__
158     #include <mach/clock.h>
159     #include <mach/mach.h>
160     #include <Availability.h>
161     #endif
162 
163     #ifndef MSG_NOSIGNAL
164     #define MSG_NOSIGNAL 0
165     #endif
166 
167     #ifdef MSG_MAXIOVLEN
168     #define ENET_BUFFER_MAXIMUM MSG_MAXIOVLEN
169     #endif
170 
171     typedef int ENetSocket;
172 
173     #define ENET_SOCKET_NULL -1
174 
175     #define ENET_HOST_TO_NET_16(value) (htons(value)) /**< macro that converts host to net byte-order of a 16-bit value */
176     #define ENET_HOST_TO_NET_32(value) (htonl(value)) /**< macro that converts host to net byte-order of a 32-bit value */
177 
178     #define ENET_NET_TO_HOST_16(value) (ntohs(value)) /**< macro that converts net to host byte-order of a 16-bit value */
179     #define ENET_NET_TO_HOST_32(value) (ntohl(value)) /**< macro that converts net to host byte-order of a 32-bit value */
180 
181     typedef struct {
182         void * data;
183         size_t dataLength;
184     } ENetBuffer;
185 
186     #define ENET_CALLBACK
187     #define ENET_API extern
188 
189     typedef fd_set ENetSocketSet;
190 
191     #define ENET_SOCKETSET_EMPTY(sockset)          FD_ZERO(&(sockset))
192     #define ENET_SOCKETSET_ADD(sockset, socket)    FD_SET(socket, &(sockset))
193     #define ENET_SOCKETSET_REMOVE(sockset, socket) FD_CLR(socket, &(sockset))
194     #define ENET_SOCKETSET_CHECK(sockset, socket)  FD_ISSET(socket, &(sockset))
195 #endif
196 
197 #ifndef ENET_BUFFER_MAXIMUM
198 #define ENET_BUFFER_MAXIMUM (1 + 2 * ENET_PROTOCOL_MAXIMUM_PACKET_COMMANDS)
199 #endif
200 
201 #define ENET_MAX(x, y) ((x) > (y) ? (x) : (y))
202 #define ENET_MIN(x, y) ((x) < (y) ? (x) : (y))
203 
204 #define ENET_IPV6           1
205 #define ENET_HOST_ANY       in6addr_any
206 #define ENET_HOST_BROADCAST 0xFFFFFFFFU
207 #define ENET_PORT_ANY       0
208 
209 #ifdef __cplusplus
210 extern "C" {
211 #endif
212 
213 // =======================================================================//
214 // !
215 // ! Basic stuff
216 // !
217 // =======================================================================//
218 
219     typedef uint8_t   enet_uint8;   /**< unsigned 8-bit type  */
220     typedef uint16_t enet_uint16;   /**< unsigned 16-bit type */
221     typedef uint32_t enet_uint32;   /**< unsigned 32-bit type */
222     typedef uint64_t enet_uint64;   /**< unsigned 64-bit type */
223 
224     typedef enet_uint32 ENetVersion;
225 
226     typedef struct _ENetCallbacks {
227         void *(ENET_CALLBACK *malloc) (size_t size);
228         void (ENET_CALLBACK *free) (void *memory);
229         void (ENET_CALLBACK *no_memory) (void);
230     } ENetCallbacks;
231 
232     extern void *enet_malloc(size_t);
233     extern void enet_free(void *);
234 
235 // =======================================================================//
236 // !
237 // ! List
238 // !
239 // =======================================================================//
240 
241     typedef struct _ENetListNode {
242         struct _ENetListNode *next;
243         struct _ENetListNode *previous;
244     } ENetListNode;
245 
246     typedef ENetListNode *ENetListIterator;
247 
248     typedef struct _ENetList {
249         ENetListNode sentinel;
250     } ENetList;
251 
252     extern ENetListIterator enet_list_insert(ENetListIterator, void *);
253     extern ENetListIterator enet_list_move(ENetListIterator, void *, void *);
254 
255     extern void *enet_list_remove(ENetListIterator);
256     extern void enet_list_clear(ENetList *);
257     extern size_t enet_list_size(ENetList *);
258 
259     #define enet_list_begin(list) ((list)->sentinel.next)
260     #define enet_list_end(list) (&(list)->sentinel)
261     #define enet_list_empty(list) (enet_list_begin(list) == enet_list_end(list))
262     #define enet_list_next(iterator) ((iterator)->next)
263     #define enet_list_previous(iterator) ((iterator)->previous)
264     #define enet_list_front(list) ((void *)(list)->sentinel.next)
265     #define enet_list_back(list) ((void *)(list)->sentinel.previous)
266 
267 
268 // =======================================================================//
269 // !
270 // ! Protocol
271 // !
272 // =======================================================================//
273 
274     enum {
275         ENET_PROTOCOL_MINIMUM_MTU             = 576,
276         ENET_PROTOCOL_MAXIMUM_MTU             = 4096,
277         ENET_PROTOCOL_MAXIMUM_PACKET_COMMANDS = 32,
278         ENET_PROTOCOL_MINIMUM_WINDOW_SIZE     = 4096,
279         ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE     = 65536,
280         ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT   = 1,
281         ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT   = 255,
282         ENET_PROTOCOL_MAXIMUM_PEER_ID         = 0xFFF,
283         ENET_PROTOCOL_MAXIMUM_FRAGMENT_COUNT  = 1024 * 1024
284     };
285 
286     typedef enum _ENetProtocolCommand {
287         ENET_PROTOCOL_COMMAND_NONE                     = 0,
288         ENET_PROTOCOL_COMMAND_ACKNOWLEDGE              = 1,
289         ENET_PROTOCOL_COMMAND_CONNECT                  = 2,
290         ENET_PROTOCOL_COMMAND_VERIFY_CONNECT           = 3,
291         ENET_PROTOCOL_COMMAND_DISCONNECT               = 4,
292         ENET_PROTOCOL_COMMAND_PING                     = 5,
293         ENET_PROTOCOL_COMMAND_SEND_RELIABLE            = 6,
294         ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE          = 7,
295         ENET_PROTOCOL_COMMAND_SEND_FRAGMENT            = 8,
296         ENET_PROTOCOL_COMMAND_SEND_UNSEQUENCED         = 9,
297         ENET_PROTOCOL_COMMAND_BANDWIDTH_LIMIT          = 10,
298         ENET_PROTOCOL_COMMAND_THROTTLE_CONFIGURE       = 11,
299         ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE_FRAGMENT = 12,
300         ENET_PROTOCOL_COMMAND_COUNT                    = 13,
301 
302         ENET_PROTOCOL_COMMAND_MASK                     = 0x0F,
303 
304         ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE         = (1 << 7),
305         ENET_PROTOCOL_COMMAND_FLAG_UNSEQUENCED         = (1 << 6),
306 
307         ENET_PROTOCOL_COMMAND_FLAG_MASK                = 0xC0
308     } ENetProtocolCommand;
309 
310     typedef enum _ENetProtocolFlag {
311         ENET_PROTOCOL_HEADER_FLAG_COMPRESSED   = (1 << 14),
312         ENET_PROTOCOL_HEADER_FLAG_SENT_TIME    = (1 << 15),
313         ENET_PROTOCOL_HEADER_FLAG_MASK         = ENET_PROTOCOL_HEADER_FLAG_COMPRESSED | ENET_PROTOCOL_HEADER_FLAG_SENT_TIME,
314 
315         ENET_PROTOCOL_HEADER_SESSION_MASK      = (3 << 12),
316         ENET_PROTOCOL_HEADER_SESSION_SHIFT     = 12
317     } ENetProtocolFlag;
318 
319     #ifdef _MSC_VER
320     #pragma pack(push, 1)
321     #define ENET_PACKED
322     #elif defined(__GNUC__) || defined(__clang__)
323     #define ENET_PACKED __attribute__ ((packed))
324     #else
325     #define ENET_PACKED
326     #endif
327 
328     typedef struct _ENetProtocolHeader {
329         enet_uint16 peerID;
330         enet_uint16 sentTime;
331     } ENET_PACKED ENetProtocolHeader;
332 
333     typedef struct _ENetProtocolCommandHeader {
334         enet_uint8  command;
335         enet_uint8  channelID;
336         enet_uint16 reliableSequenceNumber;
337     } ENET_PACKED ENetProtocolCommandHeader;
338 
339     typedef struct _ENetProtocolAcknowledge {
340         ENetProtocolCommandHeader header;
341         enet_uint16               receivedReliableSequenceNumber;
342         enet_uint16               receivedSentTime;
343     } ENET_PACKED ENetProtocolAcknowledge;
344 
345     typedef struct _ENetProtocolConnect {
346         ENetProtocolCommandHeader header;
347         enet_uint16               outgoingPeerID;
348         enet_uint8                incomingSessionID;
349         enet_uint8                outgoingSessionID;
350         enet_uint32               mtu;
351         enet_uint32               windowSize;
352         enet_uint32               channelCount;
353         enet_uint32               incomingBandwidth;
354         enet_uint32               outgoingBandwidth;
355         enet_uint32               packetThrottleInterval;
356         enet_uint32               packetThrottleAcceleration;
357         enet_uint32               packetThrottleDeceleration;
358         enet_uint32               connectID;
359         enet_uint32               data;
360     } ENET_PACKED ENetProtocolConnect;
361 
362     typedef struct _ENetProtocolVerifyConnect {
363         ENetProtocolCommandHeader header;
364         enet_uint16               outgoingPeerID;
365         enet_uint8                incomingSessionID;
366         enet_uint8                outgoingSessionID;
367         enet_uint32               mtu;
368         enet_uint32               windowSize;
369         enet_uint32               channelCount;
370         enet_uint32               incomingBandwidth;
371         enet_uint32               outgoingBandwidth;
372         enet_uint32               packetThrottleInterval;
373         enet_uint32               packetThrottleAcceleration;
374         enet_uint32               packetThrottleDeceleration;
375         enet_uint32               connectID;
376     } ENET_PACKED ENetProtocolVerifyConnect;
377 
378     typedef struct _ENetProtocolBandwidthLimit {
379         ENetProtocolCommandHeader header;
380         enet_uint32               incomingBandwidth;
381         enet_uint32               outgoingBandwidth;
382     } ENET_PACKED ENetProtocolBandwidthLimit;
383 
384     typedef struct _ENetProtocolThrottleConfigure {
385         ENetProtocolCommandHeader header;
386         enet_uint32               packetThrottleInterval;
387         enet_uint32               packetThrottleAcceleration;
388         enet_uint32               packetThrottleDeceleration;
389     } ENET_PACKED ENetProtocolThrottleConfigure;
390 
391     typedef struct _ENetProtocolDisconnect {
392         ENetProtocolCommandHeader header;
393         enet_uint32               data;
394     } ENET_PACKED ENetProtocolDisconnect;
395 
396     typedef struct _ENetProtocolPing {
397         ENetProtocolCommandHeader header;
398     } ENET_PACKED ENetProtocolPing;
399 
400     typedef struct _ENetProtocolSendReliable {
401         ENetProtocolCommandHeader header;
402         enet_uint16               dataLength;
403     } ENET_PACKED ENetProtocolSendReliable;
404 
405     typedef struct _ENetProtocolSendUnreliable {
406         ENetProtocolCommandHeader header;
407         enet_uint16               unreliableSequenceNumber;
408         enet_uint16               dataLength;
409     } ENET_PACKED ENetProtocolSendUnreliable;
410 
411     typedef struct _ENetProtocolSendUnsequenced {
412         ENetProtocolCommandHeader header;
413         enet_uint16               unsequencedGroup;
414         enet_uint16               dataLength;
415     } ENET_PACKED ENetProtocolSendUnsequenced;
416 
417     typedef struct _ENetProtocolSendFragment {
418         ENetProtocolCommandHeader header;
419         enet_uint16               startSequenceNumber;
420         enet_uint16               dataLength;
421         enet_uint32               fragmentCount;
422         enet_uint32               fragmentNumber;
423         enet_uint32               totalLength;
424         enet_uint32               fragmentOffset;
425     } ENET_PACKED ENetProtocolSendFragment;
426 
427     typedef union _ENetProtocol {
428         ENetProtocolCommandHeader     header;
429         ENetProtocolAcknowledge       acknowledge;
430         ENetProtocolConnect           connect;
431         ENetProtocolVerifyConnect     verifyConnect;
432         ENetProtocolDisconnect        disconnect;
433         ENetProtocolPing              ping;
434         ENetProtocolSendReliable      sendReliable;
435         ENetProtocolSendUnreliable    sendUnreliable;
436         ENetProtocolSendUnsequenced   sendUnsequenced;
437         ENetProtocolSendFragment      sendFragment;
438         ENetProtocolBandwidthLimit    bandwidthLimit;
439         ENetProtocolThrottleConfigure throttleConfigure;
440     } ENET_PACKED ENetProtocol;
441 
442     #ifdef _MSC_VER
443     #pragma pack(pop)
444     #endif
445 
446 // =======================================================================//
447 // !
448 // ! General ENet structs/enums
449 // !
450 // =======================================================================//
451 
452     typedef enum _ENetSocketType {
453         ENET_SOCKET_TYPE_STREAM   = 1,
454         ENET_SOCKET_TYPE_DATAGRAM = 2
455     } ENetSocketType;
456 
457     typedef enum _ENetSocketWait {
458         ENET_SOCKET_WAIT_NONE      = 0,
459         ENET_SOCKET_WAIT_SEND      = (1 << 0),
460         ENET_SOCKET_WAIT_RECEIVE   = (1 << 1),
461         ENET_SOCKET_WAIT_INTERRUPT = (1 << 2)
462     } ENetSocketWait;
463 
464     typedef enum _ENetSocketOption {
465         ENET_SOCKOPT_NONBLOCK  = 1,
466         ENET_SOCKOPT_BROADCAST = 2,
467         ENET_SOCKOPT_RCVBUF    = 3,
468         ENET_SOCKOPT_SNDBUF    = 4,
469         ENET_SOCKOPT_REUSEADDR = 5,
470         ENET_SOCKOPT_RCVTIMEO  = 6,
471         ENET_SOCKOPT_SNDTIMEO  = 7,
472         ENET_SOCKOPT_ERROR     = 8,
473         ENET_SOCKOPT_NODELAY   = 9,
474         ENET_SOCKOPT_IPV6_V6ONLY = 10,
475     } ENetSocketOption;
476 
477     typedef enum _ENetSocketShutdown {
478         ENET_SOCKET_SHUTDOWN_READ       = 0,
479         ENET_SOCKET_SHUTDOWN_WRITE      = 1,
480         ENET_SOCKET_SHUTDOWN_READ_WRITE = 2
481     } ENetSocketShutdown;
482 
483     /**
484      * Portable internet address structure.
485      *
486      * The host must be specified in network byte-order, and the port must be in host
487      * byte-order. The constant ENET_HOST_ANY may be used to specify the default
488      * server host. The constant ENET_HOST_BROADCAST may be used to specify the
489      * broadcast address (255.255.255.255).  This makes sense for enet_host_connect,
490      * but not for enet_host_create.  Once a server responds to a broadcast, the
491      * address is updated from ENET_HOST_BROADCAST to the server's actual IP address.
492      */
493     typedef struct _ENetAddress {
494         struct in6_addr host;
495         enet_uint16 port;
496         enet_uint16 sin6_scope_id;
497     } ENetAddress;
498 
499     #define in6_equal(in6_addr_a, in6_addr_b) (memcmp(&in6_addr_a, &in6_addr_b, sizeof(struct in6_addr)) == 0)
500 
501     /**
502      * Packet flag bit constants.
503      *
504      * The host must be specified in network byte-order, and the port must be in
505      * host byte-order. The constant ENET_HOST_ANY may be used to specify the
506      * default server host.
507      *
508      * @sa ENetPacket
509      */
510     typedef enum _ENetPacketFlag {
511         ENET_PACKET_FLAG_RELIABLE            = (1 << 0), /** packet must be received by the target peer and resend attempts should be made until the packet is delivered */
512         ENET_PACKET_FLAG_UNSEQUENCED         = (1 << 1), /** packet will not be sequenced with other packets not supported for reliable packets */
513         ENET_PACKET_FLAG_NO_ALLOCATE         = (1 << 2), /** packet will not allocate data, and user must supply it instead */
514         ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT = (1 << 3), /** packet will be fragmented using unreliable (instead of reliable) sends if it exceeds the MTU */
515         ENET_PACKET_FLAG_SENT                = (1 << 8), /** whether the packet has been sent from all queues it has been entered into */
516     } ENetPacketFlag;
517 
518     typedef void (ENET_CALLBACK *ENetPacketFreeCallback)(void *);
519 
520     /**
521      * ENet packet structure.
522      *
523      * An ENet data packet that may be sent to or received from a peer. The shown
524      * fields should only be read and never modified. The data field contains the
525      * allocated data for the packet. The dataLength fields specifies the length
526      * of the allocated data.  The flags field is either 0 (specifying no flags),
527      * or a bitwise-or of any combination of the following flags:
528      *
529      *    ENET_PACKET_FLAG_RELIABLE - packet must be received by the target peer and resend attempts should be made until the packet is delivered
530      *    ENET_PACKET_FLAG_UNSEQUENCED - packet will not be sequenced with other packets (not supported for reliable packets)
531      *    ENET_PACKET_FLAG_NO_ALLOCATE - packet will not allocate data, and user must supply it instead
532      *    ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT - packet will be fragmented using unreliable (instead of reliable) sends if it exceeds the MTU
533      *    ENET_PACKET_FLAG_SENT - whether the packet has been sent from all queues it has been entered into
534      * @sa ENetPacketFlag
535      */
536     typedef struct _ENetPacket {
537         size_t                 referenceCount; /**< internal use only */
538         enet_uint32            flags;          /**< bitwise-or of ENetPacketFlag constants */
539         enet_uint8 *           data;           /**< allocated data for packet */
540         size_t                 dataLength;     /**< length of data */
541         ENetPacketFreeCallback freeCallback;   /**< function to be called when the packet is no longer in use */
542         void *                 userData;       /**< application private data, may be freely modified */
543     } ENetPacket;
544 
545     typedef struct _ENetAcknowledgement {
546         ENetListNode acknowledgementList;
547         enet_uint32  sentTime;
548         ENetProtocol command;
549     } ENetAcknowledgement;
550 
551     typedef struct _ENetOutgoingCommand {
552         ENetListNode outgoingCommandList;
553         enet_uint16  reliableSequenceNumber;
554         enet_uint16  unreliableSequenceNumber;
555         enet_uint32  sentTime;
556         enet_uint32  roundTripTimeout;
557         enet_uint32  roundTripTimeoutLimit;
558         enet_uint32  fragmentOffset;
559         enet_uint16  fragmentLength;
560         enet_uint16  sendAttempts;
561         ENetProtocol command;
562         ENetPacket * packet;
563     } ENetOutgoingCommand;
564 
565     typedef struct _ENetIncomingCommand {
566         ENetListNode incomingCommandList;
567         enet_uint16  reliableSequenceNumber;
568         enet_uint16  unreliableSequenceNumber;
569         ENetProtocol command;
570         enet_uint32  fragmentCount;
571         enet_uint32  fragmentsRemaining;
572         enet_uint32 *fragments;
573         ENetPacket * packet;
574     } ENetIncomingCommand;
575 
576     typedef enum _ENetPeerState {
577         ENET_PEER_STATE_DISCONNECTED             = 0,
578         ENET_PEER_STATE_CONNECTING               = 1,
579         ENET_PEER_STATE_ACKNOWLEDGING_CONNECT    = 2,
580         ENET_PEER_STATE_CONNECTION_PENDING       = 3,
581         ENET_PEER_STATE_CONNECTION_SUCCEEDED     = 4,
582         ENET_PEER_STATE_CONNECTED                = 5,
583         ENET_PEER_STATE_DISCONNECT_LATER         = 6,
584         ENET_PEER_STATE_DISCONNECTING            = 7,
585         ENET_PEER_STATE_ACKNOWLEDGING_DISCONNECT = 8,
586         ENET_PEER_STATE_ZOMBIE                   = 9
587     } ENetPeerState;
588 
589     enum {
590         ENET_HOST_RECEIVE_BUFFER_SIZE          = 256 * 1024,
591         ENET_HOST_SEND_BUFFER_SIZE             = 256 * 1024,
592         ENET_HOST_BANDWIDTH_THROTTLE_INTERVAL  = 1000,
593         ENET_HOST_DEFAULT_MTU                  = 1400,
594         ENET_HOST_DEFAULT_MAXIMUM_PACKET_SIZE  = 32 * 1024 * 1024,
595         ENET_HOST_DEFAULT_MAXIMUM_WAITING_DATA = 32 * 1024 * 1024,
596 
597         ENET_PEER_DEFAULT_ROUND_TRIP_TIME      = 500,
598         ENET_PEER_DEFAULT_PACKET_THROTTLE      = 32,
599         ENET_PEER_PACKET_THROTTLE_SCALE        = 32,
600         ENET_PEER_PACKET_THROTTLE_COUNTER      = 7,
601         ENET_PEER_PACKET_THROTTLE_ACCELERATION = 2,
602         ENET_PEER_PACKET_THROTTLE_DECELERATION = 2,
603         ENET_PEER_PACKET_THROTTLE_INTERVAL     = 5000,
604         ENET_PEER_PACKET_LOSS_SCALE            = (1 << 16),
605         ENET_PEER_PACKET_LOSS_INTERVAL         = 10000,
606         ENET_PEER_WINDOW_SIZE_SCALE            = 64 * 1024,
607         ENET_PEER_TIMEOUT_LIMIT                = 32,
608         ENET_PEER_TIMEOUT_MINIMUM              = 5000,
609         ENET_PEER_TIMEOUT_MAXIMUM              = 30000,
610         ENET_PEER_PING_INTERVAL                = 500,
611         ENET_PEER_UNSEQUENCED_WINDOWS          = 64,
612         ENET_PEER_UNSEQUENCED_WINDOW_SIZE      = 1024,
613         ENET_PEER_FREE_UNSEQUENCED_WINDOWS     = 32,
614         ENET_PEER_RELIABLE_WINDOWS             = 16,
615         ENET_PEER_RELIABLE_WINDOW_SIZE         = 0x1000,
616         ENET_PEER_FREE_RELIABLE_WINDOWS        = 8
617     };
618 
619     typedef struct _ENetChannel {
620         enet_uint16 outgoingReliableSequenceNumber;
621         enet_uint16 outgoingUnreliableSequenceNumber;
622         enet_uint16 usedReliableWindows;
623         enet_uint16 reliableWindows[ENET_PEER_RELIABLE_WINDOWS];
624         enet_uint16 incomingReliableSequenceNumber;
625         enet_uint16 incomingUnreliableSequenceNumber;
626         ENetList    incomingReliableCommands;
627         ENetList    incomingUnreliableCommands;
628     } ENetChannel;
629 
630     /**
631      * An ENet peer which data packets may be sent or received from.
632      *
633      * No fields should be modified unless otherwise specified.
634      */
635     typedef struct _ENetPeer {
636         ENetListNode      dispatchList;
637         struct _ENetHost *host;
638         enet_uint16       outgoingPeerID;
639         enet_uint16       incomingPeerID;
640         enet_uint32       connectID;
641         enet_uint8        outgoingSessionID;
642         enet_uint8        incomingSessionID;
643         ENetAddress       address; /**< Internet address of the peer */
644         void *            data;    /**< Application private data, may be freely modified */
645         ENetPeerState     state;
646         ENetChannel *     channels;
647         size_t            channelCount;      /**< Number of channels allocated for communication with peer */
648         enet_uint32       incomingBandwidth; /**< Downstream bandwidth of the client in bytes/second */
649         enet_uint32       outgoingBandwidth; /**< Upstream bandwidth of the client in bytes/second */
650         enet_uint32       incomingBandwidthThrottleEpoch;
651         enet_uint32       outgoingBandwidthThrottleEpoch;
652         enet_uint32       incomingDataTotal;
653         enet_uint64       totalDataReceived;
654         enet_uint32       outgoingDataTotal;
655         enet_uint64       totalDataSent;
656         enet_uint32       lastSendTime;
657         enet_uint32       lastReceiveTime;
658         enet_uint32       nextTimeout;
659         enet_uint32       earliestTimeout;
660         enet_uint32       packetLossEpoch;
661         enet_uint32       packetsSent;
662         enet_uint64       totalPacketsSent; /**< total number of packets sent during a session */
663         enet_uint32       packetsLost;
664         enet_uint32       totalPacketsLost;     /**< total number of packets lost during a session */
665         enet_uint32       packetLoss; /**< mean packet loss of reliable packets as a ratio with respect to the constant ENET_PEER_PACKET_LOSS_SCALE */
666         enet_uint32       packetLossVariance;
667         enet_uint32       packetThrottle;
668         enet_uint32       packetThrottleLimit;
669         enet_uint32       packetThrottleCounter;
670         enet_uint32       packetThrottleEpoch;
671         enet_uint32       packetThrottleAcceleration;
672         enet_uint32       packetThrottleDeceleration;
673         enet_uint32       packetThrottleInterval;
674         enet_uint32       pingInterval;
675         enet_uint32       timeoutLimit;
676         enet_uint32       timeoutMinimum;
677         enet_uint32       timeoutMaximum;
678         enet_uint32       lastRoundTripTime;
679         enet_uint32       lowestRoundTripTime;
680         enet_uint32       lastRoundTripTimeVariance;
681         enet_uint32       highestRoundTripTimeVariance;
682         enet_uint32       roundTripTime; /**< mean round trip time (RTT), in milliseconds, between sending a reliable packet and receiving its acknowledgement */
683         enet_uint32       roundTripTimeVariance;
684         enet_uint32       mtu;
685         enet_uint32       windowSize;
686         enet_uint32       reliableDataInTransit;
687         enet_uint16       outgoingReliableSequenceNumber;
688         ENetList          acknowledgements;
689         ENetList          sentReliableCommands;
690         ENetList          sentUnreliableCommands;
691         ENetList          outgoingReliableCommands;
692         ENetList          outgoingUnreliableCommands;
693         ENetList          dispatchedCommands;
694         int               needsDispatch;
695         enet_uint16       incomingUnsequencedGroup;
696         enet_uint16       outgoingUnsequencedGroup;
697         enet_uint32       unsequencedWindow[ENET_PEER_UNSEQUENCED_WINDOW_SIZE / 32];
698         enet_uint32       eventData;
699         size_t            totalWaitingData;
700     } ENetPeer;
701 
702     /** An ENet packet compressor for compressing UDP packets before socket sends or receives. */
703     typedef struct _ENetCompressor {
704         /** Context data for the compressor. Must be non-NULL. */
705         void *context;
706 
707         /** Compresses from inBuffers[0:inBufferCount-1], containing inLimit bytes, to outData, outputting at most outLimit bytes. Should return 0 on failure. */
708         size_t(ENET_CALLBACK * compress) (void *context, const ENetBuffer * inBuffers, size_t inBufferCount, size_t inLimit, enet_uint8 * outData, size_t outLimit);
709 
710         /** Decompresses from inData, containing inLimit bytes, to outData, outputting at most outLimit bytes. Should return 0 on failure. */
711         size_t(ENET_CALLBACK * decompress) (void *context, const enet_uint8 * inData, size_t inLimit, enet_uint8 * outData, size_t outLimit);
712 
713         /** Destroys the context when compression is disabled or the host is destroyed. May be NULL. */
714         void (ENET_CALLBACK * destroy)(void *context);
715     } ENetCompressor;
716 
717     /** Callback that computes the checksum of the data held in buffers[0:bufferCount-1] */
718     typedef enet_uint32 (ENET_CALLBACK * ENetChecksumCallback)(const ENetBuffer *buffers, size_t bufferCount);
719 
720     /** Callback for intercepting received raw UDP packets. Should return 1 to intercept, 0 to ignore, or -1 to propagate an error. */
721     typedef int (ENET_CALLBACK * ENetInterceptCallback)(struct _ENetHost *host, void *event);
722 
723     /** An ENet host for communicating with peers.
724      *
725      * No fields should be modified unless otherwise stated.
726      *
727      *  @sa enet_host_create()
728      *  @sa enet_host_destroy()
729      *  @sa enet_host_connect()
730      *  @sa enet_host_service()
731      *  @sa enet_host_flush()
732      *  @sa enet_host_broadcast()
733      *  @sa enet_host_compress()
734      *  @sa enet_host_channel_limit()
735      *  @sa enet_host_bandwidth_limit()
736      *  @sa enet_host_bandwidth_throttle()
737      */
738     typedef struct _ENetHost {
739         ENetSocket            socket;
740         ENetAddress           address;           /**< Internet address of the host */
741         enet_uint32           incomingBandwidth; /**< downstream bandwidth of the host */
742         enet_uint32           outgoingBandwidth; /**< upstream bandwidth of the host */
743         enet_uint32           bandwidthThrottleEpoch;
744         enet_uint32           mtu;
745         enet_uint32           randomSeed;
746         int                   recalculateBandwidthLimits;
747         ENetPeer *            peers;        /**< array of peers allocated for this host */
748         size_t                peerCount;    /**< number of peers allocated for this host */
749         size_t                channelLimit; /**< maximum number of channels allowed for connected peers */
750         enet_uint32           serviceTime;
751         ENetList              dispatchQueue;
752         int                   continueSending;
753         size_t                packetSize;
754         enet_uint16           headerFlags;
755         ENetProtocol          commands[ENET_PROTOCOL_MAXIMUM_PACKET_COMMANDS];
756         size_t                commandCount;
757         ENetBuffer            buffers[ENET_BUFFER_MAXIMUM];
758         size_t                bufferCount;
759         ENetChecksumCallback  checksum; /**< callback the user can set to enable packet checksums for this host */
760         ENetCompressor        compressor;
761         enet_uint8            packetData[2][ENET_PROTOCOL_MAXIMUM_MTU];
762         ENetAddress           receivedAddress;
763         enet_uint8 *          receivedData;
764         size_t                receivedDataLength;
765         enet_uint32           totalSentData;        /**< total data sent, user should reset to 0 as needed to prevent overflow */
766         enet_uint32           totalSentPackets;     /**< total UDP packets sent, user should reset to 0 as needed to prevent overflow */
767         enet_uint32           totalReceivedData;    /**< total data received, user should reset to 0 as needed to prevent overflow */
768         enet_uint32           totalReceivedPackets; /**< total UDP packets received, user should reset to 0 as needed to prevent overflow */
769         ENetInterceptCallback intercept;            /**< callback the user can set to intercept received raw UDP packets */
770         size_t                connectedPeers;
771         size_t                bandwidthLimitedPeers;
772         size_t                duplicatePeers;     /**< optional number of allowed peers from duplicate IPs, defaults to ENET_PROTOCOL_MAXIMUM_PEER_ID */
773         size_t                maximumPacketSize;  /**< the maximum allowable packet size that may be sent or received on a peer */
774         size_t                maximumWaitingData; /**< the maximum aggregate amount of buffer space a peer may use waiting for packets to be delivered */
775     } ENetHost;
776 
777     /**
778      * An ENet event type, as specified in @ref ENetEvent.
779      */
780     typedef enum _ENetEventType {
781         /** no event occurred within the specified time limit */
782         ENET_EVENT_TYPE_NONE       = 0,
783 
784         /** a connection request initiated by enet_host_connect has completed.
785          * The peer field contains the peer which successfully connected.
786          */
787         ENET_EVENT_TYPE_CONNECT    = 1,
788 
789         /** a peer has disconnected.  This event is generated on a successful
790          * completion of a disconnect initiated by enet_peer_disconnect, if
791          * a peer has timed out.  The peer field contains the peer
792          * which disconnected. The data field contains user supplied data
793          * describing the disconnection, or 0, if none is available.
794          */
795         ENET_EVENT_TYPE_DISCONNECT = 2,
796 
797         /** a packet has been received from a peer.  The peer field specifies the
798          * peer which sent the packet.  The channelID field specifies the channel
799          * number upon which the packet was received.  The packet field contains
800          * the packet that was received; this packet must be destroyed with
801          * enet_packet_destroy after use.
802          */
803         ENET_EVENT_TYPE_RECEIVE    = 3,
804 
805         /** a peer is disconnected because the host didn't receive the acknowledgment
806          * packet within certain maximum time out. The reason could be because of bad
807          * network connection or  host crashed.
808          */
809         ENET_EVENT_TYPE_DISCONNECT_TIMEOUT = 4,
810     } ENetEventType;
811 
812     /**
813      * An ENet event as returned by enet_host_service().
814      *
815      * @sa enet_host_service
816      */
817     typedef struct _ENetEvent {
818         ENetEventType type;      /**< type of the event */
819         ENetPeer *    peer;      /**< peer that generated a connect, disconnect or receive event */
820         enet_uint8    channelID; /**< channel on the peer that generated the event, if appropriate */
821         enet_uint32   data;      /**< data associated with the event, if appropriate */
822         ENetPacket *  packet;    /**< packet associated with the event, if appropriate */
823     } ENetEvent;
824 
825 // =======================================================================//
826 // !
827 // ! Public API
828 // !
829 // =======================================================================//
830 
831     /**
832      * Initializes ENet globally.  Must be called prior to using any functions in ENet.
833      * @returns 0 on success, < 0 on failure
834      */
835     ENET_API int enet_initialize(void);
836 
837     /**
838      * 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.
839      *
840      * @param version the constant ENET_VERSION should be supplied so ENet knows which version of ENetCallbacks struct to use
841      * @param inits user-overridden callbacks where any NULL callbacks will use ENet's defaults
842      * @returns 0 on success, < 0 on failure
843      */
844     ENET_API int enet_initialize_with_callbacks(ENetVersion version, const ENetCallbacks * inits);
845 
846     /**
847      * Shuts down ENet globally.  Should be called when a program that has initialized ENet exits.
848      */
849     ENET_API void enet_deinitialize(void);
850 
851     /**
852      * Gives the linked version of the ENet library.
853      * @returns the version number
854      */
855     ENET_API ENetVersion enet_linked_version(void);
856 
857     /** Returns the monotonic time in milliseconds. Its initial value is unspecified unless otherwise set. */
858     ENET_API enet_uint32 enet_time_get(void);
859 
860     /** ENet socket functions */
861     ENET_API ENetSocket enet_socket_create(ENetSocketType);
862     ENET_API int        enet_socket_bind(ENetSocket, ENetAddress *);
863     ENET_API int        enet_socket_get_address(ENetSocket, ENetAddress *);
864     ENET_API int        enet_socket_listen(ENetSocket, int);
865     ENET_API ENetSocket enet_socket_accept(ENetSocket, ENetAddress *);
866     ENET_API int        enet_socket_connect(ENetSocket, ENetAddress *);
867     ENET_API int        enet_socket_send(ENetSocket, ENetAddress *, ENetBuffer *, size_t);
868     ENET_API int        enet_socket_receive(ENetSocket, ENetAddress *, ENetBuffer *, size_t);
869     ENET_API int        enet_socket_wait(ENetSocket, enet_uint32 *, enet_uint64);
870     ENET_API int        enet_socket_set_option(ENetSocket, ENetSocketOption, int);
871     ENET_API int        enet_socket_get_option(ENetSocket, ENetSocketOption, int *);
872     ENET_API int        enet_socket_shutdown(ENetSocket, ENetSocketShutdown);
873     ENET_API void       enet_socket_destroy(ENetSocket);
874     ENET_API int        enet_socketset_select(ENetSocket, ENetSocketSet *, ENetSocketSet *, enet_uint32);
875 
876     /** Attempts to parse the printable form of the IP address in the parameter hostName
877         and sets the host field in the address parameter if successful.
878         @param address destination to store the parsed IP address
879         @param hostName IP address to parse
880         @retval 0 on success
881         @retval < 0 on failure
882         @returns the address of the given hostName in address on success
883     */
884     ENET_API int enet_address_set_host_ip(ENetAddress * address, char * hostName);
885 
886     /** Attempts to resolve the host named by the parameter hostName and sets
887         the host field in the address parameter if successful.
888         @param address destination to store resolved address
889         @param hostName host name to lookup
890         @retval 0 on success
891         @retval < 0 on failure
892         @returns the address of the given hostName in address on success
893     */
894     ENET_API int enet_address_set_host(ENetAddress * address, char * hostName);
895 
896     /** Gives the printable form of the IP address specified in the address parameter.
897         @param address    address printed
898         @param hostName   destination for name, must not be NULL
899         @param nameLength maximum length of hostName.
900         @returns the null-terminated name of the host in hostName on success
901         @retval 0 on success
902         @retval < 0 on failure
903     */
904     ENET_API int enet_address_get_host_ip(ENetAddress * address, char * hostName, size_t nameLength);
905 
906     /** Attempts to do a reverse lookup of the host field in the address parameter.
907         @param address    address used for reverse lookup
908         @param hostName   destination for name, must not be NULL
909         @param nameLength maximum length of hostName.
910         @returns the null-terminated name of the host in hostName on success
911         @retval 0 on success
912         @retval < 0 on failure
913     */
914     ENET_API int enet_address_get_host(ENetAddress * address, char * hostName, size_t nameLength);
915 
916     ENET_API enet_uint32 enet_host_get_peers_count(ENetHost *);
917     ENET_API enet_uint32 enet_host_get_packets_sent(ENetHost *);
918     ENET_API enet_uint32 enet_host_get_packets_received(ENetHost *);
919     ENET_API enet_uint32 enet_host_get_bytes_sent(ENetHost *);
920     ENET_API enet_uint32 enet_host_get_bytes_received(ENetHost *);
921     ENET_API enet_uint32 enet_host_get_received_data(ENetHost *, enet_uint8** data);
922     ENET_API enet_uint32 enet_host_get_mtu(ENetHost *);
923 
924     ENET_API enet_uint32 enet_peer_get_id(ENetPeer *);
925     ENET_API enet_uint32 enet_peer_get_ip(ENetPeer *, char * ip, size_t ipLength);
926     ENET_API enet_uint16 enet_peer_get_port(ENetPeer *);
927     ENET_API enet_uint32 enet_peer_get_rtt(ENetPeer *);
928     ENET_API enet_uint64 enet_peer_get_packets_sent(ENetPeer *);
929     ENET_API enet_uint32 enet_peer_get_packets_lost(ENetPeer *);
930     ENET_API enet_uint64 enet_peer_get_bytes_sent(ENetPeer *);
931     ENET_API enet_uint64 enet_peer_get_bytes_received(ENetPeer *);
932 
933     ENET_API ENetPeerState enet_peer_get_state(ENetPeer *);
934 
935     ENET_API void * enet_peer_get_data(ENetPeer *);
936     ENET_API void   enet_peer_set_data(ENetPeer *, void *);
937 
938     ENET_API void *      enet_packet_get_data(ENetPacket *);
939     ENET_API enet_uint32 enet_packet_get_length(ENetPacket *);
940     ENET_API void        enet_packet_set_free_callback(ENetPacket *, void *);
941 
942     ENET_API ENetPacket * enet_packet_create(void *, size_t, enet_uint32);
943     ENET_API ENetPacket * enet_packet_create_offset(void *, size_t, size_t, enet_uint32);
944     ENET_API void         enet_packet_destroy(ENetPacket *);
945     ENET_API enet_uint32  enet_crc32(const ENetBuffer *, size_t);
946 
947     ENET_API ENetHost * enet_host_create(ENetAddress *, size_t, size_t, enet_uint32, enet_uint32);
948     ENET_API void       enet_host_destroy(ENetHost *);
949     ENET_API ENetPeer * enet_host_connect(ENetHost *, ENetAddress *, size_t, enet_uint32);
950     ENET_API int        enet_host_check_events(ENetHost *, ENetEvent *);
951     ENET_API int        enet_host_service(ENetHost *, ENetEvent *, enet_uint32);
952     ENET_API int        enet_host_send_raw(ENetHost *, ENetAddress *, enet_uint8 *, size_t);
953     ENET_API int        enet_host_send_raw_ex(ENetHost *host, ENetAddress* address, enet_uint8* data, size_t skipBytes, size_t bytesToSend);
954     ENET_API void       enet_host_set_intercept(ENetHost *, const ENetInterceptCallback);
955     ENET_API void       enet_host_flush(ENetHost *);
956     ENET_API void       enet_host_broadcast(ENetHost *, enet_uint8, ENetPacket *);
957     ENET_API void       enet_host_compress(ENetHost *, const ENetCompressor *);
958     ENET_API void       enet_host_channel_limit(ENetHost *, size_t);
959     ENET_API void       enet_host_bandwidth_limit(ENetHost *, enet_uint32, enet_uint32);
960     extern   void       enet_host_bandwidth_throttle(ENetHost *);
961     extern  enet_uint64 enet_host_random_seed(void);
962 
963     ENET_API int                 enet_peer_send(ENetPeer *, enet_uint8, ENetPacket *);
964     ENET_API ENetPacket *        enet_peer_receive(ENetPeer *, enet_uint8 * channelID);
965     ENET_API void                enet_peer_ping(ENetPeer *);
966     ENET_API void                enet_peer_ping_interval(ENetPeer *, enet_uint32);
967     ENET_API void                enet_peer_timeout(ENetPeer *, enet_uint32, enet_uint32, enet_uint32);
968     ENET_API void                enet_peer_reset(ENetPeer *);
969     ENET_API void                enet_peer_disconnect(ENetPeer *, enet_uint32);
970     ENET_API void                enet_peer_disconnect_now(ENetPeer *, enet_uint32);
971     ENET_API void                enet_peer_disconnect_later(ENetPeer *, enet_uint32);
972     ENET_API void                enet_peer_throttle_configure(ENetPeer *, enet_uint32, enet_uint32, enet_uint32);
973     extern int                   enet_peer_throttle(ENetPeer *, enet_uint32);
974     extern void                  enet_peer_reset_queues(ENetPeer *);
975     extern void                  enet_peer_setup_outgoing_command(ENetPeer *, ENetOutgoingCommand *);
976     extern ENetOutgoingCommand * enet_peer_queue_outgoing_command(ENetPeer *, const ENetProtocol *, ENetPacket *, enet_uint32, enet_uint16);
977     extern ENetIncomingCommand * enet_peer_queue_incoming_command(ENetPeer *, const ENetProtocol *, void *, size_t, enet_uint32, enet_uint32);
978     extern ENetAcknowledgement * enet_peer_queue_acknowledgement(ENetPeer *, const ENetProtocol *, enet_uint16);
979     extern void                  enet_peer_dispatch_incoming_unreliable_commands(ENetPeer *, ENetChannel *);
980     extern void                  enet_peer_dispatch_incoming_reliable_commands(ENetPeer *, ENetChannel *);
981     extern void                  enet_peer_on_connect(ENetPeer *);
982     extern void                  enet_peer_on_disconnect(ENetPeer *);
983 
984     extern size_t enet_protocol_command_size (enet_uint8);
985 
986 #if defined _WIN32 || __APPLE__ && __MAC_OS_X_VERSION_MIN_REQUIRED < 101200
987     extern int enet_gettime(int X, struct timespec *tv);
988 #else
989 # define enet_gettime clock_gettime
990 #endif
991 
992 
993 #ifdef __cplusplus
994 }
995 #endif
996 
997 #if defined(ENET_IMPLEMENTATION) && !defined(ENET_IMPLEMENTATION_DONE)
998 #define ENET_IMPLEMENTATION_DONE 1
999 
1000 #ifdef __cplusplus
1001 extern "C" {
1002 #endif
1003 
1004 // =======================================================================//
1005 // !
1006 // ! Atomics
1007 // !
1008 // =======================================================================//
1009 
1010 #if defined(_MSC_VER)
1011 
1012     #define ENET_AT_CASSERT_PRED(predicate) sizeof(char[2 * !!(predicate)-1])
1013     #define ENET_IS_SUPPORTED_ATOMIC(size) ENET_AT_CASSERT_PRED(size == 1 || size == 2 || size == 4 || size == 8)
1014     #define ENET_ATOMIC_SIZEOF(variable) (ENET_IS_SUPPORTED_ATOMIC(sizeof(*(variable))), sizeof(*(variable)))
1015 
enet_at_atomic_read(char * ptr,size_t size)1016     __inline int64_t enet_at_atomic_read(char *ptr, size_t size)
1017     {
1018         switch (size) {
1019             case 1:
1020                 return _InterlockedExchangeAdd8((volatile char *)ptr, 0);
1021             case 2:
1022                 return _InterlockedExchangeAdd16((volatile SHORT *)ptr, 0);
1023             case 4:
1024     #ifdef NOT_UNDERSCORED_INTERLOCKED_EXCHANGE
1025                 return InterlockedExchangeAdd((volatile LONG *)ptr, 0);
1026     #else
1027                 return _InterlockedExchangeAdd((volatile LONG *)ptr, 0);
1028     #endif
1029             case 8:
1030     #ifdef NOT_UNDERSCORED_INTERLOCKED_EXCHANGE
1031                 return InterlockedExchangeAdd64((volatile LONGLONG *)ptr, 0);
1032     #else
1033                 return _InterlockedExchangeAdd64((volatile LONGLONG *)ptr, 0);
1034     #endif
1035             default:
1036                 return 0xbad13bad; /* never reached */
1037         }
1038     }
1039 
enet_at_atomic_write(char * ptr,int64_t value,size_t size)1040     __inline int64_t enet_at_atomic_write(char *ptr, int64_t value, size_t size)
1041     {
1042         switch (size) {
1043             case 1:
1044                 return _InterlockedExchange8((volatile char *)ptr, (char)value);
1045             case 2:
1046                 return _InterlockedExchange16((volatile SHORT *)ptr, (SHORT)value);
1047             case 4:
1048     #ifdef NOT_UNDERSCORED_INTERLOCKED_EXCHANGE
1049                 return InterlockedExchange((volatile LONG *)ptr, (LONG)value);
1050     #else
1051                 return _InterlockedExchange((volatile LONG *)ptr, (LONG)value);
1052     #endif
1053             case 8:
1054     #ifdef NOT_UNDERSCORED_INTERLOCKED_EXCHANGE
1055                 return InterlockedExchange64((volatile LONGLONG *)ptr, (LONGLONG)value);
1056     #else
1057                 return _InterlockedExchange64((volatile LONGLONG *)ptr, (LONGLONG)value);
1058     #endif
1059             default:
1060                 return 0xbad13bad; /* never reached */
1061         }
1062     }
1063 
enet_at_atomic_cas(char * ptr,int64_t new_val,int64_t old_val,size_t size)1064     __inline int64_t enet_at_atomic_cas(char *ptr, int64_t new_val, int64_t old_val, size_t size)
1065     {
1066         switch (size) {
1067             case 1:
1068                 return _InterlockedCompareExchange8((volatile char *)ptr, (char)new_val, (char)old_val);
1069             case 2:
1070                 return _InterlockedCompareExchange16((volatile SHORT *)ptr, (SHORT)new_val,
1071                                                      (SHORT)old_val);
1072             case 4:
1073     #ifdef NOT_UNDERSCORED_INTERLOCKED_EXCHANGE
1074                 return InterlockedCompareExchange((volatile LONG *)ptr, (LONG)new_val, (LONG)old_val);
1075     #else
1076                 return _InterlockedCompareExchange((volatile LONG *)ptr, (LONG)new_val, (LONG)old_val);
1077     #endif
1078             case 8:
1079     #ifdef NOT_UNDERSCORED_INTERLOCKED_EXCHANGE
1080                 return InterlockedCompareExchange64((volatile LONGLONG *)ptr, (LONGLONG)new_val,
1081                                                     (LONGLONG)old_val);
1082     #else
1083                 return _InterlockedCompareExchange64((volatile LONGLONG *)ptr, (LONGLONG)new_val,
1084                                                      (LONGLONG)old_val);
1085     #endif
1086             default:
1087                 return 0xbad13bad; /* never reached */
1088         }
1089     }
1090 
enet_at_atomic_inc(char * ptr,int64_t delta,size_t data_size)1091     __inline int64_t enet_at_atomic_inc(char *ptr, int64_t delta, size_t data_size)
1092     {
1093         switch (data_size) {
1094             case 1:
1095                 return _InterlockedExchangeAdd8((volatile char *)ptr, (char)delta);
1096             case 2:
1097                 return _InterlockedExchangeAdd16((volatile SHORT *)ptr, (SHORT)delta);
1098             case 4:
1099     #ifdef NOT_UNDERSCORED_INTERLOCKED_EXCHANGE
1100                 return InterlockedExchangeAdd((volatile LONG *)ptr, (LONG)delta);
1101     #else
1102                 return _InterlockedExchangeAdd((volatile LONG *)ptr, (LONG)delta);
1103     #endif
1104             case 8:
1105     #ifdef NOT_UNDERSCORED_INTERLOCKED_EXCHANGE
1106                 return InterlockedExchangeAdd64((volatile LONGLONG *)ptr, (LONGLONG)delta);
1107     #else
1108                 return _InterlockedExchangeAdd64((volatile LONGLONG *)ptr, (LONGLONG)delta);
1109     #endif
1110             default:
1111                 return 0xbad13bad; /* never reached */
1112         }
1113     }
1114 
1115     #define ENET_ATOMIC_READ(variable) enet_at_atomic_read((char *)(variable), ENET_ATOMIC_SIZEOF(variable))
1116     #define ENET_ATOMIC_WRITE(variable, new_val)                                                            \
1117         enet_at_atomic_write((char *)(variable), (int64_t)(new_val), ENET_ATOMIC_SIZEOF(variable))
1118     #define ENET_ATOMIC_CAS(variable, old_value, new_val)                                                   \
1119         enet_at_atomic_cas((char *)(variable), (int64_t)(new_val), (int64_t)(old_value),                    \
1120                       ENET_ATOMIC_SIZEOF(variable))
1121     #define ENET_ATOMIC_INC(variable) enet_at_atomic_inc((char *)(variable), 1, ENET_ATOMIC_SIZEOF(variable))
1122     #define ENET_ATOMIC_DEC(variable) enet_at_atomic_inc((char *)(variable), -1, ENET_ATOMIC_SIZEOF(variable))
1123     #define ENET_ATOMIC_INC_BY(variable, delta)                                                             \
1124         enet_at_atomic_inc((char *)(variable), (delta), ENET_ATOMIC_SIZEOF(variable))
1125     #define ENET_ATOMIC_DEC_BY(variable, delta)                                                             \
1126         enet_at_atomic_inc((char *)(variable), -(delta), ENET_ATOMIC_SIZEOF(variable))
1127 
1128 #elif defined(__GNUC__) || defined(__clang__)
1129 
1130     #if defined(__clang__) || (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7))
1131     #define AT_HAVE_ATOMICS
1132     #endif
1133 
1134     /* We want to use __atomic built-ins if possible because the __sync primitives are
1135        deprecated, because the __atomic build-ins allow us to use ENET_ATOMIC_WRITE on
1136        uninitialized memory without running into undefined behavior, and because the
1137        __atomic versions generate more efficient code since we don't need to rely on
1138        CAS when we don't actually want it.
1139 
1140        Note that we use acquire-release memory order (like mutexes do). We could use
1141        sequentially consistent memory order but that has lower performance and is
1142        almost always unneeded. */
1143     #ifdef AT_HAVE_ATOMICS
1144         #define ENET_ATOMIC_READ(ptr) __atomic_load_n((ptr), __ATOMIC_ACQUIRE)
1145         #define ENET_ATOMIC_WRITE(ptr, value) __atomic_store_n((ptr), (value), __ATOMIC_RELEASE)
1146 
1147         #ifndef typeof
1148         #define typeof __typeof__
1149         #endif
1150 
1151         /* clang_analyzer doesn't know that CAS writes to memory so it complains about
1152            potentially lost data. Replace the code with the equivalent non-sync code. */
1153         #ifdef __clang_analyzer__
1154 
1155         #define ENET_ATOMIC_CAS(ptr, old_value, new_value)                                                      \
1156             ({                                                                                             \
1157                 typeof(*(ptr)) ENET_ATOMIC_CAS_old_actual_ = (*(ptr));                                          \
1158                 if (ATOMIC_CAS_old_actual_ == (old_value)) {                                               \
1159                     *(ptr) = new_value;                                                                    \
1160                 }                                                                                          \
1161                 ENET_ATOMIC_CAS_old_actual_;                                                                    \
1162             })
1163 
1164         #else
1165 
1166         /* Could use __auto_type instead of typeof but that shouldn't work in C++.
1167            The ({ }) syntax is a GCC extension called statement expression. It lets
1168            us return a value out of the macro.
1169 
1170            TODO We should return bool here instead of the old value to avoid the ABA
1171            problem. */
1172         #define ENET_ATOMIC_CAS(ptr, old_value, new_value)                                                      \
1173             ({                                                                                             \
1174                 typeof(*(ptr)) ENET_ATOMIC_CAS_expected_ = (old_value);                                         \
1175                 __atomic_compare_exchange_n((ptr), &ENET_ATOMIC_CAS_expected_, (new_value), false,              \
1176                                             __ATOMIC_ACQ_REL, __ATOMIC_ACQUIRE);                           \
1177                 ENET_ATOMIC_CAS_expected_;                                                                      \
1178             })
1179 
1180         #endif /* __clang_analyzer__ */
1181 
1182         #define ENET_ATOMIC_INC(ptr) __atomic_fetch_add((ptr), 1, __ATOMIC_ACQ_REL)
1183         #define ENET_ATOMIC_DEC(ptr) __atomic_fetch_sub((ptr), 1, __ATOMIC_ACQ_REL)
1184         #define ENET_ATOMIC_INC_BY(ptr, delta) __atomic_fetch_add((ptr), (delta), __ATOMIC_ACQ_REL)
1185         #define ENET_ATOMIC_DEC_BY(ptr, delta) __atomic_fetch_sub((ptr), (delta), __ATOMIC_ACQ_REL)
1186 
1187         #else
1188 
1189         #define ENET_ATOMIC_READ(variable) __sync_fetch_and_add(variable, 0)
1190         #define ENET_ATOMIC_WRITE(variable, new_val)                                                            \
1191             (void) __sync_val_compare_and_swap((variable), *(variable), (new_val))
1192         #define ENET_ATOMIC_CAS(variable, old_value, new_val)                                                   \
1193             __sync_val_compare_and_swap((variable), (old_value), (new_val))
1194         #define ENET_ATOMIC_INC(variable) __sync_fetch_and_add((variable), 1)
1195         #define ENET_ATOMIC_DEC(variable) __sync_fetch_and_sub((variable), 1)
1196         #define ENET_ATOMIC_INC_BY(variable, delta) __sync_fetch_and_add((variable), (delta), 1)
1197         #define ENET_ATOMIC_DEC_BY(variable, delta) __sync_fetch_and_sub((variable), (delta), 1)
1198 
1199     #endif /* AT_HAVE_ATOMICS */
1200 
1201     #undef AT_HAVE_ATOMICS
1202 
1203 #endif /* defined(_MSC_VER) */
1204 
1205 
1206 // =======================================================================//
1207 // !
1208 // ! Callbacks
1209 // !
1210 // =======================================================================//
1211 
1212     static ENetCallbacks callbacks = { malloc, free, abort };
1213 
enet_initialize_with_callbacks(ENetVersion version,const ENetCallbacks * inits)1214     int enet_initialize_with_callbacks(ENetVersion version, const ENetCallbacks *inits) {
1215         if (version < ENET_VERSION_CREATE(1, 3, 0)) {
1216             return -1;
1217         }
1218 
1219         if (inits->malloc != NULL || inits->free != NULL) {
1220             if (inits->malloc == NULL || inits->free == NULL) {
1221                 return -1;
1222             }
1223 
1224             callbacks.malloc = inits->malloc;
1225             callbacks.free   = inits->free;
1226         }
1227 
1228         if (inits->no_memory != NULL) {
1229             callbacks.no_memory = inits->no_memory;
1230         }
1231 
1232         return enet_initialize();
1233     }
1234 
enet_linked_version(void)1235     ENetVersion enet_linked_version(void) {
1236         return ENET_VERSION;
1237     }
1238 
enet_malloc(size_t size)1239     void * enet_malloc(size_t size) {
1240         void *memory = callbacks.malloc(size);
1241 
1242         if (memory == NULL) {
1243             callbacks.no_memory();
1244         }
1245 
1246         return memory;
1247     }
1248 
enet_free(void * memory)1249     void enet_free(void *memory) {
1250         callbacks.free(memory);
1251     }
1252 
1253 // =======================================================================//
1254 // !
1255 // ! List
1256 // !
1257 // =======================================================================//
1258 
enet_list_clear(ENetList * list)1259     void enet_list_clear(ENetList *list) {
1260         list->sentinel.next     = &list->sentinel;
1261         list->sentinel.previous = &list->sentinel;
1262     }
1263 
enet_list_insert(ENetListIterator position,void * data)1264     ENetListIterator enet_list_insert(ENetListIterator position, void *data) {
1265         ENetListIterator result = (ENetListIterator)data;
1266 
1267         result->previous = position->previous;
1268         result->next     = position;
1269 
1270         result->previous->next = result;
1271         position->previous     = result;
1272 
1273         return result;
1274     }
1275 
enet_list_remove(ENetListIterator position)1276     void *enet_list_remove(ENetListIterator position) {
1277         position->previous->next = position->next;
1278         position->next->previous = position->previous;
1279 
1280         return position;
1281     }
1282 
enet_list_move(ENetListIterator position,void * dataFirst,void * dataLast)1283     ENetListIterator enet_list_move(ENetListIterator position, void *dataFirst, void *dataLast) {
1284         ENetListIterator first = (ENetListIterator)dataFirst;
1285         ENetListIterator last  = (ENetListIterator)dataLast;
1286 
1287         first->previous->next = last->next;
1288         last->next->previous  = first->previous;
1289 
1290         first->previous = position->previous;
1291         last->next      = position;
1292 
1293         first->previous->next = first;
1294         position->previous    = last;
1295 
1296         return first;
1297     }
1298 
enet_list_size(ENetList * list)1299     size_t enet_list_size(ENetList *list) {
1300         size_t size = 0;
1301         ENetListIterator position;
1302 
1303         for (position = enet_list_begin(list); position != enet_list_end(list); position = enet_list_next(position)) {
1304             ++size;
1305         }
1306 
1307         return size;
1308     }
1309 
1310 // =======================================================================//
1311 // !
1312 // ! Packet
1313 // !
1314 // =======================================================================//
1315 
1316     /**
1317      * Creates a packet that may be sent to a peer.
1318      * @param data         initial contents of the packet's data; the packet's data will remain uninitialized if data is NULL.
1319      * @param dataLength   size of the data allocated for this packet
1320      * @param flags        flags for this packet as described for the ENetPacket structure.
1321      * @returns the packet on success, NULL on failure
1322      */
enet_packet_create(void * data,size_t dataLength,enet_uint32 flags)1323     ENetPacket *enet_packet_create(void *data, size_t dataLength, enet_uint32 flags) {
1324         ENetPacket *packet;
1325         if (flags & ENET_PACKET_FLAG_NO_ALLOCATE) {
1326             packet = (ENetPacket *)enet_malloc(sizeof (ENetPacket));
1327             if (packet == NULL) {
1328                 return NULL;
1329             }
1330 
1331             packet->data = (enet_uint8 *)data;
1332         }
1333         else {
1334             packet = (ENetPacket *)enet_malloc(sizeof (ENetPacket) + dataLength);
1335             if (packet == NULL) {
1336                 return NULL;
1337             }
1338 
1339             packet->data = (enet_uint8 *)packet + sizeof(ENetPacket);
1340 
1341             if (data != NULL) {
1342                 memcpy(packet->data, data, dataLength);
1343             }
1344         }
1345 
1346         packet->referenceCount = 0;
1347         packet->flags        = flags;
1348         packet->dataLength   = dataLength;
1349         packet->freeCallback = NULL;
1350         packet->userData     = NULL;
1351 
1352         return packet;
1353     }
1354 
enet_packet_create_offset(void * data,size_t dataLength,size_t dataOffset,enet_uint32 flags)1355     ENetPacket *enet_packet_create_offset(void *data, size_t dataLength, size_t dataOffset, enet_uint32 flags) {
1356         ENetPacket *packet;
1357         if (flags & ENET_PACKET_FLAG_NO_ALLOCATE) {
1358             packet = (ENetPacket *)enet_malloc(sizeof (ENetPacket));
1359             if (packet == NULL) {
1360                 return NULL;
1361             }
1362 
1363             packet->data = (enet_uint8 *)data;
1364         }
1365         else {
1366             packet = (ENetPacket *)enet_malloc(sizeof (ENetPacket) + dataLength + dataOffset);
1367             if (packet == NULL) {
1368                 return NULL;
1369             }
1370 
1371             packet->data = (enet_uint8 *)packet + sizeof(ENetPacket);
1372 
1373             if (data != NULL) {
1374                 memcpy(packet->data + dataOffset, data, dataLength);
1375             }
1376         }
1377 
1378         packet->referenceCount = 0;
1379         packet->flags        = flags;
1380         packet->dataLength   = dataLength + dataOffset;
1381         packet->freeCallback = NULL;
1382         packet->userData     = NULL;
1383 
1384         return packet;
1385     }
1386 
1387     /**
1388      * Destroys the packet and deallocates its data.
1389      * @param packet packet to be destroyed
1390      */
enet_packet_destroy(ENetPacket * packet)1391     void enet_packet_destroy(ENetPacket *packet) {
1392         if (packet == NULL) {
1393             return;
1394         }
1395 
1396         if (packet->freeCallback != NULL) {
1397             (*packet->freeCallback)((void *)packet);
1398         }
1399 
1400         enet_free(packet);
1401     }
1402 
1403     static int initializedCRC32 = 0;
1404     static enet_uint32 crcTable[256];
1405 
reflect_crc(int val,int bits)1406     static enet_uint32 reflect_crc(int val, int bits) {
1407         int result = 0, bit;
1408 
1409         for (bit = 0; bit < bits; bit++) {
1410             if (val & 1) { result |= 1 << (bits - 1 - bit); }
1411             val >>= 1;
1412         }
1413 
1414         return result;
1415     }
1416 
initialize_crc32(void)1417     static void initialize_crc32(void) {
1418         int byte;
1419 
1420         for (byte = 0; byte < 256; ++byte) {
1421             enet_uint32 crc = reflect_crc(byte, 8) << 24;
1422             int offset;
1423 
1424             for (offset = 0; offset < 8; ++offset) {
1425                 if (crc & 0x80000000) {
1426                     crc = (crc << 1) ^ 0x04c11db7;
1427                 } else {
1428                     crc <<= 1;
1429                 }
1430             }
1431 
1432             crcTable[byte] = reflect_crc(crc, 32);
1433         }
1434 
1435         initializedCRC32 = 1;
1436     }
1437 
enet_crc32(const ENetBuffer * buffers,size_t bufferCount)1438     enet_uint32 enet_crc32(const ENetBuffer *buffers, size_t bufferCount) {
1439         enet_uint32 crc = 0xFFFFFFFF;
1440 
1441         if (!initializedCRC32) { initialize_crc32(); }
1442 
1443         while (bufferCount-- > 0) {
1444             const enet_uint8 *data = (const enet_uint8 *)buffers->data;
1445             const enet_uint8 *dataEnd = &data[buffers->dataLength];
1446 
1447             while (data < dataEnd) {
1448                 crc = (crc >> 8) ^ crcTable[(crc & 0xFF) ^ *data++];
1449             }
1450 
1451             ++buffers;
1452         }
1453 
1454         return ENET_HOST_TO_NET_32(~crc);
1455     }
1456 
1457 // =======================================================================//
1458 // !
1459 // ! Protocol
1460 // !
1461 // =======================================================================//
1462 
1463     static size_t commandSizes[ENET_PROTOCOL_COMMAND_COUNT] = {
1464         0,
1465         sizeof(ENetProtocolAcknowledge),
1466         sizeof(ENetProtocolConnect),
1467         sizeof(ENetProtocolVerifyConnect),
1468         sizeof(ENetProtocolDisconnect),
1469         sizeof(ENetProtocolPing),
1470         sizeof(ENetProtocolSendReliable),
1471         sizeof(ENetProtocolSendUnreliable),
1472         sizeof(ENetProtocolSendFragment),
1473         sizeof(ENetProtocolSendUnsequenced),
1474         sizeof(ENetProtocolBandwidthLimit),
1475         sizeof(ENetProtocolThrottleConfigure),
1476         sizeof(ENetProtocolSendFragment)
1477     };
1478 
enet_protocol_command_size(enet_uint8 commandNumber)1479     size_t enet_protocol_command_size(enet_uint8 commandNumber) {
1480         return commandSizes[commandNumber & ENET_PROTOCOL_COMMAND_MASK];
1481     }
1482 
enet_protocol_change_state(ENetHost * host,ENetPeer * peer,ENetPeerState state)1483     static void enet_protocol_change_state(ENetHost *host, ENetPeer *peer, ENetPeerState state) {
1484         UNREFERENCED_PARAMETER(host);
1485         if (state == ENET_PEER_STATE_CONNECTED || state == ENET_PEER_STATE_DISCONNECT_LATER) {
1486             enet_peer_on_connect(peer);
1487         } else {
1488             enet_peer_on_disconnect(peer);
1489         }
1490 
1491         peer->state = state;
1492     }
1493 
enet_protocol_dispatch_state(ENetHost * host,ENetPeer * peer,ENetPeerState state)1494     static void enet_protocol_dispatch_state(ENetHost *host, ENetPeer *peer, ENetPeerState state) {
1495         enet_protocol_change_state(host, peer, state);
1496 
1497         if (!peer->needsDispatch) {
1498             enet_list_insert(enet_list_end(&host->dispatchQueue), &peer->dispatchList);
1499             peer->needsDispatch = 1;
1500         }
1501     }
1502 
enet_protocol_dispatch_incoming_commands(ENetHost * host,ENetEvent * event)1503     static int enet_protocol_dispatch_incoming_commands(ENetHost *host, ENetEvent *event) {
1504         while (!enet_list_empty(&host->dispatchQueue)) {
1505             ENetPeer *peer = (ENetPeer *) enet_list_remove(enet_list_begin(&host->dispatchQueue));
1506             peer->needsDispatch = 0;
1507 
1508             switch (peer->state) {
1509                 case ENET_PEER_STATE_CONNECTION_PENDING:
1510                 case ENET_PEER_STATE_CONNECTION_SUCCEEDED:
1511                     enet_protocol_change_state(host, peer, ENET_PEER_STATE_CONNECTED);
1512 
1513                     event->type = ENET_EVENT_TYPE_CONNECT;
1514                     event->peer = peer;
1515                     event->data = peer->eventData;
1516 
1517                     return 1;
1518 
1519                 case ENET_PEER_STATE_ZOMBIE:
1520                     host->recalculateBandwidthLimits = 1;
1521 
1522                     event->type = ENET_EVENT_TYPE_DISCONNECT;
1523                     event->peer = peer;
1524                     event->data = peer->eventData;
1525 
1526                     enet_peer_reset(peer);
1527 
1528                     return 1;
1529 
1530                 case ENET_PEER_STATE_CONNECTED:
1531                     if (enet_list_empty(&peer->dispatchedCommands)) {
1532                         continue;
1533                     }
1534 
1535                     event->packet = enet_peer_receive(peer, &event->channelID);
1536                     if (event->packet == NULL) {
1537                         continue;
1538                     }
1539 
1540                     event->type = ENET_EVENT_TYPE_RECEIVE;
1541                     event->peer = peer;
1542 
1543                     if (!enet_list_empty(&peer->dispatchedCommands)) {
1544                         peer->needsDispatch = 1;
1545                         enet_list_insert(enet_list_end(&host->dispatchQueue), &peer->dispatchList);
1546                     }
1547 
1548                     return 1;
1549 
1550                 default:
1551                     break;
1552             }
1553         }
1554 
1555         return 0;
1556     } /* enet_protocol_dispatch_incoming_commands */
1557 
enet_protocol_notify_connect(ENetHost * host,ENetPeer * peer,ENetEvent * event)1558     static void enet_protocol_notify_connect(ENetHost *host, ENetPeer *peer, ENetEvent *event) {
1559         host->recalculateBandwidthLimits = 1;
1560 
1561         if (event != NULL) {
1562             enet_protocol_change_state(host, peer, ENET_PEER_STATE_CONNECTED);
1563 
1564             peer->totalDataSent     = 0;
1565             peer->totalDataReceived = 0;
1566             peer->totalPacketsSent  = 0;
1567             peer->totalPacketsLost  = 0;
1568 
1569             event->type = ENET_EVENT_TYPE_CONNECT;
1570             event->peer = peer;
1571             event->data = peer->eventData;
1572         } else {
1573             enet_protocol_dispatch_state(host, peer, peer->state == ENET_PEER_STATE_CONNECTING ? ENET_PEER_STATE_CONNECTION_SUCCEEDED : ENET_PEER_STATE_CONNECTION_PENDING);
1574         }
1575     }
1576 
enet_protocol_notify_disconnect(ENetHost * host,ENetPeer * peer,ENetEvent * event)1577     static void enet_protocol_notify_disconnect(ENetHost *host, ENetPeer *peer, ENetEvent *event) {
1578         if (peer->state >= ENET_PEER_STATE_CONNECTION_PENDING) {
1579             host->recalculateBandwidthLimits = 1;
1580         }
1581 
1582         if (peer->state != ENET_PEER_STATE_CONNECTING && peer->state < ENET_PEER_STATE_CONNECTION_SUCCEEDED) {
1583             enet_peer_reset(peer);
1584         } else if (event != NULL) {
1585             event->type = ENET_EVENT_TYPE_DISCONNECT;
1586             event->peer = peer;
1587             event->data = 0;
1588 
1589             enet_peer_reset(peer);
1590         } else {
1591             peer->eventData = 0;
1592             enet_protocol_dispatch_state(host, peer, ENET_PEER_STATE_ZOMBIE);
1593         }
1594     }
1595 
enet_protocol_notify_disconnect_timeout(ENetHost * host,ENetPeer * peer,ENetEvent * event)1596     static void enet_protocol_notify_disconnect_timeout (ENetHost * host, ENetPeer * peer, ENetEvent * event) {
1597         if (peer->state >= ENET_PEER_STATE_CONNECTION_PENDING) {
1598            host->recalculateBandwidthLimits = 1;
1599         }
1600 
1601         if (peer->state != ENET_PEER_STATE_CONNECTING && peer->state < ENET_PEER_STATE_CONNECTION_SUCCEEDED) {
1602             enet_peer_reset (peer);
1603         }
1604         else if (event != NULL) {
1605             event->type = ENET_EVENT_TYPE_DISCONNECT_TIMEOUT;
1606             event->peer = peer;
1607             event->data = 0;
1608 
1609             enet_peer_reset(peer);
1610         }
1611         else {
1612             peer->eventData = 0;
1613             enet_protocol_dispatch_state(host, peer, ENET_PEER_STATE_ZOMBIE);
1614         }
1615     }
1616 
enet_protocol_remove_sent_unreliable_commands(ENetPeer * peer)1617     static void enet_protocol_remove_sent_unreliable_commands(ENetPeer *peer) {
1618         ENetOutgoingCommand *outgoingCommand;
1619 
1620         while (!enet_list_empty(&peer->sentUnreliableCommands)) {
1621             outgoingCommand = (ENetOutgoingCommand *) enet_list_front(&peer->sentUnreliableCommands);
1622             enet_list_remove(&outgoingCommand->outgoingCommandList);
1623 
1624             if (outgoingCommand->packet != NULL) {
1625                 --outgoingCommand->packet->referenceCount;
1626 
1627                 if (outgoingCommand->packet->referenceCount == 0) {
1628                     outgoingCommand->packet->flags |= ENET_PACKET_FLAG_SENT;
1629                     enet_packet_destroy(outgoingCommand->packet);
1630                 }
1631             }
1632 
1633             enet_free(outgoingCommand);
1634         }
1635     }
1636 
enet_protocol_remove_sent_reliable_command(ENetPeer * peer,enet_uint16 reliableSequenceNumber,enet_uint8 channelID)1637     static ENetProtocolCommand enet_protocol_remove_sent_reliable_command(ENetPeer *peer, enet_uint16 reliableSequenceNumber, enet_uint8 channelID) {
1638         ENetOutgoingCommand *outgoingCommand = NULL;
1639         ENetListIterator currentCommand;
1640         ENetProtocolCommand commandNumber;
1641         int wasSent = 1;
1642 
1643         for (currentCommand = enet_list_begin(&peer->sentReliableCommands);
1644             currentCommand != enet_list_end(&peer->sentReliableCommands);
1645             currentCommand = enet_list_next(currentCommand)
1646         ) {
1647             outgoingCommand = (ENetOutgoingCommand *) currentCommand;
1648 
1649             if (outgoingCommand->reliableSequenceNumber == reliableSequenceNumber && outgoingCommand->command.header.channelID == channelID) {
1650                 break;
1651             }
1652         }
1653 
1654         if (currentCommand == enet_list_end(&peer->sentReliableCommands)) {
1655             for (currentCommand = enet_list_begin(&peer->outgoingReliableCommands);
1656                 currentCommand != enet_list_end(&peer->outgoingReliableCommands);
1657                 currentCommand = enet_list_next(currentCommand)
1658             ) {
1659                 outgoingCommand = (ENetOutgoingCommand *) currentCommand;
1660 
1661                 if (outgoingCommand->sendAttempts < 1) { return ENET_PROTOCOL_COMMAND_NONE; }
1662                 if (outgoingCommand->reliableSequenceNumber == reliableSequenceNumber && outgoingCommand->command.header.channelID == channelID) {
1663                     break;
1664                 }
1665             }
1666 
1667             if (currentCommand == enet_list_end(&peer->outgoingReliableCommands)) {
1668                 return ENET_PROTOCOL_COMMAND_NONE;
1669             }
1670 
1671             wasSent = 0;
1672         }
1673 
1674         if (outgoingCommand == NULL) {
1675             return ENET_PROTOCOL_COMMAND_NONE;
1676         }
1677 
1678         if (channelID < peer->channelCount) {
1679             ENetChannel *channel       = &peer->channels[channelID];
1680             enet_uint16 reliableWindow = reliableSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE;
1681             if (channel->reliableWindows[reliableWindow] > 0) {
1682                 --channel->reliableWindows[reliableWindow];
1683                 if (!channel->reliableWindows[reliableWindow]) {
1684                     channel->usedReliableWindows &= ~(1 << reliableWindow);
1685                 }
1686             }
1687         }
1688 
1689         commandNumber = (ENetProtocolCommand) (outgoingCommand->command.header.command & ENET_PROTOCOL_COMMAND_MASK);
1690         enet_list_remove(&outgoingCommand->outgoingCommandList);
1691 
1692         if (outgoingCommand->packet != NULL) {
1693             if (wasSent) {
1694                 peer->reliableDataInTransit -= outgoingCommand->fragmentLength;
1695             }
1696 
1697             --outgoingCommand->packet->referenceCount;
1698 
1699             if (outgoingCommand->packet->referenceCount == 0) {
1700                 outgoingCommand->packet->flags |= ENET_PACKET_FLAG_SENT;
1701                 enet_packet_destroy(outgoingCommand->packet);
1702             }
1703         }
1704 
1705         enet_free(outgoingCommand);
1706 
1707         if (enet_list_empty(&peer->sentReliableCommands)) {
1708             return commandNumber;
1709         }
1710 
1711         outgoingCommand = (ENetOutgoingCommand *) enet_list_front(&peer->sentReliableCommands);
1712         peer->nextTimeout = outgoingCommand->sentTime + outgoingCommand->roundTripTimeout;
1713 
1714         return commandNumber;
1715     } /* enet_protocol_remove_sent_reliable_command */
1716 
enet_protocol_handle_connect(ENetHost * host,ENetProtocolHeader * header,ENetProtocol * command)1717     static ENetPeer * enet_protocol_handle_connect(ENetHost *host, ENetProtocolHeader *header, ENetProtocol *command) {
1718         UNREFERENCED_PARAMETER(header);
1719         enet_uint8 incomingSessionID, outgoingSessionID;
1720         enet_uint32 mtu, windowSize;
1721         ENetChannel *channel;
1722         size_t channelCount, duplicatePeers = 0;
1723         ENetPeer *currentPeer, *peer = NULL;
1724         ENetProtocol verifyCommand;
1725 
1726         channelCount = ENET_NET_TO_HOST_32(command->connect.channelCount);
1727 
1728         if (channelCount < ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT || channelCount > ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT) {
1729             return NULL;
1730         }
1731 
1732         for (currentPeer = host->peers; currentPeer < &host->peers[host->peerCount]; ++currentPeer) {
1733             if (currentPeer->state == ENET_PEER_STATE_DISCONNECTED) {
1734                 if (peer == NULL) {
1735                     peer = currentPeer;
1736                 }
1737             } else if (currentPeer->state != ENET_PEER_STATE_CONNECTING && in6_equal(currentPeer->address.host, host->receivedAddress.host)) {
1738                 if (currentPeer->address.port == host->receivedAddress.port && currentPeer->connectID == command->connect.connectID) {
1739                     return NULL;
1740                 }
1741 
1742                 ++duplicatePeers;
1743             }
1744         }
1745 
1746         if (peer == NULL || duplicatePeers >= host->duplicatePeers) {
1747             return NULL;
1748         }
1749 
1750         if (channelCount > host->channelLimit) {
1751             channelCount = host->channelLimit;
1752         }
1753         peer->channels = (ENetChannel *) enet_malloc(channelCount * sizeof(ENetChannel));
1754         if (peer->channels == NULL) {
1755             return NULL;
1756         }
1757         peer->channelCount               = channelCount;
1758         peer->state                      = ENET_PEER_STATE_ACKNOWLEDGING_CONNECT;
1759         peer->connectID                  = command->connect.connectID;
1760         peer->address                    = host->receivedAddress;
1761         peer->outgoingPeerID             = ENET_NET_TO_HOST_16(command->connect.outgoingPeerID);
1762         peer->incomingBandwidth          = ENET_NET_TO_HOST_32(command->connect.incomingBandwidth);
1763         peer->outgoingBandwidth          = ENET_NET_TO_HOST_32(command->connect.outgoingBandwidth);
1764         peer->packetThrottleInterval     = ENET_NET_TO_HOST_32(command->connect.packetThrottleInterval);
1765         peer->packetThrottleAcceleration = ENET_NET_TO_HOST_32(command->connect.packetThrottleAcceleration);
1766         peer->packetThrottleDeceleration = ENET_NET_TO_HOST_32(command->connect.packetThrottleDeceleration);
1767         peer->eventData                  = ENET_NET_TO_HOST_32(command->connect.data);
1768 
1769         incomingSessionID = command->connect.incomingSessionID == 0xFF ? peer->outgoingSessionID : command->connect.incomingSessionID;
1770         incomingSessionID = (incomingSessionID + 1) & (ENET_PROTOCOL_HEADER_SESSION_MASK >> ENET_PROTOCOL_HEADER_SESSION_SHIFT);
1771         if (incomingSessionID == peer->outgoingSessionID) {
1772             incomingSessionID = (incomingSessionID + 1)
1773               & (ENET_PROTOCOL_HEADER_SESSION_MASK >> ENET_PROTOCOL_HEADER_SESSION_SHIFT);
1774         }
1775         peer->outgoingSessionID = incomingSessionID;
1776 
1777         outgoingSessionID = command->connect.outgoingSessionID == 0xFF ? peer->incomingSessionID : command->connect.outgoingSessionID;
1778         outgoingSessionID = (outgoingSessionID + 1) & (ENET_PROTOCOL_HEADER_SESSION_MASK >> ENET_PROTOCOL_HEADER_SESSION_SHIFT);
1779         if (outgoingSessionID == peer->incomingSessionID) {
1780             outgoingSessionID = (outgoingSessionID + 1)
1781               & (ENET_PROTOCOL_HEADER_SESSION_MASK >> ENET_PROTOCOL_HEADER_SESSION_SHIFT);
1782         }
1783         peer->incomingSessionID = outgoingSessionID;
1784 
1785         for (channel = peer->channels; channel < &peer->channels[channelCount]; ++channel) {
1786             channel->outgoingReliableSequenceNumber   = 0;
1787             channel->outgoingUnreliableSequenceNumber = 0;
1788             channel->incomingReliableSequenceNumber   = 0;
1789             channel->incomingUnreliableSequenceNumber = 0;
1790 
1791             enet_list_clear(&channel->incomingReliableCommands);
1792             enet_list_clear(&channel->incomingUnreliableCommands);
1793 
1794             channel->usedReliableWindows = 0;
1795             memset(channel->reliableWindows, 0, sizeof(channel->reliableWindows));
1796         }
1797 
1798         mtu = ENET_NET_TO_HOST_32(command->connect.mtu);
1799 
1800         if (mtu < ENET_PROTOCOL_MINIMUM_MTU) {
1801             mtu = ENET_PROTOCOL_MINIMUM_MTU;
1802         } else if (mtu > ENET_PROTOCOL_MAXIMUM_MTU) {
1803             mtu = ENET_PROTOCOL_MAXIMUM_MTU;
1804         }
1805 
1806         peer->mtu = mtu;
1807 
1808         if (host->outgoingBandwidth == 0 && peer->incomingBandwidth == 0) {
1809             peer->windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE;
1810         } else if (host->outgoingBandwidth == 0 || peer->incomingBandwidth == 0) {
1811             peer->windowSize = (ENET_MAX(host->outgoingBandwidth, peer->incomingBandwidth) / ENET_PEER_WINDOW_SIZE_SCALE) * ENET_PROTOCOL_MINIMUM_WINDOW_SIZE;
1812         } else {
1813             peer->windowSize = (ENET_MIN(host->outgoingBandwidth, peer->incomingBandwidth) / ENET_PEER_WINDOW_SIZE_SCALE) * ENET_PROTOCOL_MINIMUM_WINDOW_SIZE;
1814         }
1815 
1816         if (peer->windowSize < ENET_PROTOCOL_MINIMUM_WINDOW_SIZE) {
1817             peer->windowSize = ENET_PROTOCOL_MINIMUM_WINDOW_SIZE;
1818         } else if (peer->windowSize > ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE) {
1819             peer->windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE;
1820         }
1821 
1822         if (host->incomingBandwidth == 0) {
1823             windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE;
1824         } else {
1825             windowSize = (host->incomingBandwidth / ENET_PEER_WINDOW_SIZE_SCALE) * ENET_PROTOCOL_MINIMUM_WINDOW_SIZE;
1826         }
1827 
1828         if (windowSize > ENET_NET_TO_HOST_32(command->connect.windowSize)) {
1829             windowSize = ENET_NET_TO_HOST_32(command->connect.windowSize);
1830         }
1831 
1832         if (windowSize < ENET_PROTOCOL_MINIMUM_WINDOW_SIZE) {
1833             windowSize = ENET_PROTOCOL_MINIMUM_WINDOW_SIZE;
1834         } else if (windowSize > ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE) {
1835             windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE;
1836         }
1837 
1838         verifyCommand.header.command                            = ENET_PROTOCOL_COMMAND_VERIFY_CONNECT | ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE;
1839         verifyCommand.header.channelID                          = 0xFF;
1840         verifyCommand.verifyConnect.outgoingPeerID              = ENET_HOST_TO_NET_16(peer->incomingPeerID);
1841         verifyCommand.verifyConnect.incomingSessionID           = incomingSessionID;
1842         verifyCommand.verifyConnect.outgoingSessionID           = outgoingSessionID;
1843         verifyCommand.verifyConnect.mtu                         = ENET_HOST_TO_NET_32(peer->mtu);
1844         verifyCommand.verifyConnect.windowSize                  = ENET_HOST_TO_NET_32(windowSize);
1845         verifyCommand.verifyConnect.channelCount                = ENET_HOST_TO_NET_32(channelCount);
1846         verifyCommand.verifyConnect.incomingBandwidth           = ENET_HOST_TO_NET_32(host->incomingBandwidth);
1847         verifyCommand.verifyConnect.outgoingBandwidth           = ENET_HOST_TO_NET_32(host->outgoingBandwidth);
1848         verifyCommand.verifyConnect.packetThrottleInterval      = ENET_HOST_TO_NET_32(peer->packetThrottleInterval);
1849         verifyCommand.verifyConnect.packetThrottleAcceleration  = ENET_HOST_TO_NET_32(peer->packetThrottleAcceleration);
1850         verifyCommand.verifyConnect.packetThrottleDeceleration  = ENET_HOST_TO_NET_32(peer->packetThrottleDeceleration);
1851         verifyCommand.verifyConnect.connectID                   = peer->connectID;
1852 
1853         enet_peer_queue_outgoing_command(peer, &verifyCommand, NULL, 0, 0);
1854         return peer;
1855     } /* enet_protocol_handle_connect */
1856 
enet_protocol_handle_send_reliable(ENetHost * host,ENetPeer * peer,ENetProtocol * command,enet_uint8 ** currentData)1857     static int enet_protocol_handle_send_reliable(ENetHost *host, ENetPeer *peer, ENetProtocol *command, enet_uint8 **currentData) {
1858         size_t dataLength;
1859 
1860         if (command->header.channelID >= peer->channelCount || (peer->state != ENET_PEER_STATE_CONNECTED && peer->state != ENET_PEER_STATE_DISCONNECT_LATER)) {
1861             return -1;
1862         }
1863 
1864         dataLength    = ENET_NET_TO_HOST_16(command->sendReliable.dataLength);
1865         *currentData += dataLength;
1866 
1867         if (dataLength > host->maximumPacketSize || *currentData < host->receivedData || *currentData > &host->receivedData[host->receivedDataLength]) {
1868             return -1;
1869         }
1870 
1871         if (enet_peer_queue_incoming_command(peer, command, (enet_uint8 *) command + sizeof(ENetProtocolSendReliable), dataLength, ENET_PACKET_FLAG_RELIABLE, 0) == NULL) {
1872             return -1;
1873         }
1874 
1875         return 0;
1876     }
1877 
enet_protocol_handle_send_unsequenced(ENetHost * host,ENetPeer * peer,ENetProtocol * command,enet_uint8 ** currentData)1878     static int enet_protocol_handle_send_unsequenced(ENetHost *host, ENetPeer *peer, ENetProtocol *command, enet_uint8 **currentData) {
1879         enet_uint32 unsequencedGroup, index;
1880         size_t dataLength;
1881 
1882         if (command->header.channelID >= peer->channelCount || (peer->state != ENET_PEER_STATE_CONNECTED && peer->state != ENET_PEER_STATE_DISCONNECT_LATER)) {
1883             return -1;
1884         }
1885 
1886         dataLength    = ENET_NET_TO_HOST_16(command->sendUnsequenced.dataLength);
1887         *currentData += dataLength;
1888         if (dataLength > host->maximumPacketSize || *currentData < host->receivedData || *currentData > &host->receivedData[host->receivedDataLength]) {
1889             return -1;
1890         }
1891 
1892         unsequencedGroup = ENET_NET_TO_HOST_16(command->sendUnsequenced.unsequencedGroup);
1893         index = unsequencedGroup % ENET_PEER_UNSEQUENCED_WINDOW_SIZE;
1894 
1895         if (unsequencedGroup < peer->incomingUnsequencedGroup) {
1896             unsequencedGroup += 0x10000;
1897         }
1898 
1899         if (unsequencedGroup >= (enet_uint32) peer->incomingUnsequencedGroup + ENET_PEER_FREE_UNSEQUENCED_WINDOWS * ENET_PEER_UNSEQUENCED_WINDOW_SIZE) {
1900             return 0;
1901         }
1902 
1903         unsequencedGroup &= 0xFFFF;
1904 
1905         if (unsequencedGroup - index != peer->incomingUnsequencedGroup) {
1906             peer->incomingUnsequencedGroup = unsequencedGroup - index;
1907             memset(peer->unsequencedWindow, 0, sizeof(peer->unsequencedWindow));
1908         } else if (peer->unsequencedWindow[index / 32] & (1 << (index % 32))) {
1909             return 0;
1910         }
1911 
1912         if (enet_peer_queue_incoming_command(peer, command, (enet_uint8 *) command + sizeof(ENetProtocolSendUnsequenced), dataLength, ENET_PACKET_FLAG_UNSEQUENCED,0) == NULL) {
1913             return -1;
1914         }
1915 
1916         peer->unsequencedWindow[index / 32] |= 1 << (index % 32);
1917 
1918         return 0;
1919     } /* enet_protocol_handle_send_unsequenced */
1920 
enet_protocol_handle_send_unreliable(ENetHost * host,ENetPeer * peer,ENetProtocol * command,enet_uint8 ** currentData)1921     static int enet_protocol_handle_send_unreliable(ENetHost *host, ENetPeer *peer, ENetProtocol *command,
1922       enet_uint8 **currentData) {
1923         size_t dataLength;
1924 
1925         if (command->header.channelID >= peer->channelCount ||
1926           (peer->state != ENET_PEER_STATE_CONNECTED && peer->state != ENET_PEER_STATE_DISCONNECT_LATER))
1927         {
1928             return -1;
1929         }
1930 
1931         dataLength    = ENET_NET_TO_HOST_16(command->sendUnreliable.dataLength);
1932         *currentData += dataLength;
1933         if (dataLength > host->maximumPacketSize || *currentData < host->receivedData || *currentData > &host->receivedData[host->receivedDataLength]) {
1934             return -1;
1935         }
1936 
1937         if (enet_peer_queue_incoming_command(peer, command, (enet_uint8 *) command + sizeof(ENetProtocolSendUnreliable), dataLength, 0, 0) == NULL) {
1938             return -1;
1939         }
1940 
1941         return 0;
1942     }
1943 
enet_protocol_handle_send_fragment(ENetHost * host,ENetPeer * peer,ENetProtocol * command,enet_uint8 ** currentData)1944     static int enet_protocol_handle_send_fragment(ENetHost *host, ENetPeer *peer, ENetProtocol *command, enet_uint8 **currentData) {
1945         enet_uint32 fragmentNumber, fragmentCount, fragmentOffset, fragmentLength, startSequenceNumber, totalLength;
1946         ENetChannel *channel;
1947         enet_uint16 startWindow, currentWindow;
1948         ENetListIterator currentCommand;
1949         ENetIncomingCommand *startCommand = NULL;
1950 
1951         if (command->header.channelID >= peer->channelCount || (peer->state != ENET_PEER_STATE_CONNECTED && peer->state != ENET_PEER_STATE_DISCONNECT_LATER)) {
1952             return -1;
1953         }
1954 
1955         fragmentLength = ENET_NET_TO_HOST_16(command->sendFragment.dataLength);
1956         *currentData  += fragmentLength;
1957         if (fragmentLength > host->maximumPacketSize || *currentData < host->receivedData || *currentData > &host->receivedData[host->receivedDataLength]) {
1958             return -1;
1959         }
1960 
1961         channel = &peer->channels[command->header.channelID];
1962         startSequenceNumber = ENET_NET_TO_HOST_16(command->sendFragment.startSequenceNumber);
1963         startWindow         = startSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE;
1964         currentWindow       = channel->incomingReliableSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE;
1965 
1966         if (startSequenceNumber < channel->incomingReliableSequenceNumber) {
1967             startWindow += ENET_PEER_RELIABLE_WINDOWS;
1968         }
1969 
1970         if (startWindow < currentWindow || startWindow >= currentWindow + ENET_PEER_FREE_RELIABLE_WINDOWS - 1) {
1971             return 0;
1972         }
1973 
1974         fragmentNumber = ENET_NET_TO_HOST_32(command->sendFragment.fragmentNumber);
1975         fragmentCount  = ENET_NET_TO_HOST_32(command->sendFragment.fragmentCount);
1976         fragmentOffset = ENET_NET_TO_HOST_32(command->sendFragment.fragmentOffset);
1977         totalLength    = ENET_NET_TO_HOST_32(command->sendFragment.totalLength);
1978 
1979         if (fragmentCount > ENET_PROTOCOL_MAXIMUM_FRAGMENT_COUNT ||
1980             fragmentNumber >= fragmentCount ||
1981             totalLength > host->maximumPacketSize ||
1982             fragmentOffset >= totalLength ||
1983             fragmentLength > totalLength - fragmentOffset
1984         ) {
1985             return -1;
1986         }
1987 
1988         for (currentCommand = enet_list_previous(enet_list_end(&channel->incomingReliableCommands));
1989             currentCommand != enet_list_end(&channel->incomingReliableCommands);
1990             currentCommand = enet_list_previous(currentCommand)
1991         ) {
1992             ENetIncomingCommand *incomingCommand = (ENetIncomingCommand *) currentCommand;
1993 
1994             if (startSequenceNumber >= channel->incomingReliableSequenceNumber) {
1995                 if (incomingCommand->reliableSequenceNumber < channel->incomingReliableSequenceNumber) {
1996                     continue;
1997                 }
1998             } else if (incomingCommand->reliableSequenceNumber >= channel->incomingReliableSequenceNumber) {
1999                 break;
2000             }
2001 
2002             if (incomingCommand->reliableSequenceNumber <= startSequenceNumber) {
2003                 if (incomingCommand->reliableSequenceNumber < startSequenceNumber) {
2004                     break;
2005                 }
2006 
2007                 if ((incomingCommand->command.header.command & ENET_PROTOCOL_COMMAND_MASK) !=
2008                     ENET_PROTOCOL_COMMAND_SEND_FRAGMENT ||
2009                     totalLength != incomingCommand->packet->dataLength ||
2010                     fragmentCount != incomingCommand->fragmentCount
2011                 ) {
2012                     return -1;
2013                 }
2014 
2015                 startCommand = incomingCommand;
2016                 break;
2017             }
2018         }
2019 
2020         if (startCommand == NULL) {
2021             ENetProtocol hostCommand = *command;
2022             hostCommand.header.reliableSequenceNumber = startSequenceNumber;
2023             startCommand = enet_peer_queue_incoming_command(peer, &hostCommand, NULL, totalLength, ENET_PACKET_FLAG_RELIABLE, fragmentCount);
2024             if (startCommand == NULL) {
2025                 return -1;
2026             }
2027         }
2028 
2029         if ((startCommand->fragments[fragmentNumber / 32] & (1 << (fragmentNumber % 32))) == 0) {
2030             --startCommand->fragmentsRemaining;
2031             startCommand->fragments[fragmentNumber / 32] |= (1 << (fragmentNumber % 32));
2032 
2033             if (fragmentOffset + fragmentLength > startCommand->packet->dataLength) {
2034                 fragmentLength = startCommand->packet->dataLength - fragmentOffset;
2035             }
2036 
2037             memcpy(startCommand->packet->data + fragmentOffset, (enet_uint8 *) command + sizeof(ENetProtocolSendFragment), fragmentLength);
2038 
2039             if (startCommand->fragmentsRemaining <= 0) {
2040                 enet_peer_dispatch_incoming_reliable_commands(peer, channel);
2041             }
2042         }
2043 
2044         return 0;
2045     } /* enet_protocol_handle_send_fragment */
2046 
enet_protocol_handle_send_unreliable_fragment(ENetHost * host,ENetPeer * peer,ENetProtocol * command,enet_uint8 ** currentData)2047     static int enet_protocol_handle_send_unreliable_fragment(ENetHost *host, ENetPeer *peer, ENetProtocol *command, enet_uint8 **currentData) {
2048         enet_uint32 fragmentNumber, fragmentCount, fragmentOffset, fragmentLength, reliableSequenceNumber, startSequenceNumber, totalLength;
2049         enet_uint16 reliableWindow, currentWindow;
2050         ENetChannel *channel;
2051         ENetListIterator currentCommand;
2052         ENetIncomingCommand *startCommand = NULL;
2053 
2054         if (command->header.channelID >= peer->channelCount || (peer->state != ENET_PEER_STATE_CONNECTED && peer->state != ENET_PEER_STATE_DISCONNECT_LATER)) {
2055             return -1;
2056         }
2057 
2058         fragmentLength = ENET_NET_TO_HOST_16(command->sendFragment.dataLength);
2059         *currentData  += fragmentLength;
2060         if (fragmentLength > host->maximumPacketSize || *currentData < host->receivedData || *currentData > &host->receivedData[host->receivedDataLength]) {
2061             return -1;
2062         }
2063 
2064         channel = &peer->channels[command->header.channelID];
2065         reliableSequenceNumber = command->header.reliableSequenceNumber;
2066         startSequenceNumber    = ENET_NET_TO_HOST_16(command->sendFragment.startSequenceNumber);
2067 
2068         reliableWindow = reliableSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE;
2069         currentWindow  = channel->incomingReliableSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE;
2070 
2071         if (reliableSequenceNumber < channel->incomingReliableSequenceNumber) {
2072             reliableWindow += ENET_PEER_RELIABLE_WINDOWS;
2073         }
2074 
2075         if (reliableWindow < currentWindow || reliableWindow >= currentWindow + ENET_PEER_FREE_RELIABLE_WINDOWS - 1) {
2076             return 0;
2077         }
2078 
2079         if (reliableSequenceNumber == channel->incomingReliableSequenceNumber && startSequenceNumber <= channel->incomingUnreliableSequenceNumber) {
2080             return 0;
2081         }
2082 
2083         fragmentNumber = ENET_NET_TO_HOST_32(command->sendFragment.fragmentNumber);
2084         fragmentCount  = ENET_NET_TO_HOST_32(command->sendFragment.fragmentCount);
2085         fragmentOffset = ENET_NET_TO_HOST_32(command->sendFragment.fragmentOffset);
2086         totalLength    = ENET_NET_TO_HOST_32(command->sendFragment.totalLength);
2087 
2088         if (fragmentCount > ENET_PROTOCOL_MAXIMUM_FRAGMENT_COUNT ||
2089             fragmentNumber >= fragmentCount ||
2090             totalLength > host->maximumPacketSize ||
2091             fragmentOffset >= totalLength ||
2092             fragmentLength > totalLength - fragmentOffset
2093         ) {
2094             return -1;
2095         }
2096 
2097         for (currentCommand = enet_list_previous(enet_list_end(&channel->incomingUnreliableCommands));
2098             currentCommand != enet_list_end(&channel->incomingUnreliableCommands);
2099             currentCommand = enet_list_previous(currentCommand)
2100         ) {
2101             ENetIncomingCommand *incomingCommand = (ENetIncomingCommand *) currentCommand;
2102 
2103             if (reliableSequenceNumber >= channel->incomingReliableSequenceNumber) {
2104                 if (incomingCommand->reliableSequenceNumber < channel->incomingReliableSequenceNumber) {
2105                     continue;
2106                 }
2107             } else if (incomingCommand->reliableSequenceNumber >= channel->incomingReliableSequenceNumber) {
2108                 break;
2109             }
2110 
2111             if (incomingCommand->reliableSequenceNumber < reliableSequenceNumber) {
2112                 break;
2113             }
2114 
2115             if (incomingCommand->reliableSequenceNumber > reliableSequenceNumber) {
2116                 continue;
2117             }
2118 
2119             if (incomingCommand->unreliableSequenceNumber <= startSequenceNumber) {
2120                 if (incomingCommand->unreliableSequenceNumber < startSequenceNumber) {
2121                     break;
2122                 }
2123 
2124                 if ((incomingCommand->command.header.command & ENET_PROTOCOL_COMMAND_MASK) !=
2125                     ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE_FRAGMENT ||
2126                     totalLength != incomingCommand->packet->dataLength ||
2127                     fragmentCount != incomingCommand->fragmentCount
2128                 ) {
2129                     return -1;
2130                 }
2131 
2132                 startCommand = incomingCommand;
2133                 break;
2134             }
2135         }
2136 
2137         if (startCommand == NULL) {
2138             startCommand = enet_peer_queue_incoming_command(peer, command, NULL, totalLength,
2139                 ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT, fragmentCount);
2140             if (startCommand == NULL) {
2141                 return -1;
2142             }
2143         }
2144 
2145         if ((startCommand->fragments[fragmentNumber / 32] & (1 << (fragmentNumber % 32))) == 0) {
2146             --startCommand->fragmentsRemaining;
2147             startCommand->fragments[fragmentNumber / 32] |= (1 << (fragmentNumber % 32));
2148 
2149             if (fragmentOffset + fragmentLength > startCommand->packet->dataLength) {
2150                 fragmentLength = startCommand->packet->dataLength - fragmentOffset;
2151             }
2152 
2153             memcpy(startCommand->packet->data + fragmentOffset, (enet_uint8 *) command + sizeof(ENetProtocolSendFragment), fragmentLength);
2154 
2155             if (startCommand->fragmentsRemaining <= 0) {
2156                 enet_peer_dispatch_incoming_unreliable_commands(peer, channel);
2157             }
2158         }
2159 
2160         return 0;
2161     } /* enet_protocol_handle_send_unreliable_fragment */
2162 
enet_protocol_handle_ping(ENetHost * host,ENetPeer * peer,const ENetProtocol * command)2163     static int enet_protocol_handle_ping(ENetHost *host, ENetPeer *peer, const ENetProtocol *command) {
2164         UNREFERENCED_PARAMETER(host);
2165         UNREFERENCED_PARAMETER(command);
2166         if (peer->state != ENET_PEER_STATE_CONNECTED && peer->state != ENET_PEER_STATE_DISCONNECT_LATER) {
2167             return -1;
2168         }
2169 
2170         return 0;
2171     }
2172 
enet_protocol_handle_bandwidth_limit(ENetHost * host,ENetPeer * peer,const ENetProtocol * command)2173     static int enet_protocol_handle_bandwidth_limit(ENetHost *host, ENetPeer *peer, const ENetProtocol *command) {
2174         if (peer->state != ENET_PEER_STATE_CONNECTED && peer->state != ENET_PEER_STATE_DISCONNECT_LATER) {
2175             return -1;
2176         }
2177 
2178         if (peer->incomingBandwidth != 0) {
2179             --host->bandwidthLimitedPeers;
2180         }
2181 
2182         peer->incomingBandwidth = ENET_NET_TO_HOST_32(command->bandwidthLimit.incomingBandwidth);
2183         peer->outgoingBandwidth = ENET_NET_TO_HOST_32(command->bandwidthLimit.outgoingBandwidth);
2184 
2185         if (peer->incomingBandwidth != 0) {
2186             ++host->bandwidthLimitedPeers;
2187         }
2188 
2189         if (peer->incomingBandwidth == 0 && host->outgoingBandwidth == 0) {
2190             peer->windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE;
2191         } else if (peer->incomingBandwidth == 0 || host->outgoingBandwidth == 0) {
2192             peer->windowSize = (ENET_MAX(peer->incomingBandwidth, host->outgoingBandwidth)
2193               / ENET_PEER_WINDOW_SIZE_SCALE) * ENET_PROTOCOL_MINIMUM_WINDOW_SIZE;
2194         } else {
2195             peer->windowSize = (ENET_MIN(peer->incomingBandwidth, host->outgoingBandwidth)
2196               / ENET_PEER_WINDOW_SIZE_SCALE) * ENET_PROTOCOL_MINIMUM_WINDOW_SIZE;
2197         }
2198 
2199         if (peer->windowSize < ENET_PROTOCOL_MINIMUM_WINDOW_SIZE) {
2200             peer->windowSize = ENET_PROTOCOL_MINIMUM_WINDOW_SIZE;
2201         } else if (peer->windowSize > ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE) {
2202             peer->windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE;
2203         }
2204 
2205         return 0;
2206     } /* enet_protocol_handle_bandwidth_limit */
2207 
enet_protocol_handle_throttle_configure(ENetHost * host,ENetPeer * peer,ENetProtocol * command)2208     static int enet_protocol_handle_throttle_configure(ENetHost *host, ENetPeer *peer, ENetProtocol *command) {
2209         UNREFERENCED_PARAMETER(host);
2210         UNREFERENCED_PARAMETER(command);
2211         if (peer->state != ENET_PEER_STATE_CONNECTED && peer->state != ENET_PEER_STATE_DISCONNECT_LATER) {
2212             return -1;
2213         }
2214 
2215         peer->packetThrottleInterval     = ENET_NET_TO_HOST_32(command->throttleConfigure.packetThrottleInterval);
2216         peer->packetThrottleAcceleration = ENET_NET_TO_HOST_32(command->throttleConfigure.packetThrottleAcceleration);
2217         peer->packetThrottleDeceleration = ENET_NET_TO_HOST_32(command->throttleConfigure.packetThrottleDeceleration);
2218 
2219         return 0;
2220     }
2221 
enet_protocol_handle_disconnect(ENetHost * host,ENetPeer * peer,const ENetProtocol * command)2222     static int enet_protocol_handle_disconnect(ENetHost *host, ENetPeer *peer, const ENetProtocol *command) {
2223         if (peer->state == ENET_PEER_STATE_DISCONNECTED || peer->state == ENET_PEER_STATE_ZOMBIE ||
2224             peer->state == ENET_PEER_STATE_ACKNOWLEDGING_DISCONNECT
2225         ) {
2226             return 0;
2227         }
2228 
2229         enet_peer_reset_queues(peer);
2230 
2231         if (peer->state == ENET_PEER_STATE_CONNECTION_SUCCEEDED || peer->state == ENET_PEER_STATE_DISCONNECTING || peer->state == ENET_PEER_STATE_CONNECTING) {
2232             enet_protocol_dispatch_state(host, peer, ENET_PEER_STATE_ZOMBIE);
2233         }
2234         else if (peer->state != ENET_PEER_STATE_CONNECTED && peer->state != ENET_PEER_STATE_DISCONNECT_LATER) {
2235             if (peer->state == ENET_PEER_STATE_CONNECTION_PENDING) { host->recalculateBandwidthLimits = 1; }
2236             enet_peer_reset(peer);
2237         }
2238         else if (command->header.command & ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE) {
2239             enet_protocol_change_state(host, peer, ENET_PEER_STATE_ACKNOWLEDGING_DISCONNECT);
2240         }
2241         else {
2242             enet_protocol_dispatch_state(host, peer, ENET_PEER_STATE_ZOMBIE);
2243         }
2244 
2245         if (peer->state != ENET_PEER_STATE_DISCONNECTED) {
2246             peer->eventData = ENET_NET_TO_HOST_32(command->disconnect.data);
2247         }
2248 
2249         return 0;
2250     }
2251 
enet_protocol_handle_acknowledge(ENetHost * host,ENetEvent * event,ENetPeer * peer,const ENetProtocol * command)2252     static int enet_protocol_handle_acknowledge(ENetHost *host, ENetEvent *event, ENetPeer *peer, const ENetProtocol *command) {
2253         enet_uint32 roundTripTime, receivedSentTime, receivedReliableSequenceNumber;
2254         ENetProtocolCommand commandNumber;
2255 
2256         if (peer->state == ENET_PEER_STATE_DISCONNECTED || peer->state == ENET_PEER_STATE_ZOMBIE) {
2257             return 0;
2258         }
2259 
2260         receivedSentTime  = ENET_NET_TO_HOST_16(command->acknowledge.receivedSentTime);
2261         receivedSentTime |= host->serviceTime & 0xFFFF0000;
2262         if ((receivedSentTime & 0x8000) > (host->serviceTime & 0x8000)) {
2263             receivedSentTime -= 0x10000;
2264         }
2265 
2266         if (ENET_TIME_LESS(host->serviceTime, receivedSentTime)) {
2267             return 0;
2268         }
2269 
2270         peer->lastReceiveTime = host->serviceTime;
2271         peer->earliestTimeout = 0;
2272         roundTripTime = ENET_TIME_DIFFERENCE(host->serviceTime, receivedSentTime);
2273 
2274         enet_peer_throttle(peer, roundTripTime);
2275         peer->roundTripTimeVariance -= peer->roundTripTimeVariance / 4;
2276 
2277         if (roundTripTime >= peer->roundTripTime) {
2278             peer->roundTripTime         += (roundTripTime - peer->roundTripTime) / 8;
2279             peer->roundTripTimeVariance += (roundTripTime - peer->roundTripTime) / 4;
2280         } else {
2281             peer->roundTripTime         -= (peer->roundTripTime - roundTripTime) / 8;
2282             peer->roundTripTimeVariance += (peer->roundTripTime - roundTripTime) / 4;
2283         }
2284 
2285         if (peer->roundTripTime < peer->lowestRoundTripTime) {
2286             peer->lowestRoundTripTime = peer->roundTripTime;
2287         }
2288 
2289         if (peer->roundTripTimeVariance > peer->highestRoundTripTimeVariance) {
2290             peer->highestRoundTripTimeVariance = peer->roundTripTimeVariance;
2291         }
2292 
2293         if (peer->packetThrottleEpoch == 0 ||
2294             ENET_TIME_DIFFERENCE(host->serviceTime, peer->packetThrottleEpoch) >= peer->packetThrottleInterval
2295         ) {
2296             peer->lastRoundTripTime            = peer->lowestRoundTripTime;
2297             peer->lastRoundTripTimeVariance    = peer->highestRoundTripTimeVariance;
2298             peer->lowestRoundTripTime          = peer->roundTripTime;
2299             peer->highestRoundTripTimeVariance = peer->roundTripTimeVariance;
2300             peer->packetThrottleEpoch          = host->serviceTime;
2301         }
2302 
2303         receivedReliableSequenceNumber = ENET_NET_TO_HOST_16(command->acknowledge.receivedReliableSequenceNumber);
2304         commandNumber = enet_protocol_remove_sent_reliable_command(peer, receivedReliableSequenceNumber, command->header.channelID);
2305 
2306         switch (peer->state) {
2307             case ENET_PEER_STATE_ACKNOWLEDGING_CONNECT:
2308                 if (commandNumber != ENET_PROTOCOL_COMMAND_VERIFY_CONNECT) {
2309                     return -1;
2310                 }
2311 
2312                 enet_protocol_notify_connect(host, peer, event);
2313                 break;
2314 
2315             case ENET_PEER_STATE_DISCONNECTING:
2316                 if (commandNumber != ENET_PROTOCOL_COMMAND_DISCONNECT) {
2317                     return -1;
2318                 }
2319 
2320                 enet_protocol_notify_disconnect(host, peer, event);
2321                 break;
2322 
2323             case ENET_PEER_STATE_DISCONNECT_LATER:
2324                 if (enet_list_empty(&peer->outgoingReliableCommands) &&
2325                   enet_list_empty(&peer->outgoingUnreliableCommands) &&
2326                   enet_list_empty(&peer->sentReliableCommands))
2327                 {
2328                     enet_peer_disconnect(peer, peer->eventData);
2329                 }
2330                 break;
2331 
2332             default:
2333                 break;
2334         }
2335 
2336         return 0;
2337     } /* enet_protocol_handle_acknowledge */
2338 
enet_protocol_handle_verify_connect(ENetHost * host,ENetEvent * event,ENetPeer * peer,const ENetProtocol * command)2339     static int enet_protocol_handle_verify_connect(ENetHost *host, ENetEvent *event, ENetPeer *peer, const ENetProtocol *command) {
2340         enet_uint32 mtu, windowSize;
2341         size_t channelCount;
2342 
2343         if (peer->state != ENET_PEER_STATE_CONNECTING) {
2344             return 0;
2345         }
2346 
2347         channelCount = ENET_NET_TO_HOST_32(command->verifyConnect.channelCount);
2348 
2349         if (channelCount < ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT || channelCount > ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT ||
2350             ENET_NET_TO_HOST_32(command->verifyConnect.packetThrottleInterval) != peer->packetThrottleInterval ||
2351             ENET_NET_TO_HOST_32(command->verifyConnect.packetThrottleAcceleration) != peer->packetThrottleAcceleration ||
2352             ENET_NET_TO_HOST_32(command->verifyConnect.packetThrottleDeceleration) != peer->packetThrottleDeceleration ||
2353             command->verifyConnect.connectID != peer->connectID
2354         ) {
2355             peer->eventData = 0;
2356             enet_protocol_dispatch_state(host, peer, ENET_PEER_STATE_ZOMBIE);
2357             return -1;
2358         }
2359 
2360         enet_protocol_remove_sent_reliable_command(peer, 1, 0xFF);
2361 
2362         if (channelCount < peer->channelCount) {
2363             peer->channelCount = channelCount;
2364         }
2365 
2366         peer->outgoingPeerID    = ENET_NET_TO_HOST_16(command->verifyConnect.outgoingPeerID);
2367         peer->incomingSessionID = command->verifyConnect.incomingSessionID;
2368         peer->outgoingSessionID = command->verifyConnect.outgoingSessionID;
2369 
2370         mtu = ENET_NET_TO_HOST_32(command->verifyConnect.mtu);
2371 
2372         if (mtu < ENET_PROTOCOL_MINIMUM_MTU) {
2373             mtu = ENET_PROTOCOL_MINIMUM_MTU;
2374         } else if (mtu > ENET_PROTOCOL_MAXIMUM_MTU) {
2375             mtu = ENET_PROTOCOL_MAXIMUM_MTU;
2376         }
2377 
2378         if (mtu < peer->mtu) {
2379             peer->mtu = mtu;
2380         }
2381 
2382         windowSize = ENET_NET_TO_HOST_32(command->verifyConnect.windowSize);
2383         if (windowSize < ENET_PROTOCOL_MINIMUM_WINDOW_SIZE) {
2384             windowSize = ENET_PROTOCOL_MINIMUM_WINDOW_SIZE;
2385         }
2386 
2387         if (windowSize > ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE) {
2388             windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE;
2389         }
2390 
2391         if (windowSize < peer->windowSize) {
2392             peer->windowSize = windowSize;
2393         }
2394 
2395         peer->incomingBandwidth = ENET_NET_TO_HOST_32(command->verifyConnect.incomingBandwidth);
2396         peer->outgoingBandwidth = ENET_NET_TO_HOST_32(command->verifyConnect.outgoingBandwidth);
2397 
2398         enet_protocol_notify_connect(host, peer, event);
2399         return 0;
2400     } /* enet_protocol_handle_verify_connect */
2401 
enet_protocol_handle_incoming_commands(ENetHost * host,ENetEvent * event)2402     static int enet_protocol_handle_incoming_commands(ENetHost *host, ENetEvent *event) {
2403         ENetProtocolHeader *header;
2404         ENetProtocol *command;
2405         ENetPeer *peer;
2406         enet_uint8 *currentData;
2407         size_t headerSize;
2408         enet_uint16 peerID, flags;
2409         enet_uint8 sessionID;
2410 
2411         if (host->receivedDataLength < (size_t) &((ENetProtocolHeader *) 0)->sentTime) {
2412             return 0;
2413         }
2414 
2415         header = (ENetProtocolHeader *) host->receivedData;
2416 
2417         peerID    = ENET_NET_TO_HOST_16(header->peerID);
2418         sessionID = (peerID & ENET_PROTOCOL_HEADER_SESSION_MASK) >> ENET_PROTOCOL_HEADER_SESSION_SHIFT;
2419         flags     = peerID & ENET_PROTOCOL_HEADER_FLAG_MASK;
2420         peerID   &= ~(ENET_PROTOCOL_HEADER_FLAG_MASK | ENET_PROTOCOL_HEADER_SESSION_MASK);
2421 
2422         headerSize = (flags & ENET_PROTOCOL_HEADER_FLAG_SENT_TIME ? sizeof(ENetProtocolHeader) : (size_t) &((ENetProtocolHeader *) 0)->sentTime);
2423         if (host->checksum != NULL) {
2424             headerSize += sizeof(enet_uint32);
2425         }
2426 
2427         if (peerID == ENET_PROTOCOL_MAXIMUM_PEER_ID) {
2428             peer = NULL;
2429         } else if (peerID >= host->peerCount) {
2430             return 0;
2431         } else {
2432             peer = &host->peers[peerID];
2433 
2434             if (peer->state == ENET_PEER_STATE_DISCONNECTED ||
2435                 peer->state == ENET_PEER_STATE_ZOMBIE ||
2436                 ((!in6_equal(host->receivedAddress.host , peer->address.host) ||
2437                 host->receivedAddress.port != peer->address.port) &&
2438                 1 /* no broadcast in ipv6  !in6_equal(peer->address.host , ENET_HOST_BROADCAST)*/) ||
2439                 (peer->outgoingPeerID < ENET_PROTOCOL_MAXIMUM_PEER_ID &&
2440                 sessionID != peer->incomingSessionID)
2441             ) {
2442                 return 0;
2443             }
2444         }
2445 
2446         if (flags & ENET_PROTOCOL_HEADER_FLAG_COMPRESSED) {
2447             size_t originalSize;
2448             if (host->compressor.context == NULL || host->compressor.decompress == NULL) {
2449                 return 0;
2450             }
2451 
2452             originalSize = host->compressor.decompress(host->compressor.context,
2453                 host->receivedData + headerSize,
2454                 host->receivedDataLength - headerSize,
2455                 host->packetData[1] + headerSize,
2456                 sizeof(host->packetData[1]) - headerSize
2457             );
2458 
2459             if (originalSize <= 0 || originalSize > sizeof(host->packetData[1]) - headerSize) {
2460                 return 0;
2461             }
2462 
2463             memcpy(host->packetData[1], header, headerSize);
2464             host->receivedData       = host->packetData[1];
2465             host->receivedDataLength = headerSize + originalSize;
2466         }
2467 
2468         if (host->checksum != NULL) {
2469             enet_uint32 *checksum = (enet_uint32 *) &host->receivedData[headerSize - sizeof(enet_uint32)];
2470             enet_uint32 desiredChecksum = *checksum;
2471             ENetBuffer buffer;
2472 
2473             *checksum = peer != NULL ? peer->connectID : 0;
2474 
2475             buffer.data       = host->receivedData;
2476             buffer.dataLength = host->receivedDataLength;
2477 
2478             if (host->checksum(&buffer, 1) != desiredChecksum) {
2479                 return 0;
2480             }
2481         }
2482 
2483         if (peer != NULL) {
2484             peer->address.host       = host->receivedAddress.host;
2485             peer->address.port       = host->receivedAddress.port;
2486             peer->incomingDataTotal += host->receivedDataLength;
2487             peer->totalDataReceived += host->receivedDataLength;
2488         }
2489 
2490         currentData = host->receivedData + headerSize;
2491 
2492         while (currentData < &host->receivedData[host->receivedDataLength]) {
2493             enet_uint8 commandNumber;
2494             size_t commandSize;
2495 
2496             command = (ENetProtocol *) currentData;
2497 
2498             if (currentData + sizeof(ENetProtocolCommandHeader) > &host->receivedData[host->receivedDataLength]) {
2499                 break;
2500             }
2501 
2502             commandNumber = command->header.command & ENET_PROTOCOL_COMMAND_MASK;
2503             if (commandNumber >= ENET_PROTOCOL_COMMAND_COUNT) {
2504                 break;
2505             }
2506 
2507             commandSize = commandSizes[commandNumber];
2508             if (commandSize == 0 || currentData + commandSize > &host->receivedData[host->receivedDataLength]) {
2509                 break;
2510             }
2511 
2512             currentData += commandSize;
2513 
2514             if (peer == NULL && (commandNumber != ENET_PROTOCOL_COMMAND_CONNECT || currentData < &host->receivedData[host->receivedDataLength])) {
2515                 break;
2516             }
2517 
2518             command->header.reliableSequenceNumber = ENET_NET_TO_HOST_16(command->header.reliableSequenceNumber);
2519 
2520             switch (commandNumber) {
2521                 case ENET_PROTOCOL_COMMAND_ACKNOWLEDGE:
2522                     if (enet_protocol_handle_acknowledge(host, event, peer, command)) {
2523                         goto commandError;
2524                     }
2525                     break;
2526 
2527                 case ENET_PROTOCOL_COMMAND_CONNECT:
2528                     if (peer != NULL) {
2529                         goto commandError;
2530                     }
2531                     peer = enet_protocol_handle_connect(host, header, command);
2532                     if (peer == NULL) {
2533                         goto commandError;
2534                     }
2535                     break;
2536 
2537                 case ENET_PROTOCOL_COMMAND_VERIFY_CONNECT:
2538                     if (enet_protocol_handle_verify_connect(host, event, peer, command)) {
2539                         goto commandError;
2540                     }
2541                     break;
2542 
2543                 case ENET_PROTOCOL_COMMAND_DISCONNECT:
2544                     if (enet_protocol_handle_disconnect(host, peer, command)) {
2545                         goto commandError;
2546                     }
2547                     break;
2548 
2549                 case ENET_PROTOCOL_COMMAND_PING:
2550                     if (enet_protocol_handle_ping(host, peer, command)) {
2551                         goto commandError;
2552                     }
2553                     break;
2554 
2555                 case ENET_PROTOCOL_COMMAND_SEND_RELIABLE:
2556                     if (enet_protocol_handle_send_reliable(host, peer, command, &currentData)) {
2557                         goto commandError;
2558                     }
2559                     break;
2560 
2561                 case ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE:
2562                     if (enet_protocol_handle_send_unreliable(host, peer, command, &currentData)) {
2563                         goto commandError;
2564                     }
2565                     break;
2566 
2567                 case ENET_PROTOCOL_COMMAND_SEND_UNSEQUENCED:
2568                     if (enet_protocol_handle_send_unsequenced(host, peer, command, &currentData)) {
2569                         goto commandError;
2570                     }
2571                     break;
2572 
2573                 case ENET_PROTOCOL_COMMAND_SEND_FRAGMENT:
2574                     if (enet_protocol_handle_send_fragment(host, peer, command, &currentData)) {
2575                         goto commandError;
2576                     }
2577                     break;
2578 
2579                 case ENET_PROTOCOL_COMMAND_BANDWIDTH_LIMIT:
2580                     if (enet_protocol_handle_bandwidth_limit(host, peer, command)) {
2581                         goto commandError;
2582                     }
2583                     break;
2584 
2585                 case ENET_PROTOCOL_COMMAND_THROTTLE_CONFIGURE:
2586                     if (enet_protocol_handle_throttle_configure(host, peer, command)) {
2587                         goto commandError;
2588                     }
2589                     break;
2590 
2591                 case ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE_FRAGMENT:
2592                     if (enet_protocol_handle_send_unreliable_fragment(host, peer, command, &currentData)) {
2593                         goto commandError;
2594                     }
2595                     break;
2596 
2597                 default:
2598                     goto commandError;
2599             }
2600 
2601             if (peer != NULL && (command->header.command & ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE) != 0) {
2602                 enet_uint16 sentTime;
2603 
2604                 if (!(flags & ENET_PROTOCOL_HEADER_FLAG_SENT_TIME)) {
2605                     break;
2606                 }
2607 
2608                 sentTime = ENET_NET_TO_HOST_16(header->sentTime);
2609 
2610                 switch (peer->state) {
2611                     case ENET_PEER_STATE_DISCONNECTING:
2612                     case ENET_PEER_STATE_ACKNOWLEDGING_CONNECT:
2613                     case ENET_PEER_STATE_DISCONNECTED:
2614                     case ENET_PEER_STATE_ZOMBIE:
2615                         break;
2616 
2617                     case ENET_PEER_STATE_ACKNOWLEDGING_DISCONNECT:
2618                         if ((command->header.command & ENET_PROTOCOL_COMMAND_MASK) == ENET_PROTOCOL_COMMAND_DISCONNECT) {
2619                             enet_peer_queue_acknowledgement(peer, command, sentTime);
2620                         }
2621                         break;
2622 
2623                     default:
2624                         enet_peer_queue_acknowledgement(peer, command, sentTime);
2625                         break;
2626                 }
2627             }
2628         }
2629 
2630     commandError:
2631         if (event != NULL && event->type != ENET_EVENT_TYPE_NONE) {
2632             return 1;
2633         }
2634 
2635         return 0;
2636     } /* enet_protocol_handle_incoming_commands */
2637 
enet_protocol_receive_incoming_commands(ENetHost * host,ENetEvent * event)2638     static int enet_protocol_receive_incoming_commands(ENetHost *host, ENetEvent *event) {
2639         int packets;
2640 
2641         for (packets = 0; packets < 256; ++packets) {
2642             int receivedLength;
2643             ENetBuffer buffer;
2644 
2645             buffer.data       = host->packetData[0];
2646             // buffer.dataLength = sizeof (host->packetData[0]);
2647             buffer.dataLength = host->mtu;
2648 
2649             receivedLength    = enet_socket_receive(host->socket, &host->receivedAddress, &buffer, 1);
2650 
2651             if (receivedLength == -2)
2652                 continue;
2653 
2654             if (receivedLength < 0) {
2655                 return -1;
2656             }
2657 
2658             if (receivedLength == 0) {
2659                 return 0;
2660             }
2661 
2662             host->receivedData       = host->packetData[0];
2663             host->receivedDataLength = receivedLength;
2664 
2665             host->totalReceivedData += receivedLength;
2666             host->totalReceivedPackets++;
2667 
2668             if (host->intercept != NULL) {
2669                 switch (host->intercept(host, (void *)event)) {
2670                     case 1:
2671                         if (event != NULL && event->type != ENET_EVENT_TYPE_NONE) {
2672                             return 1;
2673                         }
2674 
2675                         continue;
2676 
2677                     case -1:
2678                         return -1;
2679 
2680                     default:
2681                         break;
2682                 }
2683             }
2684 
2685             switch (enet_protocol_handle_incoming_commands(host, event)) {
2686                 case 1:
2687                     return 1;
2688 
2689                 case -1:
2690                     return -1;
2691 
2692                 default:
2693                     break;
2694             }
2695         }
2696 
2697         return -1;
2698     } /* enet_protocol_receive_incoming_commands */
2699 
enet_protocol_send_acknowledgements(ENetHost * host,ENetPeer * peer)2700     static void enet_protocol_send_acknowledgements(ENetHost *host, ENetPeer *peer) {
2701         ENetProtocol *command = &host->commands[host->commandCount];
2702         ENetBuffer *buffer    = &host->buffers[host->bufferCount];
2703         ENetAcknowledgement *acknowledgement;
2704         ENetListIterator currentAcknowledgement;
2705         enet_uint16 reliableSequenceNumber;
2706 
2707         currentAcknowledgement = enet_list_begin(&peer->acknowledgements);
2708 
2709         while (currentAcknowledgement != enet_list_end(&peer->acknowledgements)) {
2710             if (command >= &host->commands[sizeof(host->commands) / sizeof(ENetProtocol)] ||
2711                 buffer >= &host->buffers[sizeof(host->buffers) / sizeof(ENetBuffer)] ||
2712                 peer->mtu - host->packetSize < sizeof(ENetProtocolAcknowledge)
2713             ) {
2714                 host->continueSending = 1;
2715                 break;
2716             }
2717 
2718             acknowledgement = (ENetAcknowledgement *) currentAcknowledgement;
2719             currentAcknowledgement = enet_list_next(currentAcknowledgement);
2720 
2721             buffer->data       = command;
2722             buffer->dataLength = sizeof(ENetProtocolAcknowledge);
2723             host->packetSize += buffer->dataLength;
2724 
2725             reliableSequenceNumber = ENET_HOST_TO_NET_16(acknowledgement->command.header.reliableSequenceNumber);
2726 
2727             command->header.command   = ENET_PROTOCOL_COMMAND_ACKNOWLEDGE;
2728             command->header.channelID = acknowledgement->command.header.channelID;
2729             command->header.reliableSequenceNumber = reliableSequenceNumber;
2730             command->acknowledge.receivedReliableSequenceNumber = reliableSequenceNumber;
2731             command->acknowledge.receivedSentTime = ENET_HOST_TO_NET_16(acknowledgement->sentTime);
2732 
2733             if ((acknowledgement->command.header.command & ENET_PROTOCOL_COMMAND_MASK) == ENET_PROTOCOL_COMMAND_DISCONNECT) {
2734                 enet_protocol_dispatch_state(host, peer, ENET_PEER_STATE_ZOMBIE);
2735             }
2736 
2737             enet_list_remove(&acknowledgement->acknowledgementList);
2738             enet_free(acknowledgement);
2739 
2740             ++command;
2741             ++buffer;
2742         }
2743 
2744         host->commandCount = command - host->commands;
2745         host->bufferCount  = buffer - host->buffers;
2746     } /* enet_protocol_send_acknowledgements */
2747 
enet_protocol_send_unreliable_outgoing_commands(ENetHost * host,ENetPeer * peer)2748     static void enet_protocol_send_unreliable_outgoing_commands(ENetHost *host, ENetPeer *peer) {
2749         ENetProtocol *command = &host->commands[host->commandCount];
2750         ENetBuffer *buffer    = &host->buffers[host->bufferCount];
2751         ENetOutgoingCommand *outgoingCommand;
2752         ENetListIterator currentCommand;
2753 
2754         currentCommand = enet_list_begin(&peer->outgoingUnreliableCommands);
2755         while (currentCommand != enet_list_end(&peer->outgoingUnreliableCommands)) {
2756             size_t commandSize;
2757 
2758             outgoingCommand = (ENetOutgoingCommand *) currentCommand;
2759             commandSize     = commandSizes[outgoingCommand->command.header.command & ENET_PROTOCOL_COMMAND_MASK];
2760 
2761             if (command >= &host->commands[sizeof(host->commands) / sizeof(ENetProtocol)] ||
2762                 buffer + 1 >= &host->buffers[sizeof(host->buffers) / sizeof(ENetBuffer)] ||
2763                 peer->mtu - host->packetSize < commandSize ||
2764                 (outgoingCommand->packet != NULL &&
2765                 peer->mtu - host->packetSize < commandSize + outgoingCommand->fragmentLength)
2766             ) {
2767                 host->continueSending = 1;
2768                 break;
2769             }
2770 
2771             currentCommand = enet_list_next(currentCommand);
2772 
2773             if (outgoingCommand->packet != NULL && outgoingCommand->fragmentOffset == 0) {
2774                 peer->packetThrottleCounter += ENET_PEER_PACKET_THROTTLE_COUNTER;
2775                 peer->packetThrottleCounter %= ENET_PEER_PACKET_THROTTLE_SCALE;
2776 
2777                 if (peer->packetThrottleCounter > peer->packetThrottle) {
2778                     enet_uint16 reliableSequenceNumber = outgoingCommand->reliableSequenceNumber;
2779                     enet_uint16 unreliableSequenceNumber = outgoingCommand->unreliableSequenceNumber;
2780                     for (;;) {
2781                         --outgoingCommand->packet->referenceCount;
2782 
2783                         if (outgoingCommand->packet->referenceCount == 0) {
2784                             enet_packet_destroy(outgoingCommand->packet);
2785                         }
2786 
2787                         enet_list_remove(&outgoingCommand->outgoingCommandList);
2788                         enet_free(outgoingCommand);
2789 
2790                         if (currentCommand == enet_list_end(&peer->outgoingUnreliableCommands)) {
2791                             break;
2792                         }
2793 
2794                         outgoingCommand = (ENetOutgoingCommand *) currentCommand;
2795                         if (outgoingCommand->reliableSequenceNumber != reliableSequenceNumber || outgoingCommand->unreliableSequenceNumber != unreliableSequenceNumber) {
2796                             break;
2797                         }
2798 
2799                         currentCommand = enet_list_next(currentCommand);
2800                     }
2801 
2802                     continue;
2803                 }
2804             }
2805 
2806             buffer->data       = command;
2807             buffer->dataLength = commandSize;
2808             host->packetSize += buffer->dataLength;
2809             *command = outgoingCommand->command;
2810             enet_list_remove(&outgoingCommand->outgoingCommandList);
2811 
2812             if (outgoingCommand->packet != NULL) {
2813                 ++buffer;
2814 
2815                 buffer->data       = outgoingCommand->packet->data + outgoingCommand->fragmentOffset;
2816                 buffer->dataLength = outgoingCommand->fragmentLength;
2817 
2818                 host->packetSize += buffer->dataLength;
2819 
2820                 enet_list_insert(enet_list_end(&peer->sentUnreliableCommands), outgoingCommand);
2821             } else {
2822                 enet_free(outgoingCommand);
2823             }
2824 
2825             ++command;
2826             ++buffer;
2827         }
2828 
2829         host->commandCount = command - host->commands;
2830         host->bufferCount  = buffer - host->buffers;
2831 
2832         if (peer->state == ENET_PEER_STATE_DISCONNECT_LATER &&
2833           enet_list_empty(&peer->outgoingReliableCommands) &&
2834           enet_list_empty(&peer->outgoingUnreliableCommands) &&
2835           enet_list_empty(&peer->sentReliableCommands))
2836         {
2837             enet_peer_disconnect(peer, peer->eventData);
2838         }
2839     } /* enet_protocol_send_unreliable_outgoing_commands */
2840 
enet_protocol_check_timeouts(ENetHost * host,ENetPeer * peer,ENetEvent * event)2841     static int enet_protocol_check_timeouts(ENetHost *host, ENetPeer *peer, ENetEvent *event) {
2842         ENetOutgoingCommand *outgoingCommand;
2843         ENetListIterator currentCommand, insertPosition;
2844 
2845         currentCommand = enet_list_begin(&peer->sentReliableCommands);
2846         insertPosition = enet_list_begin(&peer->outgoingReliableCommands);
2847 
2848         while (currentCommand != enet_list_end(&peer->sentReliableCommands)) {
2849             outgoingCommand = (ENetOutgoingCommand *) currentCommand;
2850 
2851             currentCommand = enet_list_next(currentCommand);
2852 
2853             if (ENET_TIME_DIFFERENCE(host->serviceTime, outgoingCommand->sentTime) < outgoingCommand->roundTripTimeout) {
2854                 continue;
2855             }
2856 
2857             if (peer->earliestTimeout == 0 || ENET_TIME_LESS(outgoingCommand->sentTime, peer->earliestTimeout)) {
2858                 peer->earliestTimeout = outgoingCommand->sentTime;
2859             }
2860 
2861             if (peer->earliestTimeout != 0 &&
2862                 (ENET_TIME_DIFFERENCE(host->serviceTime, peer->earliestTimeout) >= peer->timeoutMaximum ||
2863                 (outgoingCommand->roundTripTimeout >= outgoingCommand->roundTripTimeoutLimit &&
2864                 ENET_TIME_DIFFERENCE(host->serviceTime, peer->earliestTimeout) >= peer->timeoutMinimum))
2865             ) {
2866                 enet_protocol_notify_disconnect_timeout(host, peer, event);
2867                 return 1;
2868             }
2869 
2870             if (outgoingCommand->packet != NULL) {
2871                 peer->reliableDataInTransit -= outgoingCommand->fragmentLength;
2872             }
2873 
2874             ++peer->packetsLost;
2875             ++peer->totalPacketsLost;
2876 
2877             /* Replaced exponential backoff time with something more linear */
2878             /* Source: http://lists.cubik.org/pipermail/enet-discuss/2014-May/002308.html */
2879             outgoingCommand->roundTripTimeout = peer->roundTripTime + 4 * peer->roundTripTimeVariance;
2880             outgoingCommand->roundTripTimeoutLimit = peer->timeoutLimit * outgoingCommand->roundTripTimeout;
2881 
2882             enet_list_insert(insertPosition, enet_list_remove(&outgoingCommand->outgoingCommandList));
2883 
2884             if (currentCommand == enet_list_begin(&peer->sentReliableCommands) && !enet_list_empty(&peer->sentReliableCommands)) {
2885                 outgoingCommand = (ENetOutgoingCommand *) currentCommand;
2886                 peer->nextTimeout = outgoingCommand->sentTime + outgoingCommand->roundTripTimeout;
2887             }
2888         }
2889 
2890         return 0;
2891     } /* enet_protocol_check_timeouts */
2892 
enet_protocol_send_reliable_outgoing_commands(ENetHost * host,ENetPeer * peer)2893     static int enet_protocol_send_reliable_outgoing_commands(ENetHost *host, ENetPeer *peer) {
2894         ENetProtocol *command = &host->commands[host->commandCount];
2895         ENetBuffer *buffer    = &host->buffers[host->bufferCount];
2896         ENetOutgoingCommand *outgoingCommand;
2897         ENetListIterator currentCommand;
2898         ENetChannel *channel;
2899         enet_uint16 reliableWindow;
2900         size_t commandSize;
2901         int windowExceeded = 0, windowWrap = 0, canPing = 1;
2902 
2903         currentCommand = enet_list_begin(&peer->outgoingReliableCommands);
2904 
2905         while (currentCommand != enet_list_end(&peer->outgoingReliableCommands)) {
2906             outgoingCommand = (ENetOutgoingCommand *) currentCommand;
2907 
2908             channel = outgoingCommand->command.header.channelID < peer->channelCount ? &peer->channels[outgoingCommand->command.header.channelID] : NULL;
2909             reliableWindow = outgoingCommand->reliableSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE;
2910             if (channel != NULL) {
2911                 if (!windowWrap &&
2912                     outgoingCommand->sendAttempts < 1 &&
2913                     !(outgoingCommand->reliableSequenceNumber % ENET_PEER_RELIABLE_WINDOW_SIZE) &&
2914                     (channel->reliableWindows[(reliableWindow + ENET_PEER_RELIABLE_WINDOWS - 1)
2915                     % ENET_PEER_RELIABLE_WINDOWS] >= ENET_PEER_RELIABLE_WINDOW_SIZE ||
2916                     channel->usedReliableWindows & ((((1 << ENET_PEER_FREE_RELIABLE_WINDOWS) - 1) << reliableWindow)
2917                     | (((1 << ENET_PEER_FREE_RELIABLE_WINDOWS) - 1) >> (ENET_PEER_RELIABLE_WINDOWS - reliableWindow))))
2918                 ) {
2919                     windowWrap = 1;
2920                 }
2921 
2922                 if (windowWrap) {
2923                     currentCommand = enet_list_next(currentCommand);
2924                     continue;
2925                 }
2926             }
2927 
2928             if (outgoingCommand->packet != NULL) {
2929                 if (!windowExceeded) {
2930                     enet_uint32 windowSize = (peer->packetThrottle * peer->windowSize) / ENET_PEER_PACKET_THROTTLE_SCALE;
2931 
2932                     if (peer->reliableDataInTransit + outgoingCommand->fragmentLength > ENET_MAX(windowSize, peer->mtu)) {
2933                         windowExceeded = 1;
2934                     }
2935                 }
2936                 if (windowExceeded) {
2937                     currentCommand = enet_list_next(currentCommand);
2938 
2939                     continue;
2940                 }
2941             }
2942 
2943             canPing = 0;
2944 
2945             commandSize = commandSizes[outgoingCommand->command.header.command & ENET_PROTOCOL_COMMAND_MASK];
2946             if (command >= &host->commands[sizeof(host->commands) / sizeof(ENetProtocol)] ||
2947                 buffer + 1 >= &host->buffers[sizeof(host->buffers) / sizeof(ENetBuffer)] ||
2948                 peer->mtu - host->packetSize < commandSize ||
2949                 (outgoingCommand->packet != NULL &&
2950                 (enet_uint16) (peer->mtu - host->packetSize) < (enet_uint16) (commandSize + outgoingCommand->fragmentLength))
2951             ) {
2952                 host->continueSending = 1;
2953                 break;
2954             }
2955 
2956             currentCommand = enet_list_next(currentCommand);
2957 
2958             if (channel != NULL && outgoingCommand->sendAttempts < 1) {
2959                 channel->usedReliableWindows |= 1 << reliableWindow;
2960                 ++channel->reliableWindows[reliableWindow];
2961             }
2962 
2963             ++outgoingCommand->sendAttempts;
2964 
2965             if (outgoingCommand->roundTripTimeout == 0) {
2966                 outgoingCommand->roundTripTimeout      = peer->roundTripTime + 4 * peer->roundTripTimeVariance;
2967                 outgoingCommand->roundTripTimeoutLimit = peer->timeoutLimit * outgoingCommand->roundTripTimeout;
2968             }
2969 
2970             if (enet_list_empty(&peer->sentReliableCommands)) {
2971                 peer->nextTimeout = host->serviceTime + outgoingCommand->roundTripTimeout;
2972             }
2973 
2974             enet_list_insert(enet_list_end(&peer->sentReliableCommands), enet_list_remove(&outgoingCommand->outgoingCommandList));
2975 
2976             outgoingCommand->sentTime = host->serviceTime;
2977 
2978             buffer->data       = command;
2979             buffer->dataLength = commandSize;
2980 
2981             host->packetSize  += buffer->dataLength;
2982             host->headerFlags |= ENET_PROTOCOL_HEADER_FLAG_SENT_TIME;
2983 
2984             *command = outgoingCommand->command;
2985 
2986             if (outgoingCommand->packet != NULL) {
2987                 ++buffer;
2988                 buffer->data       = outgoingCommand->packet->data + outgoingCommand->fragmentOffset;
2989                 buffer->dataLength = outgoingCommand->fragmentLength;
2990                 host->packetSize += outgoingCommand->fragmentLength;
2991                 peer->reliableDataInTransit += outgoingCommand->fragmentLength;
2992             }
2993 
2994             ++peer->packetsSent;
2995             ++peer->totalPacketsSent;
2996 
2997             ++command;
2998             ++buffer;
2999         }
3000 
3001         host->commandCount = command - host->commands;
3002         host->bufferCount  = buffer - host->buffers;
3003 
3004         return canPing;
3005     } /* enet_protocol_send_reliable_outgoing_commands */
3006 
enet_protocol_send_outgoing_commands(ENetHost * host,ENetEvent * event,int checkForTimeouts)3007     static int enet_protocol_send_outgoing_commands(ENetHost *host, ENetEvent *event, int checkForTimeouts) {
3008         enet_uint8 headerData[sizeof(ENetProtocolHeader) + sizeof(enet_uint32)];
3009         ENetProtocolHeader *header = (ENetProtocolHeader *) headerData;
3010         ENetPeer *currentPeer;
3011         int sentLength;
3012         size_t shouldCompress = 0;
3013         host->continueSending = 1;
3014 
3015         while (host->continueSending)
3016             for (host->continueSending = 0, currentPeer = host->peers; currentPeer < &host->peers[host->peerCount]; ++currentPeer) {
3017                 if (currentPeer->state == ENET_PEER_STATE_DISCONNECTED || currentPeer->state == ENET_PEER_STATE_ZOMBIE) {
3018                     continue;
3019                 }
3020 
3021                 host->headerFlags  = 0;
3022                 host->commandCount = 0;
3023                 host->bufferCount  = 1;
3024                 host->packetSize   = sizeof(ENetProtocolHeader);
3025 
3026                 if (!enet_list_empty(&currentPeer->acknowledgements)) {
3027                     enet_protocol_send_acknowledgements(host, currentPeer);
3028                 }
3029 
3030                 if (checkForTimeouts != 0 &&
3031                     !enet_list_empty(&currentPeer->sentReliableCommands) &&
3032                     ENET_TIME_GREATER_EQUAL(host->serviceTime, currentPeer->nextTimeout) &&
3033                     enet_protocol_check_timeouts(host, currentPeer, event) == 1
3034                 ) {
3035                     if (event != NULL && event->type != ENET_EVENT_TYPE_NONE) {
3036                         return 1;
3037                     } else {
3038                         continue;
3039                     }
3040                 }
3041 
3042                 if ((enet_list_empty(&currentPeer->outgoingReliableCommands) ||
3043                     enet_protocol_send_reliable_outgoing_commands(host, currentPeer)) &&
3044                     enet_list_empty(&currentPeer->sentReliableCommands) &&
3045                     ENET_TIME_DIFFERENCE(host->serviceTime, currentPeer->lastReceiveTime) >= currentPeer->pingInterval &&
3046                     currentPeer->mtu - host->packetSize >= sizeof(ENetProtocolPing)
3047                 ) {
3048                     enet_peer_ping(currentPeer);
3049                     enet_protocol_send_reliable_outgoing_commands(host, currentPeer);
3050                 }
3051 
3052                 if (!enet_list_empty(&currentPeer->outgoingUnreliableCommands)) {
3053                     enet_protocol_send_unreliable_outgoing_commands(host, currentPeer);
3054                 }
3055 
3056                 if (host->commandCount == 0) {
3057                     continue;
3058                 }
3059 
3060                 if (currentPeer->packetLossEpoch == 0) {
3061                     currentPeer->packetLossEpoch = host->serviceTime;
3062                 } else if (ENET_TIME_DIFFERENCE(host->serviceTime, currentPeer->packetLossEpoch) >= ENET_PEER_PACKET_LOSS_INTERVAL && currentPeer->packetsSent > 0) {
3063                     enet_uint32 packetLoss = currentPeer->packetsLost * ENET_PEER_PACKET_LOSS_SCALE / currentPeer->packetsSent;
3064 
3065                     #ifdef ENET_DEBUG
3066                     printf(
3067                         "peer %u: %f%%+-%f%% packet loss, %u+-%u ms round trip time, %f%% throttle, %u/%u outgoing, %u/%u incoming\n", currentPeer->incomingPeerID,
3068                         currentPeer->packetLoss / (float) ENET_PEER_PACKET_LOSS_SCALE,
3069                         currentPeer->packetLossVariance / (float) ENET_PEER_PACKET_LOSS_SCALE, currentPeer->roundTripTime, currentPeer->roundTripTimeVariance,
3070                         currentPeer->packetThrottle / (float) ENET_PEER_PACKET_THROTTLE_SCALE,
3071                         enet_list_size(&currentPeer->outgoingReliableCommands),
3072                         enet_list_size(&currentPeer->outgoingUnreliableCommands),
3073                         currentPeer->channels != NULL ? enet_list_size( &currentPeer->channels->incomingReliableCommands) : 0,
3074                         currentPeer->channels != NULL ? enet_list_size(&currentPeer->channels->incomingUnreliableCommands) : 0
3075                     );
3076                     #endif
3077 
3078                     currentPeer->packetLossVariance -= currentPeer->packetLossVariance / 4;
3079 
3080                     if (packetLoss >= currentPeer->packetLoss) {
3081                         currentPeer->packetLoss         += (packetLoss - currentPeer->packetLoss) / 8;
3082                         currentPeer->packetLossVariance += (packetLoss - currentPeer->packetLoss) / 4;
3083                     } else {
3084                         currentPeer->packetLoss         -= (currentPeer->packetLoss - packetLoss) / 8;
3085                         currentPeer->packetLossVariance += (currentPeer->packetLoss - packetLoss) / 4;
3086                     }
3087 
3088                     currentPeer->packetLossEpoch = host->serviceTime;
3089                     currentPeer->packetsSent     = 0;
3090                     currentPeer->packetsLost     = 0;
3091                 }
3092 
3093                 host->buffers->data = headerData;
3094                 if (host->headerFlags & ENET_PROTOCOL_HEADER_FLAG_SENT_TIME) {
3095                     header->sentTime = ENET_HOST_TO_NET_16(host->serviceTime & 0xFFFF);
3096                     host->buffers->dataLength = sizeof(ENetProtocolHeader);
3097                 } else {
3098                     host->buffers->dataLength = (size_t) &((ENetProtocolHeader *) 0)->sentTime;
3099                 }
3100 
3101                 shouldCompress = 0;
3102                 if (host->compressor.context != NULL && host->compressor.compress != NULL) {
3103                     size_t originalSize = host->packetSize - sizeof(ENetProtocolHeader),
3104                       compressedSize    = host->compressor.compress(host->compressor.context, &host->buffers[1], host->bufferCount - 1, originalSize, host->packetData[1], originalSize);
3105                     if (compressedSize > 0 && compressedSize < originalSize) {
3106                         host->headerFlags |= ENET_PROTOCOL_HEADER_FLAG_COMPRESSED;
3107                         shouldCompress     = compressedSize;
3108                         #ifdef ENET_DEBUG_COMPRESS
3109                         printf("peer %u: compressed %u->%u (%u%%)\n", currentPeer->incomingPeerID, originalSize, compressedSize, (compressedSize * 100) / originalSize);
3110                         #endif
3111                     }
3112                 }
3113 
3114                 if (currentPeer->outgoingPeerID < ENET_PROTOCOL_MAXIMUM_PEER_ID) {
3115                     host->headerFlags |= currentPeer->outgoingSessionID << ENET_PROTOCOL_HEADER_SESSION_SHIFT;
3116                 }
3117                 header->peerID = ENET_HOST_TO_NET_16(currentPeer->outgoingPeerID | host->headerFlags);
3118                 if (host->checksum != NULL) {
3119                     enet_uint32 *checksum = (enet_uint32 *) &headerData[host->buffers->dataLength];
3120                     *checksum = currentPeer->outgoingPeerID < ENET_PROTOCOL_MAXIMUM_PEER_ID ? currentPeer->connectID : 0;
3121                     host->buffers->dataLength += sizeof(enet_uint32);
3122                     *checksum = host->checksum(host->buffers, host->bufferCount);
3123                 }
3124 
3125                 if (shouldCompress > 0) {
3126                     host->buffers[1].data       = host->packetData[1];
3127                     host->buffers[1].dataLength = shouldCompress;
3128                     host->bufferCount = 2;
3129                 }
3130 
3131                 currentPeer->lastSendTime = host->serviceTime;
3132                 sentLength = enet_socket_send(host->socket, &currentPeer->address, host->buffers, host->bufferCount);
3133                 enet_protocol_remove_sent_unreliable_commands(currentPeer);
3134 
3135                 if (sentLength < 0) {
3136                     return -1;
3137                 }
3138 
3139                 host->totalSentData += sentLength;
3140                 currentPeer->totalDataSent += sentLength;
3141                 host->totalSentPackets++;
3142             }
3143 
3144         return 0;
3145     } /* enet_protocol_send_outgoing_commands */
3146 
3147     /** Sends any queued packets on the host specified to its designated peers.
3148      *
3149      *  @param host   host to flush
3150      *  @remarks this function need only be used in circumstances where one wishes to send queued packets earlier than in a call to enet_host_service().
3151      *  @ingroup host
3152      */
enet_host_flush(ENetHost * host)3153     void enet_host_flush(ENetHost *host) {
3154         host->serviceTime = enet_time_get();
3155         enet_protocol_send_outgoing_commands(host, NULL, 0);
3156     }
3157 
3158     /** Checks for any queued events on the host and dispatches one if available.
3159      *
3160      *  @param host    host to check for events
3161      *  @param event   an event structure where event details will be placed if available
3162      *  @retval > 0 if an event was dispatched
3163      *  @retval 0 if no events are available
3164      *  @retval < 0 on failure
3165      *  @ingroup host
3166      */
enet_host_check_events(ENetHost * host,ENetEvent * event)3167     int enet_host_check_events(ENetHost *host, ENetEvent *event) {
3168         if (event == NULL) { return -1; }
3169 
3170         event->type   = ENET_EVENT_TYPE_NONE;
3171         event->peer   = NULL;
3172         event->packet = NULL;
3173 
3174         return enet_protocol_dispatch_incoming_commands(host, event);
3175     }
3176 
3177     /** Waits for events on the host specified and shuttles packets between
3178      *  the host and its peers.
3179      *
3180      *  @param host    host to service
3181      *  @param event   an event structure where event details will be placed if one occurs
3182      *                 if event == NULL then no events will be delivered
3183      *  @param timeout number of milliseconds that ENet should wait for events
3184      *  @retval > 0 if an event occurred within the specified time limit
3185      *  @retval 0 if no event occurred
3186      *  @retval < 0 on failure
3187      *  @remarks enet_host_service should be called fairly regularly for adequate performance
3188      *  @ingroup host
3189      */
enet_host_service(ENetHost * host,ENetEvent * event,enet_uint32 timeout)3190     int enet_host_service(ENetHost *host, ENetEvent *event, enet_uint32 timeout) {
3191         enet_uint32 waitCondition;
3192 
3193         if (event != NULL) {
3194             event->type   = ENET_EVENT_TYPE_NONE;
3195             event->peer   = NULL;
3196             event->packet = NULL;
3197 
3198             switch (enet_protocol_dispatch_incoming_commands(host, event)) {
3199                 case 1:
3200                     return 1;
3201 
3202                 case -1:
3203                     #ifdef ENET_DEBUG
3204                     perror("Error dispatching incoming packets");
3205                     #endif
3206 
3207                     return -1;
3208 
3209                 default:
3210                     break;
3211             }
3212         }
3213 
3214         host->serviceTime = enet_time_get();
3215         timeout += host->serviceTime;
3216 
3217         do {
3218             if (ENET_TIME_DIFFERENCE(host->serviceTime, host->bandwidthThrottleEpoch) >= ENET_HOST_BANDWIDTH_THROTTLE_INTERVAL) {
3219                 enet_host_bandwidth_throttle(host);
3220             }
3221 
3222             switch (enet_protocol_send_outgoing_commands(host, event, 1)) {
3223                 case 1:
3224                     return 1;
3225 
3226                 case -1:
3227                     #ifdef ENET_DEBUG
3228                     perror("Error sending outgoing packets");
3229                     #endif
3230 
3231                     return -1;
3232 
3233                 default:
3234                     break;
3235             }
3236 
3237             switch (enet_protocol_receive_incoming_commands(host, event)) {
3238                 case 1:
3239                     return 1;
3240 
3241                 case -1:
3242                     #ifdef ENET_DEBUG
3243                     perror("Error receiving incoming packets");
3244                     #endif
3245 
3246                     return -1;
3247 
3248                 default:
3249                     break;
3250             }
3251 
3252             switch (enet_protocol_send_outgoing_commands(host, event, 1)) {
3253                 case 1:
3254                     return 1;
3255 
3256                 case -1:
3257                     #ifdef ENET_DEBUG
3258                     perror("Error sending outgoing packets");
3259                     #endif
3260 
3261                     return -1;
3262 
3263                 default:
3264                     break;
3265             }
3266 
3267             if (event != NULL) {
3268                 switch (enet_protocol_dispatch_incoming_commands(host, event)) {
3269                     case 1:
3270                         return 1;
3271 
3272                     case -1:
3273                         #ifdef ENET_DEBUG
3274                         perror("Error dispatching incoming packets");
3275                         #endif
3276 
3277                         return -1;
3278 
3279                     default:
3280                         break;
3281                 }
3282             }
3283 
3284             if (ENET_TIME_GREATER_EQUAL(host->serviceTime, timeout)) {
3285                 return 0;
3286             }
3287 
3288             do {
3289                 host->serviceTime = enet_time_get();
3290 
3291                 if (ENET_TIME_GREATER_EQUAL(host->serviceTime, timeout)) {
3292                     return 0;
3293                 }
3294 
3295                 waitCondition = ENET_SOCKET_WAIT_RECEIVE | ENET_SOCKET_WAIT_INTERRUPT;
3296                 if (enet_socket_wait(host->socket, &waitCondition, ENET_TIME_DIFFERENCE(timeout, host->serviceTime)) != 0) {
3297                     return -1;
3298                 }
3299             } while (waitCondition & ENET_SOCKET_WAIT_INTERRUPT);
3300 
3301             host->serviceTime = enet_time_get();
3302         } while (waitCondition & ENET_SOCKET_WAIT_RECEIVE);
3303 
3304         return 0;
3305     } /* enet_host_service */
3306 
3307 
3308 // =======================================================================//
3309 // !
3310 // ! Peer
3311 // !
3312 // =======================================================================//
3313 
3314     /** Configures throttle parameter for a peer.
3315      *
3316      *  Unreliable packets are dropped by ENet in response to the varying conditions
3317      *  of the Internet connection to the peer.  The throttle represents a probability
3318      *  that an unreliable packet should not be dropped and thus sent by ENet to the peer.
3319      *  The lowest mean round trip time from the sending of a reliable packet to the
3320      *  receipt of its acknowledgement is measured over an amount of time specified by
3321      *  the interval parameter in milliseconds.  If a measured round trip time happens to
3322      *  be significantly less than the mean round trip time measured over the interval,
3323      *  then the throttle probability is increased to allow more traffic by an amount
3324      *  specified in the acceleration parameter, which is a ratio to the ENET_PEER_PACKET_THROTTLE_SCALE
3325      *  constant.  If a measured round trip time happens to be significantly greater than
3326      *  the mean round trip time measured over the interval, then the throttle probability
3327      *  is decreased to limit traffic by an amount specified in the deceleration parameter, which
3328      *  is a ratio to the ENET_PEER_PACKET_THROTTLE_SCALE constant.  When the throttle has
3329      *  a value of ENET_PEER_PACKET_THROTTLE_SCALE, no unreliable packets are dropped by
3330      *  ENet, and so 100% of all unreliable packets will be sent.  When the throttle has a
3331      *  value of 0, all unreliable packets are dropped by ENet, and so 0% of all unreliable
3332      *  packets will be sent.  Intermediate values for the throttle represent intermediate
3333      *  probabilities between 0% and 100% of unreliable packets being sent.  The bandwidth
3334      *  limits of the local and foreign hosts are taken into account to determine a
3335      *  sensible limit for the throttle probability above which it should not raise even in
3336      *  the best of conditions.
3337      *
3338      *  @param peer peer to configure
3339      *  @param interval interval, in milliseconds, over which to measure lowest mean RTT; the default value is ENET_PEER_PACKET_THROTTLE_INTERVAL.
3340      *  @param acceleration rate at which to increase the throttle probability as mean RTT declines
3341      *  @param deceleration rate at which to decrease the throttle probability as mean RTT increases
3342      */
enet_peer_throttle_configure(ENetPeer * peer,enet_uint32 interval,enet_uint32 acceleration,enet_uint32 deceleration)3343     void enet_peer_throttle_configure(ENetPeer *peer, enet_uint32 interval, enet_uint32 acceleration, enet_uint32 deceleration) {
3344         ENetProtocol command;
3345 
3346         peer->packetThrottleInterval     = interval;
3347         peer->packetThrottleAcceleration = acceleration;
3348         peer->packetThrottleDeceleration = deceleration;
3349 
3350         command.header.command   = ENET_PROTOCOL_COMMAND_THROTTLE_CONFIGURE | ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE;
3351         command.header.channelID = 0xFF;
3352 
3353         command.throttleConfigure.packetThrottleInterval     = ENET_HOST_TO_NET_32(interval);
3354         command.throttleConfigure.packetThrottleAcceleration = ENET_HOST_TO_NET_32(acceleration);
3355         command.throttleConfigure.packetThrottleDeceleration = ENET_HOST_TO_NET_32(deceleration);
3356 
3357         enet_peer_queue_outgoing_command(peer, &command, NULL, 0, 0);
3358     }
3359 
enet_peer_throttle(ENetPeer * peer,enet_uint32 rtt)3360     int enet_peer_throttle(ENetPeer *peer, enet_uint32 rtt) {
3361         if (peer->lastRoundTripTime <= peer->lastRoundTripTimeVariance) {
3362             peer->packetThrottle = peer->packetThrottleLimit;
3363         }
3364         else if (rtt < peer->lastRoundTripTime) {
3365             peer->packetThrottle += peer->packetThrottleAcceleration;
3366 
3367             if (peer->packetThrottle > peer->packetThrottleLimit) {
3368                 peer->packetThrottle = peer->packetThrottleLimit;
3369             }
3370 
3371             return 1;
3372         }
3373         else if (rtt > peer->lastRoundTripTime + 2 * peer->lastRoundTripTimeVariance) {
3374             if (peer->packetThrottle > peer->packetThrottleDeceleration) {
3375                 peer->packetThrottle -= peer->packetThrottleDeceleration;
3376             } else {
3377                 peer->packetThrottle = 0;
3378             }
3379 
3380             return -1;
3381         }
3382 
3383         return 0;
3384     }
3385 
3386     /* Extended functionality for easier binding in other programming languages */
enet_host_get_peers_count(ENetHost * host)3387     enet_uint32 enet_host_get_peers_count(ENetHost *host) {
3388         return host->connectedPeers;
3389     }
3390 
enet_host_get_packets_sent(ENetHost * host)3391     enet_uint32 enet_host_get_packets_sent(ENetHost *host) {
3392         return host->totalSentPackets;
3393     }
3394 
enet_host_get_packets_received(ENetHost * host)3395     enet_uint32 enet_host_get_packets_received(ENetHost *host) {
3396         return host->totalReceivedPackets;
3397     }
3398 
enet_host_get_bytes_sent(ENetHost * host)3399     enet_uint32 enet_host_get_bytes_sent(ENetHost *host) {
3400         return host->totalSentData;
3401     }
3402 
enet_host_get_bytes_received(ENetHost * host)3403     enet_uint32 enet_host_get_bytes_received(ENetHost *host) {
3404         return host->totalReceivedData;
3405     }
3406 
3407     /** Gets received data buffer. Returns buffer length.
3408      *  @param host host to access recevie buffer
3409      *  @param data ouput parameter for recevied data
3410      *  @retval buffer length
3411      */
enet_host_get_received_data(ENetHost * host,enet_uint8 ** data)3412     enet_uint32 enet_host_get_received_data(ENetHost *host, /*out*/ enet_uint8** data) {
3413         *data = host->receivedData;
3414         return host->receivedDataLength;
3415     }
3416 
enet_host_get_mtu(ENetHost * host)3417     enet_uint32 enet_host_get_mtu(ENetHost *host) {
3418         return host->mtu;
3419     }
3420 
enet_peer_get_id(ENetPeer * peer)3421     enet_uint32 enet_peer_get_id(ENetPeer *peer) {
3422         return peer->connectID;
3423     }
3424 
enet_peer_get_ip(ENetPeer * peer,char * ip,size_t ipLength)3425     enet_uint32 enet_peer_get_ip(ENetPeer *peer, char *ip, size_t ipLength) {
3426         return enet_address_get_host_ip(&peer->address, ip, ipLength);
3427     }
3428 
enet_peer_get_port(ENetPeer * peer)3429     enet_uint16 enet_peer_get_port(ENetPeer *peer) {
3430         return peer->address.port;
3431     }
3432 
enet_peer_get_state(ENetPeer * peer)3433     ENetPeerState enet_peer_get_state(ENetPeer *peer) {
3434         return peer->state;
3435     }
3436 
enet_peer_get_rtt(ENetPeer * peer)3437     enet_uint32 enet_peer_get_rtt(ENetPeer *peer) {
3438         return peer->roundTripTime;
3439     }
3440 
enet_peer_get_packets_sent(ENetPeer * peer)3441     enet_uint64 enet_peer_get_packets_sent(ENetPeer *peer) {
3442         return peer->totalPacketsSent;
3443     }
3444 
enet_peer_get_packets_lost(ENetPeer * peer)3445     enet_uint32 enet_peer_get_packets_lost(ENetPeer *peer) {
3446         return peer->totalPacketsLost;
3447     }
3448 
enet_peer_get_bytes_sent(ENetPeer * peer)3449     enet_uint64 enet_peer_get_bytes_sent(ENetPeer *peer) {
3450         return peer->totalDataSent;
3451     }
3452 
enet_peer_get_bytes_received(ENetPeer * peer)3453     enet_uint64 enet_peer_get_bytes_received(ENetPeer *peer) {
3454         return peer->totalDataReceived;
3455     }
3456 
enet_peer_get_data(ENetPeer * peer)3457     void * enet_peer_get_data(ENetPeer *peer) {
3458         return (void *) peer->data;
3459     }
3460 
enet_peer_set_data(ENetPeer * peer,void * data)3461     void enet_peer_set_data(ENetPeer *peer, void *data) {
3462         peer->data = (enet_uint32 *) data;
3463     }
3464 
enet_packet_get_data(ENetPacket * packet)3465     void * enet_packet_get_data(ENetPacket *packet) {
3466         return (void *) packet->data;
3467     }
3468 
enet_packet_get_length(ENetPacket * packet)3469     enet_uint32 enet_packet_get_length(ENetPacket *packet) {
3470         return packet->dataLength;
3471     }
3472 
enet_packet_set_free_callback(ENetPacket * packet,void * callback)3473     void enet_packet_set_free_callback(ENetPacket *packet, void *callback) {
3474         packet->freeCallback = (ENetPacketFreeCallback)callback;
3475     }
3476 
3477     /** Queues a packet to be sent.
3478      *  @param peer destination for the packet
3479      *  @param channelID channel on which to send
3480      *  @param packet packet to send
3481      *  @retval 0 on success
3482      *  @retval < 0 on failure
3483      */
enet_peer_send(ENetPeer * peer,enet_uint8 channelID,ENetPacket * packet)3484     int enet_peer_send(ENetPeer *peer, enet_uint8 channelID, ENetPacket *packet) {
3485         ENetChannel *channel = &peer->channels[channelID];
3486         ENetProtocol command;
3487         size_t fragmentLength;
3488 
3489         if (peer->state != ENET_PEER_STATE_CONNECTED || channelID >= peer->channelCount || packet->dataLength > peer->host->maximumPacketSize) {
3490             return -1;
3491         }
3492 
3493         fragmentLength = peer->mtu - sizeof(ENetProtocolHeader) - sizeof(ENetProtocolSendFragment);
3494         if (peer->host->checksum != NULL) {
3495             fragmentLength -= sizeof(enet_uint32);
3496         }
3497 
3498         if (packet->dataLength > fragmentLength) {
3499             enet_uint32 fragmentCount = (packet->dataLength + fragmentLength - 1) / fragmentLength, fragmentNumber, fragmentOffset;
3500             enet_uint8 commandNumber;
3501             enet_uint16 startSequenceNumber;
3502             ENetList fragments;
3503             ENetOutgoingCommand *fragment;
3504 
3505             if (fragmentCount > ENET_PROTOCOL_MAXIMUM_FRAGMENT_COUNT) {
3506                 return -1;
3507             }
3508 
3509             if ((packet->flags & (ENET_PACKET_FLAG_RELIABLE | ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT)) ==
3510                 ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT &&
3511                 channel->outgoingUnreliableSequenceNumber < 0xFFFF)
3512             {
3513                 commandNumber       = ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE_FRAGMENT;
3514                 startSequenceNumber = ENET_HOST_TO_NET_16(channel->outgoingUnreliableSequenceNumber + 1);
3515             } else {
3516                 commandNumber       = ENET_PROTOCOL_COMMAND_SEND_FRAGMENT | ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE;
3517                 startSequenceNumber = ENET_HOST_TO_NET_16(channel->outgoingReliableSequenceNumber + 1);
3518             }
3519 
3520             enet_list_clear(&fragments);
3521 
3522             for (fragmentNumber = 0, fragmentOffset = 0; fragmentOffset < packet->dataLength; ++fragmentNumber, fragmentOffset += fragmentLength) {
3523                 if (packet->dataLength - fragmentOffset < fragmentLength) {
3524                     fragmentLength = packet->dataLength - fragmentOffset;
3525                 }
3526 
3527                 fragment = (ENetOutgoingCommand *) enet_malloc(sizeof(ENetOutgoingCommand));
3528 
3529                 if (fragment == NULL) {
3530                     while (!enet_list_empty(&fragments)) {
3531                         fragment = (ENetOutgoingCommand *) enet_list_remove(enet_list_begin(&fragments));
3532 
3533                         enet_free(fragment);
3534                     }
3535 
3536                     return -1;
3537                 }
3538 
3539                 fragment->fragmentOffset           = fragmentOffset;
3540                 fragment->fragmentLength           = fragmentLength;
3541                 fragment->packet                   = packet;
3542                 fragment->command.header.command   = commandNumber;
3543                 fragment->command.header.channelID = channelID;
3544 
3545                 fragment->command.sendFragment.startSequenceNumber = startSequenceNumber;
3546 
3547                 fragment->command.sendFragment.dataLength     = ENET_HOST_TO_NET_16(fragmentLength);
3548                 fragment->command.sendFragment.fragmentCount  = ENET_HOST_TO_NET_32(fragmentCount);
3549                 fragment->command.sendFragment.fragmentNumber = ENET_HOST_TO_NET_32(fragmentNumber);
3550                 fragment->command.sendFragment.totalLength    = ENET_HOST_TO_NET_32(packet->dataLength);
3551                 fragment->command.sendFragment.fragmentOffset = ENET_NET_TO_HOST_32(fragmentOffset);
3552 
3553                 enet_list_insert(enet_list_end(&fragments), fragment);
3554             }
3555 
3556             packet->referenceCount += fragmentNumber;
3557 
3558             while (!enet_list_empty(&fragments)) {
3559                 fragment = (ENetOutgoingCommand *) enet_list_remove(enet_list_begin(&fragments));
3560                 enet_peer_setup_outgoing_command(peer, fragment);
3561             }
3562 
3563             return 0;
3564         }
3565 
3566         command.header.channelID = channelID;
3567 
3568         if ((packet->flags & (ENET_PACKET_FLAG_RELIABLE | ENET_PACKET_FLAG_UNSEQUENCED)) == ENET_PACKET_FLAG_UNSEQUENCED) {
3569             command.header.command = ENET_PROTOCOL_COMMAND_SEND_UNSEQUENCED | ENET_PROTOCOL_COMMAND_FLAG_UNSEQUENCED;
3570             command.sendUnsequenced.dataLength = ENET_HOST_TO_NET_16(packet->dataLength);
3571         }
3572         else if (packet->flags & ENET_PACKET_FLAG_RELIABLE || channel->outgoingUnreliableSequenceNumber >= 0xFFFF) {
3573             command.header.command = ENET_PROTOCOL_COMMAND_SEND_RELIABLE | ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE;
3574             command.sendReliable.dataLength = ENET_HOST_TO_NET_16(packet->dataLength);
3575         }
3576         else {
3577             command.header.command = ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE;
3578             command.sendUnreliable.dataLength = ENET_HOST_TO_NET_16(packet->dataLength);
3579         }
3580 
3581         if (enet_peer_queue_outgoing_command(peer, &command, packet, 0, packet->dataLength) == NULL) {
3582             return -1;
3583         }
3584 
3585         return 0;
3586     } // enet_peer_send
3587 
3588     /** Attempts to dequeue any incoming queued packet.
3589      *  @param peer peer to dequeue packets from
3590      *  @param channelID holds the channel ID of the channel the packet was received on success
3591      *  @returns a pointer to the packet, or NULL if there are no available incoming queued packets
3592      */
enet_peer_receive(ENetPeer * peer,enet_uint8 * channelID)3593     ENetPacket * enet_peer_receive(ENetPeer *peer, enet_uint8 *channelID) {
3594         ENetIncomingCommand *incomingCommand;
3595         ENetPacket *packet;
3596 
3597         if (enet_list_empty(&peer->dispatchedCommands)) {
3598             return NULL;
3599         }
3600 
3601         incomingCommand = (ENetIncomingCommand *) enet_list_remove(enet_list_begin(&peer->dispatchedCommands));
3602 
3603         if (channelID != NULL) {
3604             *channelID = incomingCommand->command.header.channelID;
3605         }
3606 
3607         packet = incomingCommand->packet;
3608         --packet->referenceCount;
3609 
3610         if (incomingCommand->fragments != NULL) {
3611             enet_free(incomingCommand->fragments);
3612         }
3613 
3614         enet_free(incomingCommand);
3615         peer->totalWaitingData -= packet->dataLength;
3616 
3617         return packet;
3618     }
3619 
enet_peer_reset_outgoing_commands(ENetList * queue)3620     static void enet_peer_reset_outgoing_commands(ENetList *queue) {
3621         ENetOutgoingCommand *outgoingCommand;
3622 
3623         while (!enet_list_empty(queue)) {
3624             outgoingCommand = (ENetOutgoingCommand *) enet_list_remove(enet_list_begin(queue));
3625 
3626             if (outgoingCommand->packet != NULL) {
3627                 --outgoingCommand->packet->referenceCount;
3628 
3629                 if (outgoingCommand->packet->referenceCount == 0) {
3630                     enet_packet_destroy(outgoingCommand->packet);
3631                 }
3632             }
3633 
3634             enet_free(outgoingCommand);
3635         }
3636     }
3637 
enet_peer_remove_incoming_commands(ENetList * queue,ENetListIterator startCommand,ENetListIterator endCommand)3638     static void enet_peer_remove_incoming_commands(ENetList *queue, ENetListIterator startCommand, ENetListIterator endCommand) {
3639         UNREFERENCED_PARAMETER(queue);
3640         ENetListIterator currentCommand;
3641 
3642         for (currentCommand = startCommand; currentCommand != endCommand;) {
3643             ENetIncomingCommand *incomingCommand = (ENetIncomingCommand *) currentCommand;
3644 
3645             currentCommand = enet_list_next(currentCommand);
3646             enet_list_remove(&incomingCommand->incomingCommandList);
3647 
3648             if (incomingCommand->packet != NULL) {
3649                 --incomingCommand->packet->referenceCount;
3650 
3651                 if (incomingCommand->packet->referenceCount == 0) {
3652                     enet_packet_destroy(incomingCommand->packet);
3653                 }
3654             }
3655 
3656             if (incomingCommand->fragments != NULL) {
3657                 enet_free(incomingCommand->fragments);
3658             }
3659 
3660             enet_free(incomingCommand);
3661         }
3662     }
3663 
enet_peer_reset_incoming_commands(ENetList * queue)3664     static void enet_peer_reset_incoming_commands(ENetList *queue) {
3665         enet_peer_remove_incoming_commands(queue, enet_list_begin(queue), enet_list_end(queue));
3666     }
3667 
enet_peer_reset_queues(ENetPeer * peer)3668     void enet_peer_reset_queues(ENetPeer *peer) {
3669         ENetChannel *channel;
3670 
3671         if (peer->needsDispatch) {
3672             enet_list_remove(&peer->dispatchList);
3673             peer->needsDispatch = 0;
3674         }
3675 
3676         while (!enet_list_empty(&peer->acknowledgements)) {
3677             enet_free(enet_list_remove(enet_list_begin(&peer->acknowledgements)));
3678         }
3679 
3680         enet_peer_reset_outgoing_commands(&peer->sentReliableCommands);
3681         enet_peer_reset_outgoing_commands(&peer->sentUnreliableCommands);
3682         enet_peer_reset_outgoing_commands(&peer->outgoingReliableCommands);
3683         enet_peer_reset_outgoing_commands(&peer->outgoingUnreliableCommands);
3684         enet_peer_reset_incoming_commands(&peer->dispatchedCommands);
3685 
3686         if (peer->channels != NULL && peer->channelCount > 0) {
3687             for (channel = peer->channels; channel < &peer->channels[peer->channelCount]; ++channel) {
3688                 enet_peer_reset_incoming_commands(&channel->incomingReliableCommands);
3689                 enet_peer_reset_incoming_commands(&channel->incomingUnreliableCommands);
3690             }
3691 
3692             enet_free(peer->channels);
3693         }
3694 
3695         peer->channels     = NULL;
3696         peer->channelCount = 0;
3697     }
3698 
enet_peer_on_connect(ENetPeer * peer)3699     void enet_peer_on_connect(ENetPeer *peer) {
3700         if (peer->state != ENET_PEER_STATE_CONNECTED && peer->state != ENET_PEER_STATE_DISCONNECT_LATER) {
3701             if (peer->incomingBandwidth != 0) {
3702                 ++peer->host->bandwidthLimitedPeers;
3703             }
3704 
3705             ++peer->host->connectedPeers;
3706         }
3707     }
3708 
enet_peer_on_disconnect(ENetPeer * peer)3709     void enet_peer_on_disconnect(ENetPeer *peer) {
3710         if (peer->state == ENET_PEER_STATE_CONNECTED || peer->state == ENET_PEER_STATE_DISCONNECT_LATER) {
3711             if (peer->incomingBandwidth != 0) {
3712                 --peer->host->bandwidthLimitedPeers;
3713             }
3714 
3715             --peer->host->connectedPeers;
3716         }
3717     }
3718 
3719     /** Forcefully disconnects a peer.
3720      *  @param peer peer to forcefully disconnect
3721      *  @remarks The foreign host represented by the peer is not notified of the disconnection and will timeout
3722      *  on its connection to the local host.
3723      */
enet_peer_reset(ENetPeer * peer)3724     void enet_peer_reset(ENetPeer *peer) {
3725         enet_peer_on_disconnect(peer);
3726 
3727         // We don't want to reset connectID here, otherwise, we can't get it in the Disconnect event
3728         // peer->connectID                     = 0;
3729         peer->outgoingPeerID                = ENET_PROTOCOL_MAXIMUM_PEER_ID;
3730         peer->state                         = ENET_PEER_STATE_DISCONNECTED;
3731         peer->incomingBandwidth             = 0;
3732         peer->outgoingBandwidth             = 0;
3733         peer->incomingBandwidthThrottleEpoch = 0;
3734         peer->outgoingBandwidthThrottleEpoch = 0;
3735         peer->incomingDataTotal             = 0;
3736         peer->totalDataReceived             = 0;
3737         peer->outgoingDataTotal             = 0;
3738         peer->totalDataSent                 = 0;
3739         peer->lastSendTime                  = 0;
3740         peer->lastReceiveTime               = 0;
3741         peer->nextTimeout                   = 0;
3742         peer->earliestTimeout               = 0;
3743         peer->packetLossEpoch               = 0;
3744         peer->packetsSent                   = 0;
3745         peer->totalPacketsSent              = 0;
3746         peer->packetsLost                   = 0;
3747         peer->totalPacketsLost              = 0;
3748         peer->packetLoss                    = 0;
3749         peer->packetLossVariance            = 0;
3750         peer->packetThrottle                = ENET_PEER_DEFAULT_PACKET_THROTTLE;
3751         peer->packetThrottleLimit           = ENET_PEER_PACKET_THROTTLE_SCALE;
3752         peer->packetThrottleCounter         = 0;
3753         peer->packetThrottleEpoch           = 0;
3754         peer->packetThrottleAcceleration    = ENET_PEER_PACKET_THROTTLE_ACCELERATION;
3755         peer->packetThrottleDeceleration    = ENET_PEER_PACKET_THROTTLE_DECELERATION;
3756         peer->packetThrottleInterval        = ENET_PEER_PACKET_THROTTLE_INTERVAL;
3757         peer->pingInterval                  = ENET_PEER_PING_INTERVAL;
3758         peer->timeoutLimit                  = ENET_PEER_TIMEOUT_LIMIT;
3759         peer->timeoutMinimum                = ENET_PEER_TIMEOUT_MINIMUM;
3760         peer->timeoutMaximum                = ENET_PEER_TIMEOUT_MAXIMUM;
3761         peer->lastRoundTripTime             = ENET_PEER_DEFAULT_ROUND_TRIP_TIME;
3762         peer->lowestRoundTripTime           = ENET_PEER_DEFAULT_ROUND_TRIP_TIME;
3763         peer->lastRoundTripTimeVariance     = 0;
3764         peer->highestRoundTripTimeVariance  = 0;
3765         peer->roundTripTime                 = ENET_PEER_DEFAULT_ROUND_TRIP_TIME;
3766         peer->roundTripTimeVariance         = 0;
3767         peer->mtu                           = peer->host->mtu;
3768         peer->reliableDataInTransit         = 0;
3769         peer->outgoingReliableSequenceNumber = 0;
3770         peer->windowSize                    = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE;
3771         peer->incomingUnsequencedGroup      = 0;
3772         peer->outgoingUnsequencedGroup      = 0;
3773         peer->eventData                     = 0;
3774         peer->totalWaitingData              = 0;
3775 
3776         memset(peer->unsequencedWindow, 0, sizeof(peer->unsequencedWindow));
3777         enet_peer_reset_queues(peer);
3778     }
3779 
3780     /** Sends a ping request to a peer.
3781      *  @param peer destination for the ping request
3782      *  @remarks ping requests factor into the mean round trip time as designated by the
3783      *  roundTripTime field in the ENetPeer structure.  ENet automatically pings all connected
3784      *  peers at regular intervals, however, this function may be called to ensure more
3785      *  frequent ping requests.
3786      */
enet_peer_ping(ENetPeer * peer)3787     void enet_peer_ping(ENetPeer *peer) {
3788         ENetProtocol command;
3789 
3790         if (peer->state != ENET_PEER_STATE_CONNECTED) {
3791             return;
3792         }
3793 
3794         command.header.command   = ENET_PROTOCOL_COMMAND_PING | ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE;
3795         command.header.channelID = 0xFF;
3796 
3797         enet_peer_queue_outgoing_command(peer, &command, NULL, 0, 0);
3798     }
3799 
3800     /** Sets the interval at which pings will be sent to a peer.
3801      *
3802      *  Pings are used both to monitor the liveness of the connection and also to dynamically
3803      *  adjust the throttle during periods of low traffic so that the throttle has reasonable
3804      *  responsiveness during traffic spikes.
3805      *
3806      *  @param peer the peer to adjust
3807      *  @param pingInterval the interval at which to send pings; defaults to ENET_PEER_PING_INTERVAL if 0
3808      */
enet_peer_ping_interval(ENetPeer * peer,enet_uint32 pingInterval)3809     void enet_peer_ping_interval(ENetPeer *peer, enet_uint32 pingInterval) {
3810         peer->pingInterval = pingInterval ? pingInterval : (int)ENET_PEER_PING_INTERVAL;
3811     }
3812 
3813     /** Sets the timeout parameters for a peer.
3814      *
3815      *  The timeout parameter control how and when a peer will timeout from a failure to acknowledge
3816      *  reliable traffic. Timeout values use an exponential backoff mechanism, where if a reliable
3817      *  packet is not acknowledge within some multiple of the average RTT plus a variance tolerance,
3818      *  the timeout will be doubled until it reaches a set limit. If the timeout is thus at this
3819      *  limit and reliable packets have been sent but not acknowledged within a certain minimum time
3820      *  period, the peer will be disconnected. Alternatively, if reliable packets have been sent
3821      *  but not acknowledged for a certain maximum time period, the peer will be disconnected regardless
3822      *  of the current timeout limit value.
3823      *
3824      *  @param peer the peer to adjust
3825      *  @param timeoutLimit the timeout limit; defaults to ENET_PEER_TIMEOUT_LIMIT if 0
3826      *  @param timeoutMinimum the timeout minimum; defaults to ENET_PEER_TIMEOUT_MINIMUM if 0
3827      *  @param timeoutMaximum the timeout maximum; defaults to ENET_PEER_TIMEOUT_MAXIMUM if 0
3828      */
3829 
enet_peer_timeout(ENetPeer * peer,enet_uint32 timeoutLimit,enet_uint32 timeoutMinimum,enet_uint32 timeoutMaximum)3830     void enet_peer_timeout(ENetPeer *peer, enet_uint32 timeoutLimit, enet_uint32 timeoutMinimum, enet_uint32 timeoutMaximum) {
3831         peer->timeoutLimit   = timeoutLimit ? timeoutLimit : (int)ENET_PEER_TIMEOUT_LIMIT;
3832         peer->timeoutMinimum = timeoutMinimum ? timeoutMinimum : (int)ENET_PEER_TIMEOUT_MINIMUM;
3833         peer->timeoutMaximum = timeoutMaximum ? timeoutMaximum : (int)ENET_PEER_TIMEOUT_MAXIMUM;
3834     }
3835 
3836     /** Force an immediate disconnection from a peer.
3837      *  @param peer peer to disconnect
3838      *  @param data data describing the disconnection
3839      *  @remarks No ENET_EVENT_DISCONNECT event will be generated. The foreign peer is not
3840      *  guaranteed to receive the disconnect notification, and is reset immediately upon
3841      *  return from this function.
3842      */
enet_peer_disconnect_now(ENetPeer * peer,enet_uint32 data)3843     void enet_peer_disconnect_now(ENetPeer *peer, enet_uint32 data) {
3844         ENetProtocol command;
3845 
3846         if (peer->state == ENET_PEER_STATE_DISCONNECTED) {
3847             return;
3848         }
3849 
3850         if (peer->state != ENET_PEER_STATE_ZOMBIE && peer->state != ENET_PEER_STATE_DISCONNECTING) {
3851             enet_peer_reset_queues(peer);
3852 
3853             command.header.command   = ENET_PROTOCOL_COMMAND_DISCONNECT | ENET_PROTOCOL_COMMAND_FLAG_UNSEQUENCED;
3854             command.header.channelID = 0xFF;
3855             command.disconnect.data  = ENET_HOST_TO_NET_32(data);
3856 
3857             enet_peer_queue_outgoing_command(peer, &command, NULL, 0, 0);
3858             enet_host_flush(peer->host);
3859         }
3860 
3861         enet_peer_reset(peer);
3862     }
3863 
3864     /** Request a disconnection from a peer.
3865      *  @param peer peer to request a disconnection
3866      *  @param data data describing the disconnection
3867      *  @remarks An ENET_EVENT_DISCONNECT event will be generated by enet_host_service()
3868      *  once the disconnection is complete.
3869      */
enet_peer_disconnect(ENetPeer * peer,enet_uint32 data)3870     void enet_peer_disconnect(ENetPeer *peer, enet_uint32 data) {
3871         ENetProtocol command;
3872 
3873         if (peer->state == ENET_PEER_STATE_DISCONNECTING ||
3874             peer->state == ENET_PEER_STATE_DISCONNECTED ||
3875             peer->state == ENET_PEER_STATE_ACKNOWLEDGING_DISCONNECT ||
3876             peer->state == ENET_PEER_STATE_ZOMBIE
3877         ) {
3878             return;
3879         }
3880 
3881         enet_peer_reset_queues(peer);
3882 
3883         command.header.command   = ENET_PROTOCOL_COMMAND_DISCONNECT;
3884         command.header.channelID = 0xFF;
3885         command.disconnect.data  = ENET_HOST_TO_NET_32(data);
3886 
3887         if (peer->state == ENET_PEER_STATE_CONNECTED || peer->state == ENET_PEER_STATE_DISCONNECT_LATER) {
3888             command.header.command |= ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE;
3889         } else {
3890             command.header.command |= ENET_PROTOCOL_COMMAND_FLAG_UNSEQUENCED;
3891         }
3892 
3893         enet_peer_queue_outgoing_command(peer, &command, NULL, 0, 0);
3894 
3895         if (peer->state == ENET_PEER_STATE_CONNECTED || peer->state == ENET_PEER_STATE_DISCONNECT_LATER) {
3896             enet_peer_on_disconnect(peer);
3897 
3898             peer->state = ENET_PEER_STATE_DISCONNECTING;
3899         } else {
3900             enet_host_flush(peer->host);
3901             enet_peer_reset(peer);
3902         }
3903     }
3904 
3905     /** Request a disconnection from a peer, but only after all queued outgoing packets are sent.
3906      *  @param peer peer to request a disconnection
3907      *  @param data data describing the disconnection
3908      *  @remarks An ENET_EVENT_DISCONNECT event will be generated by enet_host_service()
3909      *  once the disconnection is complete.
3910      */
enet_peer_disconnect_later(ENetPeer * peer,enet_uint32 data)3911     void enet_peer_disconnect_later(ENetPeer *peer, enet_uint32 data) {
3912         if ((peer->state == ENET_PEER_STATE_CONNECTED || peer->state == ENET_PEER_STATE_DISCONNECT_LATER) &&
3913             !(enet_list_empty(&peer->outgoingReliableCommands) &&
3914             enet_list_empty(&peer->outgoingUnreliableCommands) &&
3915             enet_list_empty(&peer->sentReliableCommands))
3916         ) {
3917             peer->state     = ENET_PEER_STATE_DISCONNECT_LATER;
3918             peer->eventData = data;
3919         } else {
3920             enet_peer_disconnect(peer, data);
3921         }
3922     }
3923 
enet_peer_queue_acknowledgement(ENetPeer * peer,const ENetProtocol * command,enet_uint16 sentTime)3924     ENetAcknowledgement *enet_peer_queue_acknowledgement(ENetPeer *peer, const ENetProtocol *command, enet_uint16 sentTime) {
3925         ENetAcknowledgement *acknowledgement;
3926 
3927         if (command->header.channelID < peer->channelCount) {
3928             ENetChannel *channel       = &peer->channels[command->header.channelID];
3929             enet_uint16 reliableWindow = command->header.reliableSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE;
3930             enet_uint16 currentWindow  = channel->incomingReliableSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE;
3931 
3932             if (command->header.reliableSequenceNumber < channel->incomingReliableSequenceNumber) {
3933                 reliableWindow += ENET_PEER_RELIABLE_WINDOWS;
3934             }
3935 
3936             if (reliableWindow >= currentWindow + ENET_PEER_FREE_RELIABLE_WINDOWS - 1 && reliableWindow <= currentWindow + ENET_PEER_FREE_RELIABLE_WINDOWS) {
3937                 return NULL;
3938             }
3939         }
3940 
3941         acknowledgement = (ENetAcknowledgement *) enet_malloc(sizeof(ENetAcknowledgement));
3942         if (acknowledgement == NULL) {
3943             return NULL;
3944         }
3945 
3946         peer->outgoingDataTotal += sizeof(ENetProtocolAcknowledge);
3947 
3948         acknowledgement->sentTime = sentTime;
3949         acknowledgement->command  = *command;
3950 
3951         enet_list_insert(enet_list_end(&peer->acknowledgements), acknowledgement);
3952         return acknowledgement;
3953     }
3954 
enet_peer_setup_outgoing_command(ENetPeer * peer,ENetOutgoingCommand * outgoingCommand)3955     void enet_peer_setup_outgoing_command(ENetPeer *peer, ENetOutgoingCommand *outgoingCommand) {
3956         ENetChannel *channel = &peer->channels[outgoingCommand->command.header.channelID];
3957         peer->outgoingDataTotal += enet_protocol_command_size(outgoingCommand->command.header.command) + outgoingCommand->fragmentLength;
3958 
3959         if (outgoingCommand->command.header.channelID == 0xFF) {
3960             ++peer->outgoingReliableSequenceNumber;
3961 
3962             outgoingCommand->reliableSequenceNumber   = peer->outgoingReliableSequenceNumber;
3963             outgoingCommand->unreliableSequenceNumber = 0;
3964         }
3965         else if (outgoingCommand->command.header.command & ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE) {
3966             ++channel->outgoingReliableSequenceNumber;
3967             channel->outgoingUnreliableSequenceNumber = 0;
3968 
3969             outgoingCommand->reliableSequenceNumber   = channel->outgoingReliableSequenceNumber;
3970             outgoingCommand->unreliableSequenceNumber = 0;
3971         }
3972         else if (outgoingCommand->command.header.command & ENET_PROTOCOL_COMMAND_FLAG_UNSEQUENCED) {
3973             ++peer->outgoingUnsequencedGroup;
3974 
3975             outgoingCommand->reliableSequenceNumber   = 0;
3976             outgoingCommand->unreliableSequenceNumber = 0;
3977         }
3978         else {
3979             if (outgoingCommand->fragmentOffset == 0) {
3980                 ++channel->outgoingUnreliableSequenceNumber;
3981             }
3982 
3983             outgoingCommand->reliableSequenceNumber   = channel->outgoingReliableSequenceNumber;
3984             outgoingCommand->unreliableSequenceNumber = channel->outgoingUnreliableSequenceNumber;
3985         }
3986 
3987         outgoingCommand->sendAttempts          = 0;
3988         outgoingCommand->sentTime              = 0;
3989         outgoingCommand->roundTripTimeout      = 0;
3990         outgoingCommand->roundTripTimeoutLimit = 0;
3991         outgoingCommand->command.header.reliableSequenceNumber = ENET_HOST_TO_NET_16(outgoingCommand->reliableSequenceNumber);
3992 
3993         switch (outgoingCommand->command.header.command & ENET_PROTOCOL_COMMAND_MASK) {
3994             case ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE:
3995                 outgoingCommand->command.sendUnreliable.unreliableSequenceNumber = ENET_HOST_TO_NET_16(outgoingCommand->unreliableSequenceNumber);
3996                 break;
3997 
3998             case ENET_PROTOCOL_COMMAND_SEND_UNSEQUENCED:
3999                 outgoingCommand->command.sendUnsequenced.unsequencedGroup = ENET_HOST_TO_NET_16(peer->outgoingUnsequencedGroup);
4000                 break;
4001 
4002             default:
4003                 break;
4004         }
4005 
4006         if (outgoingCommand->command.header.command & ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE) {
4007             enet_list_insert(enet_list_end(&peer->outgoingReliableCommands), outgoingCommand);
4008         } else {
4009             enet_list_insert(enet_list_end(&peer->outgoingUnreliableCommands), outgoingCommand);
4010         }
4011     }
4012 
enet_peer_queue_outgoing_command(ENetPeer * peer,const ENetProtocol * command,ENetPacket * packet,enet_uint32 offset,enet_uint16 length)4013     ENetOutgoingCommand * enet_peer_queue_outgoing_command(ENetPeer *peer, const ENetProtocol *command, ENetPacket *packet, enet_uint32 offset, enet_uint16 length) {
4014         ENetOutgoingCommand *outgoingCommand = (ENetOutgoingCommand *) enet_malloc(sizeof(ENetOutgoingCommand));
4015 
4016         if (outgoingCommand == NULL) {
4017             return NULL;
4018         }
4019 
4020         outgoingCommand->command        = *command;
4021         outgoingCommand->fragmentOffset = offset;
4022         outgoingCommand->fragmentLength = length;
4023         outgoingCommand->packet         = packet;
4024         if (packet != NULL) {
4025             ++packet->referenceCount;
4026         }
4027 
4028         enet_peer_setup_outgoing_command(peer, outgoingCommand);
4029         return outgoingCommand;
4030     }
4031 
enet_peer_dispatch_incoming_unreliable_commands(ENetPeer * peer,ENetChannel * channel)4032     void enet_peer_dispatch_incoming_unreliable_commands(ENetPeer *peer, ENetChannel *channel) {
4033         ENetListIterator droppedCommand, startCommand, currentCommand;
4034 
4035         for (droppedCommand = startCommand = currentCommand = enet_list_begin(&channel->incomingUnreliableCommands);
4036             currentCommand != enet_list_end(&channel->incomingUnreliableCommands);
4037             currentCommand = enet_list_next(currentCommand)
4038         ) {
4039             ENetIncomingCommand *incomingCommand = (ENetIncomingCommand *) currentCommand;
4040 
4041             if ((incomingCommand->command.header.command & ENET_PROTOCOL_COMMAND_MASK) == ENET_PROTOCOL_COMMAND_SEND_UNSEQUENCED) {
4042                 continue;
4043             }
4044 
4045             if (incomingCommand->reliableSequenceNumber == channel->incomingReliableSequenceNumber) {
4046                 if (incomingCommand->fragmentsRemaining <= 0) {
4047                     channel->incomingUnreliableSequenceNumber = incomingCommand->unreliableSequenceNumber;
4048                     continue;
4049                 }
4050 
4051                 if (startCommand != currentCommand) {
4052                     enet_list_move(enet_list_end(&peer->dispatchedCommands), startCommand, enet_list_previous(currentCommand));
4053 
4054                     if (!peer->needsDispatch) {
4055                         enet_list_insert(enet_list_end(&peer->host->dispatchQueue), &peer->dispatchList);
4056                         peer->needsDispatch = 1;
4057                     }
4058 
4059                     droppedCommand = currentCommand;
4060                 } else if (droppedCommand != currentCommand) {
4061                     droppedCommand = enet_list_previous(currentCommand);
4062                 }
4063             } else {
4064                 enet_uint16 reliableWindow = incomingCommand->reliableSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE;
4065                 enet_uint16 currentWindow  = channel->incomingReliableSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE;
4066 
4067                 if (incomingCommand->reliableSequenceNumber < channel->incomingReliableSequenceNumber) {
4068                     reliableWindow += ENET_PEER_RELIABLE_WINDOWS;
4069                 }
4070 
4071                 if (reliableWindow >= currentWindow && reliableWindow < currentWindow + ENET_PEER_FREE_RELIABLE_WINDOWS - 1) {
4072                     break;
4073                 }
4074 
4075                 droppedCommand = enet_list_next(currentCommand);
4076 
4077                 if (startCommand != currentCommand) {
4078                     enet_list_move(enet_list_end(&peer->dispatchedCommands), startCommand, enet_list_previous(currentCommand));
4079 
4080                     if (!peer->needsDispatch) {
4081                         enet_list_insert(enet_list_end(&peer->host->dispatchQueue), &peer->dispatchList);
4082                         peer->needsDispatch = 1;
4083                     }
4084                 }
4085             }
4086 
4087             startCommand = enet_list_next(currentCommand);
4088         }
4089 
4090         if (startCommand != currentCommand) {
4091             enet_list_move(enet_list_end(&peer->dispatchedCommands), startCommand, enet_list_previous(currentCommand));
4092 
4093             if (!peer->needsDispatch) {
4094                 enet_list_insert(enet_list_end(&peer->host->dispatchQueue), &peer->dispatchList);
4095                 peer->needsDispatch = 1;
4096             }
4097 
4098             droppedCommand = currentCommand;
4099         }
4100 
4101         enet_peer_remove_incoming_commands(&channel->incomingUnreliableCommands,enet_list_begin(&channel->incomingUnreliableCommands), droppedCommand);
4102     }
4103 
enet_peer_dispatch_incoming_reliable_commands(ENetPeer * peer,ENetChannel * channel)4104     void enet_peer_dispatch_incoming_reliable_commands(ENetPeer *peer, ENetChannel *channel) {
4105         ENetListIterator currentCommand;
4106 
4107         for (currentCommand = enet_list_begin(&channel->incomingReliableCommands);
4108             currentCommand != enet_list_end(&channel->incomingReliableCommands);
4109             currentCommand = enet_list_next(currentCommand)
4110         ) {
4111             ENetIncomingCommand *incomingCommand = (ENetIncomingCommand *) currentCommand;
4112 
4113             if (incomingCommand->fragmentsRemaining > 0 || incomingCommand->reliableSequenceNumber != (enet_uint16) (channel->incomingReliableSequenceNumber + 1)) {
4114                 break;
4115             }
4116 
4117             channel->incomingReliableSequenceNumber = incomingCommand->reliableSequenceNumber;
4118 
4119             if (incomingCommand->fragmentCount > 0) {
4120                 channel->incomingReliableSequenceNumber += incomingCommand->fragmentCount - 1;
4121             }
4122         }
4123 
4124         if (currentCommand == enet_list_begin(&channel->incomingReliableCommands)) {
4125             return;
4126         }
4127 
4128         channel->incomingUnreliableSequenceNumber = 0;
4129         enet_list_move(enet_list_end(&peer->dispatchedCommands), enet_list_begin(&channel->incomingReliableCommands), enet_list_previous(currentCommand));
4130 
4131         if (!peer->needsDispatch) {
4132             enet_list_insert(enet_list_end(&peer->host->dispatchQueue), &peer->dispatchList);
4133             peer->needsDispatch = 1;
4134         }
4135 
4136         if (!enet_list_empty(&channel->incomingUnreliableCommands)) {
4137             enet_peer_dispatch_incoming_unreliable_commands(peer, channel);
4138         }
4139     }
4140 
enet_peer_queue_incoming_command(ENetPeer * peer,const ENetProtocol * command,void * data,size_t dataLength,enet_uint32 flags,enet_uint32 fragmentCount)4141     ENetIncomingCommand * enet_peer_queue_incoming_command(ENetPeer *peer, const ENetProtocol *command, void *data, size_t dataLength, enet_uint32 flags, enet_uint32 fragmentCount) {
4142         static ENetIncomingCommand dummyCommand;
4143 
4144         ENetChannel *channel = &peer->channels[command->header.channelID];
4145         enet_uint32 unreliableSequenceNumber = 0, reliableSequenceNumber = 0;
4146         enet_uint16 reliableWindow, currentWindow;
4147         ENetIncomingCommand *incomingCommand;
4148         ENetListIterator currentCommand;
4149         ENetPacket *packet = NULL;
4150 
4151         if (peer->state == ENET_PEER_STATE_DISCONNECT_LATER) {
4152             goto discardCommand;
4153         }
4154 
4155         if ((command->header.command & ENET_PROTOCOL_COMMAND_MASK) != ENET_PROTOCOL_COMMAND_SEND_UNSEQUENCED) {
4156             reliableSequenceNumber = command->header.reliableSequenceNumber;
4157             reliableWindow         = reliableSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE;
4158             currentWindow = channel->incomingReliableSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE;
4159 
4160             if (reliableSequenceNumber < channel->incomingReliableSequenceNumber) {
4161                 reliableWindow += ENET_PEER_RELIABLE_WINDOWS;
4162             }
4163 
4164             if (reliableWindow < currentWindow || reliableWindow >= currentWindow + ENET_PEER_FREE_RELIABLE_WINDOWS - 1) {
4165                 goto discardCommand;
4166             }
4167         }
4168 
4169         switch (command->header.command & ENET_PROTOCOL_COMMAND_MASK) {
4170             case ENET_PROTOCOL_COMMAND_SEND_FRAGMENT:
4171             case ENET_PROTOCOL_COMMAND_SEND_RELIABLE:
4172                 if (reliableSequenceNumber == channel->incomingReliableSequenceNumber) {
4173                     goto discardCommand;
4174                 }
4175 
4176                 for (currentCommand = enet_list_previous(enet_list_end(&channel->incomingReliableCommands));
4177                     currentCommand != enet_list_end(&channel->incomingReliableCommands);
4178                     currentCommand = enet_list_previous(currentCommand)
4179                 ) {
4180                     incomingCommand = (ENetIncomingCommand *) currentCommand;
4181 
4182                     if (reliableSequenceNumber >= channel->incomingReliableSequenceNumber) {
4183                         if (incomingCommand->reliableSequenceNumber < channel->incomingReliableSequenceNumber) {
4184                             continue;
4185                         }
4186                     } else if (incomingCommand->reliableSequenceNumber >= channel->incomingReliableSequenceNumber) {
4187                         break;
4188                     }
4189 
4190                     if (incomingCommand->reliableSequenceNumber <= reliableSequenceNumber) {
4191                         if (incomingCommand->reliableSequenceNumber < reliableSequenceNumber) {
4192                             break;
4193                         }
4194 
4195                         goto discardCommand;
4196                     }
4197                 }
4198                 break;
4199 
4200             case ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE:
4201             case ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE_FRAGMENT:
4202                 unreliableSequenceNumber = ENET_NET_TO_HOST_16(command->sendUnreliable.unreliableSequenceNumber);
4203 
4204                 if (reliableSequenceNumber == channel->incomingReliableSequenceNumber && unreliableSequenceNumber <= channel->incomingUnreliableSequenceNumber) {
4205                     goto discardCommand;
4206                 }
4207 
4208                 for (currentCommand = enet_list_previous(enet_list_end(&channel->incomingUnreliableCommands));
4209                     currentCommand != enet_list_end(&channel->incomingUnreliableCommands);
4210                     currentCommand = enet_list_previous(currentCommand)
4211                 ) {
4212                     incomingCommand = (ENetIncomingCommand *) currentCommand;
4213 
4214                     if ((command->header.command & ENET_PROTOCOL_COMMAND_MASK) == ENET_PROTOCOL_COMMAND_SEND_UNSEQUENCED) {
4215                         continue;
4216                     }
4217 
4218                     if (reliableSequenceNumber >= channel->incomingReliableSequenceNumber) {
4219                         if (incomingCommand->reliableSequenceNumber < channel->incomingReliableSequenceNumber) {
4220                             continue;
4221                         }
4222                     } else if (incomingCommand->reliableSequenceNumber >= channel->incomingReliableSequenceNumber) {
4223                         break;
4224                     }
4225 
4226                     if (incomingCommand->reliableSequenceNumber < reliableSequenceNumber) {
4227                         break;
4228                     }
4229 
4230                     if (incomingCommand->reliableSequenceNumber > reliableSequenceNumber) {
4231                         continue;
4232                     }
4233 
4234                     if (incomingCommand->unreliableSequenceNumber <= unreliableSequenceNumber) {
4235                         if (incomingCommand->unreliableSequenceNumber < unreliableSequenceNumber) {
4236                             break;
4237                         }
4238 
4239                         goto discardCommand;
4240                     }
4241                 }
4242                 break;
4243 
4244             case ENET_PROTOCOL_COMMAND_SEND_UNSEQUENCED:
4245                 currentCommand = enet_list_end(&channel->incomingUnreliableCommands);
4246                 break;
4247 
4248             default:
4249                 goto discardCommand;
4250         }
4251 
4252         if (peer->totalWaitingData >= peer->host->maximumWaitingData) {
4253             goto notifyError;
4254         }
4255 
4256         packet = enet_packet_create(data, dataLength, flags);
4257         if (packet == NULL) {
4258             goto notifyError;
4259         }
4260 
4261         incomingCommand = (ENetIncomingCommand *) enet_malloc(sizeof(ENetIncomingCommand));
4262         if (incomingCommand == NULL) {
4263             goto notifyError;
4264         }
4265 
4266         incomingCommand->reliableSequenceNumber     = command->header.reliableSequenceNumber;
4267         incomingCommand->unreliableSequenceNumber   = unreliableSequenceNumber & 0xFFFF;
4268         incomingCommand->command                    = *command;
4269         incomingCommand->fragmentCount              = fragmentCount;
4270         incomingCommand->fragmentsRemaining         = fragmentCount;
4271         incomingCommand->packet                     = packet;
4272         incomingCommand->fragments                  = NULL;
4273 
4274         if (fragmentCount > 0) {
4275             if (fragmentCount <= ENET_PROTOCOL_MAXIMUM_FRAGMENT_COUNT) {
4276                 incomingCommand->fragments = (enet_uint32 *) enet_malloc((fragmentCount + 31) / 32 * sizeof(enet_uint32));
4277             }
4278 
4279             if (incomingCommand->fragments == NULL) {
4280                 enet_free(incomingCommand);
4281 
4282                 goto notifyError;
4283             }
4284 
4285             memset(incomingCommand->fragments, 0, (fragmentCount + 31) / 32 * sizeof(enet_uint32));
4286         }
4287 
4288         if (packet != NULL) {
4289             ++packet->referenceCount;
4290             peer->totalWaitingData += packet->dataLength;
4291         }
4292 
4293         enet_list_insert(enet_list_next(currentCommand), incomingCommand);
4294 
4295         switch (command->header.command & ENET_PROTOCOL_COMMAND_MASK) {
4296             case ENET_PROTOCOL_COMMAND_SEND_FRAGMENT:
4297             case ENET_PROTOCOL_COMMAND_SEND_RELIABLE:
4298                 enet_peer_dispatch_incoming_reliable_commands(peer, channel);
4299                 break;
4300 
4301             default:
4302                 enet_peer_dispatch_incoming_unreliable_commands(peer, channel);
4303                 break;
4304         }
4305 
4306         return incomingCommand;
4307 
4308     discardCommand:
4309         if (fragmentCount > 0) {
4310             goto notifyError;
4311         }
4312 
4313         if (packet != NULL && packet->referenceCount == 0) {
4314             enet_packet_destroy(packet);
4315         }
4316 
4317         return &dummyCommand;
4318 
4319     notifyError:
4320         if (packet != NULL && packet->referenceCount == 0) {
4321             enet_packet_destroy(packet);
4322         }
4323 
4324         return NULL;
4325     } /* enet_peer_queue_incoming_command */
4326 
4327 // =======================================================================//
4328 // !
4329 // ! Host
4330 // !
4331 // =======================================================================//
4332 
4333     /** Creates a host for communicating to peers.
4334      *
4335      *  @param address   the address at which other peers may connect to this host.  If NULL, then no peers may connect to the host.
4336      *  @param peerCount the maximum number of peers that should be allocated for the host.
4337      *  @param channelLimit the maximum number of channels allowed; if 0, then this is equivalent to ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT
4338      *  @param incomingBandwidth downstream bandwidth of the host in bytes/second; if 0, ENet will assume unlimited bandwidth.
4339      *  @param outgoingBandwidth upstream bandwidth of the host in bytes/second; if 0, ENet will assume unlimited bandwidth.
4340      *
4341      *  @returns the host on success and NULL on failure
4342      *
4343      *  @remarks ENet will strategically drop packets on specific sides of a connection between hosts
4344      *  to ensure the host's bandwidth is not overwhelmed.  The bandwidth parameters also determine
4345      *  the window size of a connection which limits the amount of reliable packets that may be in transit
4346      *  at any given time.
4347      */
enet_host_create(ENetAddress * address,size_t peerCount,size_t channelLimit,enet_uint32 incomingBandwidth,enet_uint32 outgoingBandwidth)4348     ENetHost * enet_host_create(ENetAddress *address, size_t peerCount, size_t channelLimit, enet_uint32 incomingBandwidth, enet_uint32 outgoingBandwidth) {
4349         ENetHost *host;
4350         ENetPeer *currentPeer;
4351 
4352         if (peerCount > ENET_PROTOCOL_MAXIMUM_PEER_ID) {
4353             return NULL;
4354         }
4355 
4356         host = (ENetHost *) enet_malloc(sizeof(ENetHost));
4357         if (host == NULL) { return NULL; }
4358         memset(host, 0, sizeof(ENetHost));
4359 
4360         host->peers = (ENetPeer *) enet_malloc(peerCount * sizeof(ENetPeer));
4361         if (host->peers == NULL) {
4362             enet_free(host);
4363             return NULL;
4364         }
4365 
4366         memset(host->peers, 0, peerCount * sizeof(ENetPeer));
4367 
4368         host->socket = enet_socket_create(ENET_SOCKET_TYPE_DATAGRAM);
4369         if (host->socket != ENET_SOCKET_NULL) {
4370             enet_socket_set_option (host->socket, ENET_SOCKOPT_IPV6_V6ONLY, 0);
4371         }
4372 
4373         if (host->socket == ENET_SOCKET_NULL || (address != NULL && enet_socket_bind(host->socket, address) < 0)) {
4374             if (host->socket != ENET_SOCKET_NULL) {
4375                 enet_socket_destroy(host->socket);
4376             }
4377 
4378             enet_free(host->peers);
4379             enet_free(host);
4380 
4381             return NULL;
4382         }
4383 
4384         enet_socket_set_option(host->socket, ENET_SOCKOPT_NONBLOCK, 1);
4385         enet_socket_set_option(host->socket, ENET_SOCKOPT_BROADCAST, 1);
4386         enet_socket_set_option(host->socket, ENET_SOCKOPT_RCVBUF, ENET_HOST_RECEIVE_BUFFER_SIZE);
4387         enet_socket_set_option(host->socket, ENET_SOCKOPT_SNDBUF, ENET_HOST_SEND_BUFFER_SIZE);
4388         enet_socket_set_option(host->socket, ENET_SOCKOPT_IPV6_V6ONLY, 0);
4389 
4390         if (address != NULL && enet_socket_get_address(host->socket, &host->address) < 0) {
4391             host->address = *address;
4392         }
4393 
4394         if (!channelLimit || channelLimit > ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT) {
4395             channelLimit = ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT;
4396         } else if (channelLimit < ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT) {
4397             channelLimit = ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT;
4398         }
4399 
4400         host->randomSeed                    = (enet_uint32) (size_t) host;
4401         host->randomSeed                    += enet_host_random_seed();
4402         host->randomSeed                    = (host->randomSeed << 16) | (host->randomSeed >> 16);
4403         host->channelLimit                  = channelLimit;
4404         host->incomingBandwidth             = incomingBandwidth;
4405         host->outgoingBandwidth             = outgoingBandwidth;
4406         host->bandwidthThrottleEpoch        = 0;
4407         host->recalculateBandwidthLimits    = 0;
4408         host->mtu                           = ENET_HOST_DEFAULT_MTU;
4409         host->peerCount                     = peerCount;
4410         host->commandCount                  = 0;
4411         host->bufferCount                   = 0;
4412         host->checksum                      = NULL;
4413         host->receivedAddress.host          = ENET_HOST_ANY;
4414         host->receivedAddress.port          = 0;
4415         host->receivedData                  = NULL;
4416         host->receivedDataLength            = 0;
4417         host->totalSentData                 = 0;
4418         host->totalSentPackets              = 0;
4419         host->totalReceivedData             = 0;
4420         host->totalReceivedPackets          = 0;
4421         host->connectedPeers                = 0;
4422         host->bandwidthLimitedPeers         = 0;
4423         host->duplicatePeers                = ENET_PROTOCOL_MAXIMUM_PEER_ID;
4424         host->maximumPacketSize             = ENET_HOST_DEFAULT_MAXIMUM_PACKET_SIZE;
4425         host->maximumWaitingData            = ENET_HOST_DEFAULT_MAXIMUM_WAITING_DATA;
4426         host->compressor.context            = NULL;
4427         host->compressor.compress           = NULL;
4428         host->compressor.decompress         = NULL;
4429         host->compressor.destroy            = NULL;
4430         host->intercept                     = NULL;
4431 
4432         enet_list_clear(&host->dispatchQueue);
4433 
4434         for (currentPeer = host->peers; currentPeer < &host->peers[host->peerCount]; ++currentPeer) {
4435             currentPeer->host = host;
4436             currentPeer->incomingPeerID    = currentPeer - host->peers;
4437             currentPeer->outgoingSessionID = currentPeer->incomingSessionID = 0xFF;
4438             currentPeer->data = NULL;
4439 
4440             enet_list_clear(&currentPeer->acknowledgements);
4441             enet_list_clear(&currentPeer->sentReliableCommands);
4442             enet_list_clear(&currentPeer->sentUnreliableCommands);
4443             enet_list_clear(&currentPeer->outgoingReliableCommands);
4444             enet_list_clear(&currentPeer->outgoingUnreliableCommands);
4445             enet_list_clear(&currentPeer->dispatchedCommands);
4446 
4447             enet_peer_reset(currentPeer);
4448         }
4449 
4450         return host;
4451     } /* enet_host_create */
4452 
4453     /** Destroys the host and all resources associated with it.
4454      *  @param host pointer to the host to destroy
4455      */
enet_host_destroy(ENetHost * host)4456     void enet_host_destroy(ENetHost *host) {
4457         ENetPeer *currentPeer;
4458 
4459         if (host == NULL) {
4460             return;
4461         }
4462 
4463         enet_socket_destroy(host->socket);
4464 
4465         for (currentPeer = host->peers; currentPeer < &host->peers[host->peerCount]; ++currentPeer) {
4466             enet_peer_reset(currentPeer);
4467         }
4468 
4469         if (host->compressor.context != NULL && host->compressor.destroy) {
4470             (*host->compressor.destroy)(host->compressor.context);
4471         }
4472 
4473         enet_free(host->peers);
4474         enet_free(host);
4475     }
4476 
4477     /** Initiates a connection to a foreign host.
4478      *  @param host host seeking the connection
4479      *  @param address destination for the connection
4480      *  @param channelCount number of channels to allocate
4481      *  @param data user data supplied to the receiving host
4482      *  @returns a peer representing the foreign host on success, NULL on failure
4483      *  @remarks The peer returned will have not completed the connection until enet_host_service()
4484      *  notifies of an ENET_EVENT_TYPE_CONNECT event for the peer.
4485      */
enet_host_connect(ENetHost * host,ENetAddress * address,size_t channelCount,enet_uint32 data)4486     ENetPeer * enet_host_connect(ENetHost *host, ENetAddress *address, size_t channelCount, enet_uint32 data) {
4487         ENetPeer *currentPeer;
4488         ENetChannel *channel;
4489         ENetProtocol command;
4490 
4491         if (channelCount < ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT) {
4492             channelCount = ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT;
4493         } else if (channelCount > ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT) {
4494             channelCount = ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT;
4495         }
4496 
4497         for (currentPeer = host->peers; currentPeer < &host->peers[host->peerCount]; ++currentPeer) {
4498             if (currentPeer->state == ENET_PEER_STATE_DISCONNECTED) {
4499                 break;
4500             }
4501         }
4502 
4503         if (currentPeer >= &host->peers[host->peerCount]) {
4504             return NULL;
4505         }
4506 
4507         currentPeer->channels = (ENetChannel *) enet_malloc(channelCount * sizeof(ENetChannel));
4508         if (currentPeer->channels == NULL) {
4509             return NULL;
4510         }
4511 
4512         currentPeer->channelCount = channelCount;
4513         currentPeer->state        = ENET_PEER_STATE_CONNECTING;
4514         currentPeer->address      = *address;
4515         currentPeer->connectID    = ++host->randomSeed;
4516 
4517         if (host->outgoingBandwidth == 0) {
4518             currentPeer->windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE;
4519         } else {
4520             currentPeer->windowSize = (host->outgoingBandwidth / ENET_PEER_WINDOW_SIZE_SCALE) * ENET_PROTOCOL_MINIMUM_WINDOW_SIZE;
4521         }
4522 
4523         if (currentPeer->windowSize < ENET_PROTOCOL_MINIMUM_WINDOW_SIZE) {
4524             currentPeer->windowSize = ENET_PROTOCOL_MINIMUM_WINDOW_SIZE;
4525         } else if (currentPeer->windowSize > ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE) {
4526             currentPeer->windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE;
4527         }
4528 
4529         for (channel = currentPeer->channels; channel < &currentPeer->channels[channelCount]; ++channel) {
4530             channel->outgoingReliableSequenceNumber   = 0;
4531             channel->outgoingUnreliableSequenceNumber = 0;
4532             channel->incomingReliableSequenceNumber   = 0;
4533             channel->incomingUnreliableSequenceNumber = 0;
4534 
4535             enet_list_clear(&channel->incomingReliableCommands);
4536             enet_list_clear(&channel->incomingUnreliableCommands);
4537 
4538             channel->usedReliableWindows = 0;
4539             memset(channel->reliableWindows, 0, sizeof(channel->reliableWindows));
4540         }
4541 
4542         command.header.command                     = ENET_PROTOCOL_COMMAND_CONNECT | ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE;
4543         command.header.channelID                   = 0xFF;
4544         command.connect.outgoingPeerID             = ENET_HOST_TO_NET_16(currentPeer->incomingPeerID);
4545         command.connect.incomingSessionID          = currentPeer->incomingSessionID;
4546         command.connect.outgoingSessionID          = currentPeer->outgoingSessionID;
4547         command.connect.mtu                        = ENET_HOST_TO_NET_32(currentPeer->mtu);
4548         command.connect.windowSize                 = ENET_HOST_TO_NET_32(currentPeer->windowSize);
4549         command.connect.channelCount               = ENET_HOST_TO_NET_32(channelCount);
4550         command.connect.incomingBandwidth          = ENET_HOST_TO_NET_32(host->incomingBandwidth);
4551         command.connect.outgoingBandwidth          = ENET_HOST_TO_NET_32(host->outgoingBandwidth);
4552         command.connect.packetThrottleInterval     = ENET_HOST_TO_NET_32(currentPeer->packetThrottleInterval);
4553         command.connect.packetThrottleAcceleration = ENET_HOST_TO_NET_32(currentPeer->packetThrottleAcceleration);
4554         command.connect.packetThrottleDeceleration = ENET_HOST_TO_NET_32(currentPeer->packetThrottleDeceleration);
4555         command.connect.connectID                  = currentPeer->connectID;
4556         command.connect.data                       = ENET_HOST_TO_NET_32(data);
4557 
4558         enet_peer_queue_outgoing_command(currentPeer, &command, NULL, 0, 0);
4559 
4560         return currentPeer;
4561     } /* enet_host_connect */
4562 
4563     /** Queues a packet to be sent to all peers associated with the host.
4564      *  @param host host on which to broadcast the packet
4565      *  @param channelID channel on which to broadcast
4566      *  @param packet packet to broadcast
4567      */
enet_host_broadcast(ENetHost * host,enet_uint8 channelID,ENetPacket * packet)4568     void enet_host_broadcast(ENetHost *host, enet_uint8 channelID, ENetPacket *packet) {
4569         ENetPeer *currentPeer;
4570 
4571         for (currentPeer = host->peers; currentPeer < &host->peers[host->peerCount]; ++currentPeer) {
4572             if (currentPeer->state != ENET_PEER_STATE_CONNECTED) {
4573                 continue;
4574             }
4575 
4576             enet_peer_send(currentPeer, channelID, packet);
4577         }
4578 
4579         if (packet->referenceCount == 0) {
4580             enet_packet_destroy(packet);
4581         }
4582     }
4583 
4584     /** Sends raw data to specified address. Useful when you want to send unconnected data using host's socket.
4585      *  @param host host sending data
4586      *  @param address destination address
4587      *  @param data data pointer
4588      *  @param dataLength length of data to send
4589      *  @retval >=0 bytes sent
4590      *  @retval <0 error
4591      *  @sa enet_socket_send
4592      */
enet_host_send_raw(ENetHost * host,ENetAddress * address,enet_uint8 * data,size_t dataLength)4593     int enet_host_send_raw(ENetHost *host, ENetAddress* address, enet_uint8* data, size_t dataLength) {
4594         ENetBuffer buffer;
4595         buffer.data = data;
4596         buffer.dataLength = dataLength;
4597         return enet_socket_send(host->socket, address, &buffer, 1);
4598     }
4599 
4600     /** Sends raw data to specified address with extended arguments. Allows to send only part of data, handy for other programming languages.
4601      *  I.e. if you have data =- { 0, 1, 2, 3 } and call function as enet_host_send_raw_ex(data, 1, 2) then it will skip 1 byte and send 2 bytes { 1, 2 }.
4602      *  @param host host sending data
4603      *  @param address destination address
4604      *  @param data data pointer
4605      *  @param skipBytes number of bytes to skip from start of data
4606      *  @param bytesToSend number of bytes to send
4607      *  @retval >=0 bytes sent
4608      *  @retval <0 error
4609      *  @sa enet_socket_send
4610      */
enet_host_send_raw_ex(ENetHost * host,ENetAddress * address,enet_uint8 * data,size_t skipBytes,size_t bytesToSend)4611     int enet_host_send_raw_ex(ENetHost *host, ENetAddress* address, enet_uint8* data, size_t skipBytes, size_t bytesToSend) {
4612         ENetBuffer buffer;
4613         buffer.data = data + skipBytes;
4614         buffer.dataLength = bytesToSend;
4615         return enet_socket_send(host->socket, address, &buffer, 1);
4616     }
4617 
4618     /** Sets intercept callback for the host.
4619      *  @param host host to set a callback
4620      *  @param callback intercept callback
4621      */
enet_host_set_intercept(ENetHost * host,const ENetInterceptCallback callback)4622     void enet_host_set_intercept(ENetHost *host, const ENetInterceptCallback callback) {
4623         host->intercept = callback;
4624     }
4625 
4626     /** Sets the packet compressor the host should use to compress and decompress packets.
4627      *  @param host host to enable or disable compression for
4628      *  @param compressor callbacks for for the packet compressor; if NULL, then compression is disabled
4629      */
enet_host_compress(ENetHost * host,const ENetCompressor * compressor)4630     void enet_host_compress(ENetHost *host, const ENetCompressor *compressor) {
4631         if (host->compressor.context != NULL && host->compressor.destroy) {
4632             (*host->compressor.destroy)(host->compressor.context);
4633         }
4634 
4635         if (compressor) {
4636             host->compressor = *compressor;
4637         } else {
4638             host->compressor.context = NULL;
4639         }
4640     }
4641 
4642     /** Limits the maximum allowed channels of future incoming connections.
4643      *  @param host host to limit
4644      *  @param channelLimit the maximum number of channels allowed; if 0, then this is equivalent to ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT
4645      */
enet_host_channel_limit(ENetHost * host,size_t channelLimit)4646     void enet_host_channel_limit(ENetHost *host, size_t channelLimit) {
4647         if (!channelLimit || channelLimit > ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT) {
4648             channelLimit = ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT;
4649         } else if (channelLimit < ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT) {
4650             channelLimit = ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT;
4651         }
4652 
4653         host->channelLimit = channelLimit;
4654     }
4655 
4656     /** Adjusts the bandwidth limits of a host.
4657      *  @param host host to adjust
4658      *  @param incomingBandwidth new incoming bandwidth
4659      *  @param outgoingBandwidth new outgoing bandwidth
4660      *  @remarks the incoming and outgoing bandwidth parameters are identical in function to those
4661      *  specified in enet_host_create().
4662      */
enet_host_bandwidth_limit(ENetHost * host,enet_uint32 incomingBandwidth,enet_uint32 outgoingBandwidth)4663     void enet_host_bandwidth_limit(ENetHost *host, enet_uint32 incomingBandwidth, enet_uint32 outgoingBandwidth) {
4664         host->incomingBandwidth = incomingBandwidth;
4665         host->outgoingBandwidth = outgoingBandwidth;
4666         host->recalculateBandwidthLimits = 1;
4667     }
4668 
enet_host_bandwidth_throttle(ENetHost * host)4669     void enet_host_bandwidth_throttle(ENetHost *host) {
4670         enet_uint32 timeCurrent       = enet_time_get();
4671         enet_uint32 elapsedTime       = timeCurrent - host->bandwidthThrottleEpoch;
4672         enet_uint32 peersRemaining    = (enet_uint32) host->connectedPeers;
4673         enet_uint32 dataTotal         = ~0;
4674         enet_uint32 bandwidth         = ~0;
4675         enet_uint32 throttle          = 0;
4676         enet_uint32 bandwidthLimit    = 0;
4677 
4678         int needsAdjustment = host->bandwidthLimitedPeers > 0 ? 1 : 0;
4679         ENetPeer *peer;
4680         ENetProtocol command;
4681 
4682         if (elapsedTime < ENET_HOST_BANDWIDTH_THROTTLE_INTERVAL) {
4683             return;
4684         }
4685 
4686         if (host->outgoingBandwidth == 0 && host->incomingBandwidth == 0) {
4687             return;
4688         }
4689 
4690         host->bandwidthThrottleEpoch = timeCurrent;
4691 
4692         if (peersRemaining == 0) {
4693             return;
4694         }
4695 
4696         if (host->outgoingBandwidth != 0) {
4697             dataTotal = 0;
4698             bandwidth = (host->outgoingBandwidth * elapsedTime) / 1000;
4699 
4700             for (peer = host->peers; peer < &host->peers[host->peerCount]; ++peer) {
4701                 if (peer->state != ENET_PEER_STATE_CONNECTED && peer->state != ENET_PEER_STATE_DISCONNECT_LATER) {
4702                     continue;
4703                 }
4704 
4705                 dataTotal += peer->outgoingDataTotal;
4706             }
4707         }
4708 
4709         while (peersRemaining > 0 && needsAdjustment != 0) {
4710             needsAdjustment = 0;
4711 
4712             if (dataTotal <= bandwidth) {
4713                 throttle = ENET_PEER_PACKET_THROTTLE_SCALE;
4714             } else {
4715                 throttle = (bandwidth * ENET_PEER_PACKET_THROTTLE_SCALE) / dataTotal;
4716             }
4717 
4718             for (peer = host->peers; peer < &host->peers[host->peerCount]; ++peer) {
4719                 enet_uint32 peerBandwidth;
4720 
4721                 if ((peer->state != ENET_PEER_STATE_CONNECTED && peer->state != ENET_PEER_STATE_DISCONNECT_LATER) ||
4722                     peer->incomingBandwidth == 0 ||
4723                     peer->outgoingBandwidthThrottleEpoch == timeCurrent
4724                 ) {
4725                     continue;
4726                 }
4727 
4728                 peerBandwidth = (peer->incomingBandwidth * elapsedTime) / 1000;
4729                 if ((throttle * peer->outgoingDataTotal) / ENET_PEER_PACKET_THROTTLE_SCALE <= peerBandwidth) {
4730                     continue;
4731                 }
4732 
4733                 peer->packetThrottleLimit = (peerBandwidth * ENET_PEER_PACKET_THROTTLE_SCALE) / peer->outgoingDataTotal;
4734 
4735                 if (peer->packetThrottleLimit == 0) {
4736                     peer->packetThrottleLimit = 1;
4737                 }
4738 
4739                 if (peer->packetThrottle > peer->packetThrottleLimit) {
4740                     peer->packetThrottle = peer->packetThrottleLimit;
4741                 }
4742 
4743                 peer->outgoingBandwidthThrottleEpoch = timeCurrent;
4744 
4745                 peer->incomingDataTotal = 0;
4746                 peer->outgoingDataTotal = 0;
4747 
4748                 needsAdjustment = 1;
4749                 --peersRemaining;
4750                 bandwidth -= peerBandwidth;
4751                 dataTotal -= peerBandwidth;
4752             }
4753         }
4754 
4755         if (peersRemaining > 0) {
4756             if (dataTotal <= bandwidth) {
4757                 throttle = ENET_PEER_PACKET_THROTTLE_SCALE;
4758             } else {
4759                 throttle = (bandwidth * ENET_PEER_PACKET_THROTTLE_SCALE) / dataTotal;
4760             }
4761 
4762             for (peer = host->peers;
4763               peer < &host->peers[host->peerCount];
4764               ++peer)
4765             {
4766                 if ((peer->state != ENET_PEER_STATE_CONNECTED && peer->state != ENET_PEER_STATE_DISCONNECT_LATER) || peer->outgoingBandwidthThrottleEpoch == timeCurrent) {
4767                     continue;
4768                 }
4769 
4770                 peer->packetThrottleLimit = throttle;
4771 
4772                 if (peer->packetThrottle > peer->packetThrottleLimit) {
4773                     peer->packetThrottle = peer->packetThrottleLimit;
4774                 }
4775 
4776                 peer->incomingDataTotal = 0;
4777                 peer->outgoingDataTotal = 0;
4778             }
4779         }
4780 
4781         if (host->recalculateBandwidthLimits) {
4782             host->recalculateBandwidthLimits = 0;
4783 
4784             peersRemaining  = (enet_uint32) host->connectedPeers;
4785             bandwidth       = host->incomingBandwidth;
4786             needsAdjustment = 1;
4787 
4788             if (bandwidth == 0) {
4789                 bandwidthLimit = 0;
4790             } else {
4791                 while (peersRemaining > 0 && needsAdjustment != 0) {
4792                     needsAdjustment = 0;
4793                     bandwidthLimit  = bandwidth / peersRemaining;
4794 
4795                     for (peer = host->peers; peer < &host->peers[host->peerCount]; ++peer) {
4796                         if ((peer->state != ENET_PEER_STATE_CONNECTED && peer->state != ENET_PEER_STATE_DISCONNECT_LATER) ||
4797                             peer->incomingBandwidthThrottleEpoch == timeCurrent
4798                         ) {
4799                             continue;
4800                         }
4801 
4802                         if (peer->outgoingBandwidth > 0 && peer->outgoingBandwidth >= bandwidthLimit) {
4803                             continue;
4804                         }
4805 
4806                         peer->incomingBandwidthThrottleEpoch = timeCurrent;
4807 
4808                         needsAdjustment = 1;
4809                         --peersRemaining;
4810                         bandwidth -= peer->outgoingBandwidth;
4811                     }
4812                 }
4813             }
4814 
4815             for (peer = host->peers; peer < &host->peers[host->peerCount]; ++peer) {
4816                 if (peer->state != ENET_PEER_STATE_CONNECTED && peer->state != ENET_PEER_STATE_DISCONNECT_LATER) {
4817                     continue;
4818                 }
4819 
4820                 command.header.command   = ENET_PROTOCOL_COMMAND_BANDWIDTH_LIMIT | ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE;
4821                 command.header.channelID = 0xFF;
4822                 command.bandwidthLimit.outgoingBandwidth = ENET_HOST_TO_NET_32(host->outgoingBandwidth);
4823 
4824                 if (peer->incomingBandwidthThrottleEpoch == timeCurrent) {
4825                     command.bandwidthLimit.incomingBandwidth = ENET_HOST_TO_NET_32(peer->outgoingBandwidth);
4826                 } else {
4827                     command.bandwidthLimit.incomingBandwidth = ENET_HOST_TO_NET_32(bandwidthLimit);
4828                 }
4829 
4830                 enet_peer_queue_outgoing_command(peer, &command, NULL, 0, 0);
4831             }
4832         }
4833     } /* enet_host_bandwidth_throttle */
4834 
4835 // =======================================================================//
4836 // !
4837 // ! Time
4838 // !
4839 // =======================================================================//
4840 
4841     #ifdef _WIN32
getFILETIMEoffset()4842         static LARGE_INTEGER getFILETIMEoffset() {
4843             SYSTEMTIME s;
4844             FILETIME f;
4845             LARGE_INTEGER t;
4846 
4847             s.wYear = 1970;
4848             s.wMonth = 1;
4849             s.wDay = 1;
4850             s.wHour = 0;
4851             s.wMinute = 0;
4852             s.wSecond = 0;
4853             s.wMilliseconds = 0;
4854             SystemTimeToFileTime(&s, &f);
4855             t.QuadPart = f.dwHighDateTime;
4856             t.QuadPart <<= 32;
4857             t.QuadPart |= f.dwLowDateTime;
4858             return (t);
4859         }
4860 
enet_gettime(int X,struct timespec * tv)4861         int enet_gettime(int X, struct timespec *tv) {
4862             UNREFERENCED_PARAMETER(X);
4863             LARGE_INTEGER t;
4864             FILETIME f;
4865             double microseconds;
4866             static LARGE_INTEGER offset;
4867             static double frequencyToMicroseconds;
4868             static int initialized = 0;
4869             static BOOL usePerformanceCounter = 0;
4870 
4871             if (!initialized) {
4872                 LARGE_INTEGER performanceFrequency;
4873                 initialized = 1;
4874                 usePerformanceCounter = QueryPerformanceFrequency(&performanceFrequency);
4875                 if (usePerformanceCounter) {
4876                     QueryPerformanceCounter(&offset);
4877                     frequencyToMicroseconds = (double)performanceFrequency.QuadPart / 1000000.;
4878                 } else {
4879                     offset = getFILETIMEoffset();
4880                     frequencyToMicroseconds = 10.;
4881                 }
4882             }
4883             if (usePerformanceCounter) {
4884                 QueryPerformanceCounter(&t);
4885             } else {
4886                 GetSystemTimeAsFileTime(&f);
4887                 t.QuadPart = f.dwHighDateTime;
4888                 t.QuadPart <<= 32;
4889                 t.QuadPart |= f.dwLowDateTime;
4890             }
4891 
4892             t.QuadPart -= offset.QuadPart;
4893             microseconds = (double)t.QuadPart / frequencyToMicroseconds;
4894             t.QuadPart = (LONGLONG)microseconds;
4895             tv->tv_sec = (long)(t.QuadPart / 1000000);
4896             tv->tv_nsec = t.QuadPart % 1000000 * 1000;
4897             return (0);
4898         }
4899     #elif __APPLE__ && __MAC_OS_X_VERSION_MIN_REQUIRED < 101200
4900         #define CLOCK_MONOTONIC 0
4901 
enet_gettime(int X,struct timespec * ts)4902         int enet_gettime(int X, struct timespec *ts) {
4903             clock_serv_t cclock;
4904             mach_timespec_t mts;
4905 
4906             host_get_clock_service(mach_host_self(), SYSTEM_CLOCK, &cclock);
4907             clock_get_time(cclock, &mts);
4908             mach_port_deallocate(mach_task_self(), cclock);
4909 
4910             ts->tv_sec = mts.tv_sec;
4911             ts->tv_nsec = mts.tv_nsec;
4912 
4913             return 0;
4914         }
4915     #endif
4916 
enet_time_get()4917     enet_uint32 enet_time_get() {
4918         // TODO enet uses 32 bit timestamps. We should modify it to use
4919         // 64 bit timestamps, but this is not trivial since we'd end up
4920         // changing half the structs in enet. For now, retain 32 bits, but
4921         // use an offset so we don't run out of bits. Basically, the first
4922         // call of enet_time_get() will always return 1, and follow-up calls
4923         // indicate elapsed time since the first call.
4924         //
4925         // Note that we don't want to return 0 from the first call, in case
4926         // some part of enet uses 0 as a special value (meaning time not set
4927         // for example).
4928         static uint64_t start_time_ns = 0;
4929 
4930         struct timespec ts;
4931     #if defined(CLOCK_MONOTONIC_RAW)
4932         enet_gettime(CLOCK_MONOTONIC_RAW, &ts);
4933     #else
4934         enet_gettime(CLOCK_MONOTONIC, &ts);
4935     #endif
4936 
4937         static const uint64_t ns_in_s = 1000 * 1000 * 1000;
4938         static const uint64_t ns_in_ms = 1000 * 1000;
4939         uint64_t current_time_ns = ts.tv_nsec + (uint64_t)ts.tv_sec * ns_in_s;
4940 
4941         // Most of the time we just want to atomically read the start time. We
4942         // could just use a single CAS instruction instead of this if, but it
4943         // would be slower in the average case.
4944         //
4945         // Note that statics are auto-initialized to zero, and starting a thread
4946         // implies a memory barrier. So we know that whatever thread calls this,
4947         // it correctly sees the start_time_ns as 0 initially.
4948         uint64_t offset_ns = ENET_ATOMIC_READ(&start_time_ns);
4949         if (offset_ns == 0) {
4950             // We still need to CAS, since two different threads can get here
4951             // at the same time.
4952             //
4953             // We assume that current_time_ns is > 1ms.
4954             //
4955             // Set the value of the start_time_ns, such that the first timestamp
4956             // is at 1ms. This ensures 0 remains a special value.
4957             uint64_t want_value = current_time_ns - 1 * ns_in_ms;
4958             uint64_t old_value = ENET_ATOMIC_CAS(&start_time_ns, 0, want_value);
4959             offset_ns = old_value == 0 ? want_value : old_value;
4960         }
4961 
4962         uint64_t result_in_ns = current_time_ns - offset_ns;
4963         return (enet_uint32)(result_in_ns / ns_in_ms);
4964     }
4965 
4966 // =======================================================================//
4967 // !
4968 // ! Platform Specific (Unix)
4969 // !
4970 // =======================================================================//
4971 
4972     #ifndef _WIN32
4973 
enet_initialize(void)4974     int enet_initialize(void) {
4975         return 0;
4976     }
4977 
enet_deinitialize(void)4978     void enet_deinitialize(void) {}
4979 
enet_host_random_seed(void)4980     enet_uint64 enet_host_random_seed(void) {
4981         return (enet_uint64) time(NULL);
4982     }
4983 
enet_address_set_host_ip(ENetAddress * address,char * name)4984     int enet_address_set_host_ip(ENetAddress *address, char *name) {
4985         if (!inet_pton(AF_INET6, name, &address->host)) {
4986             return -1;
4987         }
4988 
4989         return 0;
4990     }
4991 
enet_address_set_host(ENetAddress * address,char * name)4992     int enet_address_set_host(ENetAddress *address, char *name) {
4993         struct addrinfo hints, *resultList = NULL, *result = NULL;
4994 
4995         memset(&hints, 0, sizeof(hints));
4996         hints.ai_family = AF_UNSPEC;
4997 
4998         if (getaddrinfo(name, NULL, &hints, &resultList) != 0) {
4999             return -1;
5000         }
5001 
5002         for (result = resultList; result != NULL; result = result->ai_next) {
5003             if (result->ai_addr != NULL && result->ai_addrlen >= sizeof(struct sockaddr_in)) {
5004                 if (result->ai_family == AF_INET) {
5005                     struct sockaddr_in * sin = (struct sockaddr_in *) result->ai_addr;
5006 
5007                     ((uint32_t *)&address->host.s6_addr)[0] = 0;
5008                     ((uint32_t *)&address->host.s6_addr)[1] = 0;
5009                     ((uint32_t *)&address->host.s6_addr)[2] = htonl(0xffff);
5010                     ((uint32_t *)&address->host.s6_addr)[3] = sin->sin_addr.s_addr;
5011 
5012                     freeaddrinfo(resultList);
5013 
5014                     return 0;
5015                 }
5016                 else if(result->ai_family == AF_INET6) {
5017                     struct sockaddr_in6 * sin = (struct sockaddr_in6 *)result->ai_addr;
5018 
5019                     address->host = sin->sin6_addr;
5020                     address->sin6_scope_id = sin->sin6_scope_id;
5021 
5022                     freeaddrinfo(resultList);
5023 
5024                     return 0;
5025                 }
5026             }
5027         }
5028 
5029 
5030         if (resultList != NULL) {
5031             freeaddrinfo(resultList);
5032         }
5033 
5034         return enet_address_set_host_ip(address, name);
5035     } /* enet_address_set_host */
5036 
enet_address_get_host_ip(ENetAddress * address,char * name,size_t nameLength)5037     int enet_address_get_host_ip(ENetAddress *address, char *name, size_t nameLength) {
5038         if (inet_ntop(AF_INET6, &address->host, name, nameLength) == NULL) {
5039             return -1;
5040         }
5041 
5042         return 0;
5043     }
5044 
enet_address_get_host(ENetAddress * address,char * name,size_t nameLength)5045     int enet_address_get_host(ENetAddress *address, char *name, size_t nameLength) {
5046         struct sockaddr_in6 sin;
5047         int err;
5048 
5049         memset(&sin, 0, sizeof(struct sockaddr_in6));
5050 
5051         sin.sin6_family = AF_INET6;
5052         sin.sin6_port = ENET_HOST_TO_NET_16 (address->port);
5053         sin.sin6_addr = address->host;
5054         sin.sin6_scope_id = address->sin6_scope_id;
5055 
5056         err = getnameinfo((struct sockaddr *) &sin, sizeof(sin), name, nameLength, NULL, 0, NI_NAMEREQD);
5057         if (!err) {
5058             if (name != NULL && nameLength > 0 && !memchr(name, '\0', nameLength)) {
5059                 return -1;
5060             }
5061             return 0;
5062         }
5063         if (err != EAI_NONAME) {
5064             return -1;
5065         }
5066 
5067         return enet_address_get_host_ip(address, name, nameLength);
5068     } /* enet_address_get_host */
5069 
enet_socket_bind(ENetSocket socket,ENetAddress * address)5070     int enet_socket_bind(ENetSocket socket, ENetAddress *address) {
5071         struct sockaddr_in6 sin;
5072         memset(&sin, 0, sizeof(struct sockaddr_in6));
5073         sin.sin6_family = AF_INET6;
5074 
5075         if (address != NULL) {
5076             sin.sin6_port       = ENET_HOST_TO_NET_16(address->port);
5077             sin.sin6_addr       = address->host;
5078             sin.sin6_scope_id   = address->sin6_scope_id;
5079         } else {
5080             sin.sin6_port       = 0;
5081             sin.sin6_addr       = ENET_HOST_ANY;
5082             sin.sin6_scope_id   = 0;
5083         }
5084 
5085         return bind(socket, (struct sockaddr *)&sin, sizeof(struct sockaddr_in6));
5086     }
5087 
enet_socket_get_address(ENetSocket socket,ENetAddress * address)5088     int enet_socket_get_address(ENetSocket socket, ENetAddress *address) {
5089         struct sockaddr_in6 sin;
5090         socklen_t sinLength = sizeof(struct sockaddr_in6);
5091 
5092         if (getsockname(socket, (struct sockaddr *) &sin, &sinLength) == -1) {
5093             return -1;
5094         }
5095 
5096         address->host           = sin.sin6_addr;
5097         address->port           = ENET_NET_TO_HOST_16(sin.sin6_port);
5098         address->sin6_scope_id  = sin.sin6_scope_id;
5099 
5100         return 0;
5101     }
5102 
enet_socket_listen(ENetSocket socket,int backlog)5103     int enet_socket_listen(ENetSocket socket, int backlog) {
5104         return listen(socket, backlog < 0 ? SOMAXCONN : backlog);
5105     }
5106 
enet_socket_create(ENetSocketType type)5107     ENetSocket enet_socket_create(ENetSocketType type) {
5108         return socket(PF_INET6, type == ENET_SOCKET_TYPE_DATAGRAM ? SOCK_DGRAM : SOCK_STREAM, 0);
5109     }
5110 
enet_socket_set_option(ENetSocket socket,ENetSocketOption option,int value)5111     int enet_socket_set_option(ENetSocket socket, ENetSocketOption option, int value) {
5112         int result = -1;
5113 
5114         switch (option) {
5115             case ENET_SOCKOPT_NONBLOCK:
5116                 result = fcntl(socket, F_SETFL, (value ? O_NONBLOCK : 0) | (fcntl(socket, F_GETFL) & ~O_NONBLOCK));
5117                 break;
5118 
5119             case ENET_SOCKOPT_BROADCAST:
5120                 result = setsockopt(socket, SOL_SOCKET, SO_BROADCAST, (char *)&value, sizeof(int));
5121                 break;
5122 
5123             case ENET_SOCKOPT_REUSEADDR:
5124                 result = setsockopt(socket, SOL_SOCKET, SO_REUSEADDR, (char *)&value, sizeof(int));
5125                 break;
5126 
5127             case ENET_SOCKOPT_RCVBUF:
5128                 result = setsockopt(socket, SOL_SOCKET, SO_RCVBUF, (char *)&value, sizeof(int));
5129                 break;
5130 
5131             case ENET_SOCKOPT_SNDBUF:
5132                 result = setsockopt(socket, SOL_SOCKET, SO_SNDBUF, (char *)&value, sizeof(int));
5133                 break;
5134 
5135             case ENET_SOCKOPT_RCVTIMEO: {
5136                 struct timeval timeVal;
5137                 timeVal.tv_sec  = value / 1000;
5138                 timeVal.tv_usec = (value % 1000) * 1000;
5139                 result = setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeVal, sizeof(struct timeval));
5140                 break;
5141             }
5142 
5143             case ENET_SOCKOPT_SNDTIMEO: {
5144                 struct timeval timeVal;
5145                 timeVal.tv_sec  = value / 1000;
5146                 timeVal.tv_usec = (value % 1000) * 1000;
5147                 result = setsockopt(socket, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeVal, sizeof(struct timeval));
5148                 break;
5149             }
5150 
5151             case ENET_SOCKOPT_NODELAY:
5152                 result = setsockopt(socket, IPPROTO_TCP, TCP_NODELAY, (char *)&value, sizeof(int));
5153                 break;
5154 
5155             case ENET_SOCKOPT_IPV6_V6ONLY:
5156                 result = setsockopt(socket, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&value, sizeof(int));
5157                 break;
5158 
5159             default:
5160                 break;
5161         }
5162         return result == -1 ? -1 : 0;
5163     } /* enet_socket_set_option */
5164 
enet_socket_get_option(ENetSocket socket,ENetSocketOption option,int * value)5165     int enet_socket_get_option(ENetSocket socket, ENetSocketOption option, int *value) {
5166         int result = -1;
5167         socklen_t len;
5168 
5169         switch (option) {
5170             case ENET_SOCKOPT_ERROR:
5171                 len    = sizeof(int);
5172                 result = getsockopt(socket, SOL_SOCKET, SO_ERROR, value, &len);
5173                 break;
5174 
5175             default:
5176                 break;
5177         }
5178         return result == -1 ? -1 : 0;
5179     }
5180 
enet_socket_connect(ENetSocket socket,ENetAddress * address)5181     int enet_socket_connect(ENetSocket socket, ENetAddress *address) {
5182         struct sockaddr_in6 sin;
5183         int result;
5184 
5185         memset(&sin, 0, sizeof(struct sockaddr_in6));
5186 
5187         sin.sin6_family     = AF_INET6;
5188         sin.sin6_port       = ENET_HOST_TO_NET_16(address->port);
5189         sin.sin6_addr       = address->host;
5190         sin.sin6_scope_id   = address->sin6_scope_id;
5191 
5192         result = connect(socket, (struct sockaddr *)&sin, sizeof(struct sockaddr_in6));
5193         if (result == -1 && errno == EINPROGRESS) {
5194             return 0;
5195         }
5196 
5197         return result;
5198     }
5199 
enet_socket_accept(ENetSocket socket,ENetAddress * address)5200     ENetSocket enet_socket_accept(ENetSocket socket, ENetAddress *address) {
5201         int result;
5202         struct sockaddr_in6 sin;
5203         socklen_t sinLength = sizeof(struct sockaddr_in6);
5204 
5205         result = accept(socket,address != NULL ? (struct sockaddr *) &sin : NULL, address != NULL ? &sinLength : NULL);
5206 
5207         if (result == -1) {
5208             return ENET_SOCKET_NULL;
5209         }
5210 
5211         if (address != NULL) {
5212             address->host = sin.sin6_addr;
5213             address->port = ENET_NET_TO_HOST_16 (sin.sin6_port);
5214             address->sin6_scope_id = sin.sin6_scope_id;
5215         }
5216 
5217         return result;
5218     }
5219 
enet_socket_shutdown(ENetSocket socket,ENetSocketShutdown how)5220     int enet_socket_shutdown(ENetSocket socket, ENetSocketShutdown how) {
5221         return shutdown(socket, (int) how);
5222     }
5223 
enet_socket_destroy(ENetSocket socket)5224     void enet_socket_destroy(ENetSocket socket) {
5225         if (socket != -1) {
5226             close(socket);
5227         }
5228     }
5229 
enet_socket_send(ENetSocket socket,ENetAddress * address,ENetBuffer * buffers,size_t bufferCount)5230     int enet_socket_send(ENetSocket socket, ENetAddress *address, ENetBuffer *buffers, size_t bufferCount) {
5231         struct msghdr msgHdr;
5232         struct sockaddr_in6 sin;
5233         int sentLength;
5234 
5235         memset(&msgHdr, 0, sizeof(struct msghdr));
5236 
5237         if (address != NULL) {
5238             memset(&sin, 0, sizeof(struct sockaddr_in6));
5239 
5240             sin.sin6_family     = AF_INET6;
5241             sin.sin6_port       = ENET_HOST_TO_NET_16(address->port);
5242             sin.sin6_addr       = address->host;
5243             sin.sin6_scope_id   = address->sin6_scope_id;
5244 
5245             msgHdr.msg_name    = &sin;
5246             msgHdr.msg_namelen = sizeof(struct sockaddr_in6);
5247         }
5248 
5249         msgHdr.msg_iov    = (struct iovec *) buffers;
5250         msgHdr.msg_iovlen = bufferCount;
5251 
5252         sentLength = sendmsg(socket, &msgHdr, MSG_NOSIGNAL);
5253 
5254         if (sentLength == -1) {
5255             if (errno == EWOULDBLOCK) {
5256                 return 0;
5257             }
5258 
5259             return -1;
5260         }
5261 
5262         return sentLength;
5263     } /* enet_socket_send */
5264 
enet_socket_receive(ENetSocket socket,ENetAddress * address,ENetBuffer * buffers,size_t bufferCount)5265     int enet_socket_receive(ENetSocket socket, ENetAddress *address, ENetBuffer *buffers, size_t bufferCount) {
5266         struct msghdr msgHdr;
5267         struct sockaddr_in6 sin;
5268         int recvLength;
5269 
5270         memset(&msgHdr, 0, sizeof(struct msghdr));
5271 
5272         if (address != NULL) {
5273             msgHdr.msg_name    = &sin;
5274             msgHdr.msg_namelen = sizeof(struct sockaddr_in6);
5275         }
5276 
5277         msgHdr.msg_iov    = (struct iovec *) buffers;
5278         msgHdr.msg_iovlen = bufferCount;
5279 
5280         recvLength = recvmsg(socket, &msgHdr, MSG_NOSIGNAL);
5281 
5282         if (recvLength == -1) {
5283             if (errno == EWOULDBLOCK) {
5284                 return 0;
5285             }
5286 
5287             return -1;
5288         }
5289 
5290         if (msgHdr.msg_flags & MSG_TRUNC) {
5291             return -1;
5292         }
5293 
5294         if (address != NULL) {
5295             address->host           = sin.sin6_addr;
5296             address->port           = ENET_NET_TO_HOST_16(sin.sin6_port);
5297             address->sin6_scope_id  = sin.sin6_scope_id;
5298         }
5299 
5300         return recvLength;
5301     } /* enet_socket_receive */
5302 
enet_socketset_select(ENetSocket maxSocket,ENetSocketSet * readSet,ENetSocketSet * writeSet,enet_uint32 timeout)5303     int enet_socketset_select(ENetSocket maxSocket, ENetSocketSet *readSet, ENetSocketSet *writeSet, enet_uint32 timeout) {
5304         struct timeval timeVal;
5305 
5306         timeVal.tv_sec  = timeout / 1000;
5307         timeVal.tv_usec = (timeout % 1000) * 1000;
5308 
5309         return select(maxSocket + 1, readSet, writeSet, NULL, &timeVal);
5310     }
5311 
enet_socket_wait(ENetSocket socket,enet_uint32 * condition,enet_uint64 timeout)5312     int enet_socket_wait(ENetSocket socket, enet_uint32 *condition, enet_uint64 timeout) {
5313         struct pollfd pollSocket;
5314         int pollCount;
5315 
5316         pollSocket.fd     = socket;
5317         pollSocket.events = 0;
5318 
5319         if (*condition & ENET_SOCKET_WAIT_SEND) {
5320             pollSocket.events |= POLLOUT;
5321         }
5322 
5323         if (*condition & ENET_SOCKET_WAIT_RECEIVE) {
5324             pollSocket.events |= POLLIN;
5325         }
5326 
5327         pollCount = poll(&pollSocket, 1, timeout);
5328 
5329         if (pollCount < 0) {
5330             if (errno == EINTR && *condition & ENET_SOCKET_WAIT_INTERRUPT) {
5331                 *condition = ENET_SOCKET_WAIT_INTERRUPT;
5332 
5333                 return 0;
5334             }
5335 
5336             return -1;
5337         }
5338 
5339         *condition = ENET_SOCKET_WAIT_NONE;
5340 
5341         if (pollCount == 0) {
5342             return 0;
5343         }
5344 
5345         if (pollSocket.revents & POLLOUT) {
5346             *condition |= ENET_SOCKET_WAIT_SEND;
5347         }
5348 
5349         if (pollSocket.revents & POLLIN) {
5350             *condition |= ENET_SOCKET_WAIT_RECEIVE;
5351         }
5352 
5353         return 0;
5354     } /* enet_socket_wait */
5355 
5356     #endif // !_WIN32
5357 
5358 
5359 // =======================================================================//
5360 // !
5361 // ! Platform Specific (Win)
5362 // !
5363 // =======================================================================//
5364 
5365     #ifdef _WIN32
5366 
5367     static int is_enet_initialized = 0;
5368 
enet_initialize(void)5369     int enet_initialize(void) {
5370         WORD versionRequested = MAKEWORD(1, 1);
5371         WSADATA wsaData;
5372 
5373         if (WSAStartup(versionRequested, &wsaData)) {
5374             return -1;
5375         }
5376 
5377         if (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1) {
5378             WSACleanup();
5379             return -1;
5380         }
5381 
5382         timeBeginPeriod(1);
5383         is_enet_initialized = 1;
5384         return 0;
5385     }
5386 
enet_deinitialize(void)5387     void enet_deinitialize(void) {
5388         if (is_enet_initialized) {
5389             timeEndPeriod(1);
5390             WSACleanup();
5391             is_enet_initialized = 0;
5392         }
5393     }
5394 
enet_host_random_seed(void)5395     enet_uint64 enet_host_random_seed(void) {
5396         return (enet_uint64) timeGetTime();
5397     }
5398 
enet_address_set_host_ip(ENetAddress * address,char * name)5399     int enet_address_set_host_ip(ENetAddress *address, char *name) {
5400         enet_uint8 vals[4] = { 0, 0, 0, 0 };
5401         int i;
5402 
5403         for (i = 0; i < 4; ++i) {
5404             char *next = name + 1;
5405             if (*name != '0') {
5406                 long val = strtol(name, (char **) &next, 10);
5407                 if (val < 0 || val > 255 || next == name || next - name > 3) {
5408                     return -1;
5409                 }
5410                 vals[i] = (enet_uint8) val;
5411             }
5412 
5413             if (*next != (i < 3 ? '.' : '\0')) {
5414                 return -1;
5415             }
5416             name = next + 1;
5417         }
5418 
5419         memcpy(&address->host, vals, sizeof(enet_uint32));
5420         return 0;
5421     }
5422 
enet_pton(int const af,const char * const src,void * const dst)5423     int enet_pton(int const af, const char * const src, void * const dst) {
5424         struct sockaddr_storage ss;
5425 
5426         int  size = sizeof(ss);
5427         char src_copy[INET6_ADDRSTRLEN + 1];
5428 
5429         ZeroMemory(&ss, sizeof(ss));
5430 
5431         strncpy(src_copy, src, INET6_ADDRSTRLEN + 1);
5432         src_copy[INET6_ADDRSTRLEN] = 0;
5433 
5434         if (WSAStringToAddress(src_copy, af, NULL, (struct sockaddr *)&ss, &size) == 0) {
5435             switch (af) {
5436                 case AF_INET:
5437                     *(struct in_addr *)dst = ((struct sockaddr_in *)&ss)->sin_addr;
5438                     return 1;
5439                 case AF_INET6:
5440                     *(struct in6_addr *)dst = ((struct sockaddr_in6 *)&ss)->sin6_addr;
5441                     return 1;
5442             }
5443         }
5444 
5445         return 0;
5446     }
5447 
enet_address_set_host(ENetAddress * address,char * name)5448     int enet_address_set_host(ENetAddress *address, char *name) {
5449         struct hostent *hostEntry = NULL;
5450         hostEntry = gethostbyname(name);
5451 
5452         if (hostEntry == NULL || hostEntry->h_addrtype != AF_INET) {
5453             if (!enet_pton(AF_INET6, name, &address->host)) {
5454                 return -1;
5455             }
5456 
5457             return 0;
5458         }
5459 
5460         ((enet_uint32 *)&address->host.s6_addr)[0] = 0;
5461         ((enet_uint32 *)&address->host.s6_addr)[1] = 0;
5462         ((enet_uint32 *)&address->host.s6_addr)[2] = htonl(0xffff);
5463         ((enet_uint32 *)&address->host.s6_addr)[3] = *(enet_uint32 *)hostEntry->h_addr_list[0];
5464 
5465         return 0;
5466     }
5467 
enet_ntop(int const af,void const * const src,char * const dst,socklen_t const cnt)5468     char const *enet_ntop(int const af, void const *const src, char *const dst, socklen_t const cnt) {
5469         if (af == AF_INET) {
5470             struct sockaddr_in in;
5471             memset(&in, 0, sizeof(in));
5472             in.sin_family = AF_INET;
5473             memcpy(&in.sin_addr, src, sizeof(struct in_addr));
5474             getnameinfo((struct sockaddr *)&in, sizeof(struct sockaddr_in), dst, cnt, NULL, 0, NI_NUMERICHOST);
5475             return dst;
5476         } else if (af == AF_INET6) {
5477             struct sockaddr_in6 in;
5478             memset(&in, 0, sizeof(in));
5479             in.sin6_family = AF_INET6;
5480             memcpy(&in.sin6_addr, src, sizeof(struct in_addr6));
5481             getnameinfo((struct sockaddr *)&in, sizeof(struct sockaddr_in6), dst, cnt, NULL, 0, NI_NUMERICHOST);
5482             return dst;
5483         }
5484 
5485         return NULL;
5486     }
5487 
enet_address_get_host_ip(ENetAddress * address,char * name,size_t nameLength)5488     int enet_address_get_host_ip(ENetAddress *address, char *name, size_t nameLength) {
5489         if (enet_ntop(AF_INET6, (PVOID)&address->host, name, nameLength) == NULL) {
5490             return -1;
5491         }
5492 
5493         return 0;
5494     }
5495 
enet_address_get_host(ENetAddress * address,char * name,size_t nameLength)5496     int enet_address_get_host(ENetAddress *address, char *name, size_t nameLength) {
5497         struct in6_addr in;
5498         struct hostent *hostEntry = NULL;
5499 
5500         in = address->host;
5501         hostEntry = gethostbyaddr((char *)&in, sizeof(struct in6_addr), AF_INET6);
5502 
5503         if (hostEntry == NULL) {
5504             return enet_address_get_host_ip(address, name, nameLength);
5505         } else {
5506             size_t hostLen = strlen(hostEntry->h_name);
5507             if (hostLen >= nameLength) {
5508                 return -1;
5509             }
5510             memcpy(name, hostEntry->h_name, hostLen + 1);
5511         }
5512 
5513         return 0;
5514     }
5515 
enet_socket_bind(ENetSocket socket,ENetAddress * address)5516     int enet_socket_bind(ENetSocket socket, ENetAddress *address) {
5517         struct sockaddr_in6 sin;
5518         memset(&sin, 0, sizeof(struct sockaddr_in6));
5519         sin.sin6_family = AF_INET6;
5520 
5521         if (address != NULL) {
5522             sin.sin6_port       = ENET_HOST_TO_NET_16 (address->port);
5523             sin.sin6_addr       = address->host;
5524             sin.sin6_scope_id   = address->sin6_scope_id;
5525         } else   {
5526             sin.sin6_port       = 0;
5527             sin.sin6_addr       = in6addr_any;
5528             sin.sin6_scope_id   = 0;
5529         }
5530 
5531         return bind(socket, (struct sockaddr *) &sin, sizeof(struct sockaddr_in6)) == SOCKET_ERROR ? -1 : 0;
5532     }
5533 
enet_socket_get_address(ENetSocket socket,ENetAddress * address)5534     int enet_socket_get_address(ENetSocket socket, ENetAddress *address) {
5535         struct sockaddr_in6 sin;
5536         int sinLength = sizeof(struct sockaddr_in6);
5537 
5538         if (getsockname(socket, (struct sockaddr *) &sin, &sinLength) == -1) {
5539             return -1;
5540         }
5541 
5542         address->host           = sin.sin6_addr;
5543         address->port           = ENET_NET_TO_HOST_16(sin.sin6_port);
5544         address->sin6_scope_id  = sin.sin6_scope_id;
5545 
5546         return 0;
5547     }
5548 
enet_socket_listen(ENetSocket socket,int backlog)5549     int enet_socket_listen(ENetSocket socket, int backlog) {
5550         return listen(socket, backlog < 0 ? SOMAXCONN : backlog) == SOCKET_ERROR ? -1 : 0;
5551     }
5552 
enet_socket_create(ENetSocketType type)5553     ENetSocket enet_socket_create(ENetSocketType type) {
5554         return socket(PF_INET6, type == ENET_SOCKET_TYPE_DATAGRAM ? SOCK_DGRAM : SOCK_STREAM, 0);
5555     }
5556 
enet_socket_set_option(ENetSocket socket,ENetSocketOption option,int value)5557     int enet_socket_set_option(ENetSocket socket, ENetSocketOption option, int value) {
5558         int result = SOCKET_ERROR;
5559 
5560         switch (option) {
5561             case ENET_SOCKOPT_NONBLOCK: {
5562                 u_long nonBlocking = (u_long) value;
5563                 result = ioctlsocket(socket, FIONBIO, &nonBlocking);
5564                 break;
5565             }
5566 
5567             case ENET_SOCKOPT_BROADCAST:
5568                 result = setsockopt(socket, SOL_SOCKET, SO_BROADCAST, (char *)&value, sizeof(int));
5569                 break;
5570 
5571             case ENET_SOCKOPT_REUSEADDR:
5572                 result = setsockopt(socket, SOL_SOCKET, SO_REUSEADDR, (char *)&value, sizeof(int));
5573                 break;
5574 
5575             case ENET_SOCKOPT_RCVBUF:
5576                 result = setsockopt(socket, SOL_SOCKET, SO_RCVBUF, (char *)&value, sizeof(int));
5577                 break;
5578 
5579             case ENET_SOCKOPT_SNDBUF:
5580                 result = setsockopt(socket, SOL_SOCKET, SO_SNDBUF, (char *)&value, sizeof(int));
5581                 break;
5582 
5583             case ENET_SOCKOPT_RCVTIMEO:
5584                 result = setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, (char *)&value, sizeof(int));
5585                 break;
5586 
5587             case ENET_SOCKOPT_SNDTIMEO:
5588                 result = setsockopt(socket, SOL_SOCKET, SO_SNDTIMEO, (char *)&value, sizeof(int));
5589                 break;
5590 
5591             case ENET_SOCKOPT_NODELAY:
5592                 result = setsockopt(socket, IPPROTO_TCP, TCP_NODELAY, (char *)&value, sizeof(int));
5593                 break;
5594 
5595             case ENET_SOCKOPT_IPV6_V6ONLY:
5596                 result = setsockopt(socket, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&value, sizeof(int));
5597                 break;
5598 
5599             default:
5600                 break;
5601         }
5602         return result == SOCKET_ERROR ? -1 : 0;
5603     } /* enet_socket_set_option */
5604 
enet_socket_get_option(ENetSocket socket,ENetSocketOption option,int * value)5605     int enet_socket_get_option(ENetSocket socket, ENetSocketOption option, int *value) {
5606         int result = SOCKET_ERROR, len;
5607 
5608         switch (option) {
5609             case ENET_SOCKOPT_ERROR:
5610                 len    = sizeof(int);
5611                 result = getsockopt(socket, SOL_SOCKET, SO_ERROR, (char *)value, &len);
5612                 break;
5613 
5614             default:
5615                 break;
5616         }
5617         return result == SOCKET_ERROR ? -1 : 0;
5618     }
5619 
enet_socket_connect(ENetSocket socket,ENetAddress * address)5620     int enet_socket_connect(ENetSocket socket, ENetAddress *address) {
5621         struct sockaddr_in6 sin;
5622         int result;
5623 
5624         memset(&sin, 0, sizeof(struct sockaddr_in6));
5625 
5626         sin.sin6_family     = AF_INET6;
5627         sin.sin6_port       = ENET_HOST_TO_NET_16(address->port);
5628         sin.sin6_addr       = address->host;
5629         sin.sin6_scope_id   = address->sin6_scope_id;
5630 
5631         result = connect(socket, (struct sockaddr *) &sin, sizeof(struct sockaddr_in6));
5632         if (result == SOCKET_ERROR && WSAGetLastError() != WSAEWOULDBLOCK) {
5633             return -1;
5634         }
5635 
5636         return 0;
5637     }
5638 
enet_socket_accept(ENetSocket socket,ENetAddress * address)5639     ENetSocket enet_socket_accept(ENetSocket socket, ENetAddress *address) {
5640         SOCKET result;
5641         struct sockaddr_in6 sin;
5642         int sinLength = sizeof(struct sockaddr_in6);
5643 
5644         result = accept(socket, address != NULL ? (struct sockaddr *)&sin : NULL, address != NULL ? &sinLength : NULL);
5645 
5646         if (result == INVALID_SOCKET) {
5647             return ENET_SOCKET_NULL;
5648         }
5649 
5650         if (address != NULL) {
5651             address->host           = sin.sin6_addr;
5652             address->port           = ENET_NET_TO_HOST_16(sin.sin6_port);
5653             address->sin6_scope_id  = sin.sin6_scope_id;
5654         }
5655 
5656         return result;
5657     }
5658 
enet_socket_shutdown(ENetSocket socket,ENetSocketShutdown how)5659     int enet_socket_shutdown(ENetSocket socket, ENetSocketShutdown how) {
5660         return shutdown(socket, (int) how) == SOCKET_ERROR ? -1 : 0;
5661     }
5662 
enet_socket_destroy(ENetSocket socket)5663     void enet_socket_destroy(ENetSocket socket) {
5664         if (socket != INVALID_SOCKET) {
5665             closesocket(socket);
5666         }
5667     }
5668 
enet_socket_send(ENetSocket socket,ENetAddress * address,ENetBuffer * buffers,size_t bufferCount)5669     int enet_socket_send(ENetSocket socket, ENetAddress *address, ENetBuffer *buffers, size_t bufferCount) {
5670         struct sockaddr_in6 sin;
5671         DWORD sentLength;
5672 
5673         if (address != NULL) {
5674             memset(&sin, 0, sizeof(struct sockaddr_in6));
5675 
5676             sin.sin6_family     = AF_INET6;
5677             sin.sin6_port       = ENET_HOST_TO_NET_16(address->port);
5678             sin.sin6_addr       = address->host;
5679             sin.sin6_scope_id   = address->sin6_scope_id;
5680         }
5681 
5682         if (WSASendTo(socket,
5683             (LPWSABUF) buffers,
5684             (DWORD) bufferCount,
5685             &sentLength,
5686             0,
5687             address != NULL ? (struct sockaddr *) &sin : NULL,
5688             address != NULL ? sizeof(struct sockaddr_in6) : 0,
5689             NULL,
5690             NULL) == SOCKET_ERROR
5691         ) {
5692             return (WSAGetLastError() == WSAEWOULDBLOCK) ? 0 : -1;
5693         }
5694 
5695         return (int) sentLength;
5696     }
5697 
enet_socket_receive(ENetSocket socket,ENetAddress * address,ENetBuffer * buffers,size_t bufferCount)5698     int enet_socket_receive(ENetSocket socket, ENetAddress *address, ENetBuffer *buffers, size_t bufferCount) {
5699         INT sinLength = sizeof(struct sockaddr_in6);
5700         DWORD flags   = 0, recvLength;
5701         struct sockaddr_in6 sin;
5702 
5703         if (WSARecvFrom(socket,
5704             (LPWSABUF) buffers,
5705             (DWORD) bufferCount,
5706             &recvLength,
5707             &flags,
5708             address != NULL ? (struct sockaddr *) &sin : NULL,
5709             address != NULL ? &sinLength : NULL,
5710             NULL,
5711             NULL) == SOCKET_ERROR
5712         ) {
5713             switch (WSAGetLastError()) {
5714                 case WSAEWOULDBLOCK:
5715                 case WSAECONNRESET:
5716                     return 0;
5717             }
5718 
5719             return -1;
5720         }
5721 
5722         if (flags & MSG_PARTIAL) {
5723             return -1;
5724         }
5725 
5726         if (address != NULL) {
5727             address->host           = sin.sin6_addr;
5728             address->port           = ENET_NET_TO_HOST_16(sin.sin6_port);
5729             address->sin6_scope_id  = sin.sin6_scope_id;
5730         }
5731 
5732         return (int) recvLength;
5733     } /* enet_socket_receive */
5734 
enet_socketset_select(ENetSocket maxSocket,ENetSocketSet * readSet,ENetSocketSet * writeSet,enet_uint32 timeout)5735     int enet_socketset_select(ENetSocket maxSocket, ENetSocketSet *readSet, ENetSocketSet *writeSet, enet_uint32 timeout) {
5736         struct timeval timeVal;
5737 
5738         timeVal.tv_sec  = timeout / 1000;
5739         timeVal.tv_usec = (timeout % 1000) * 1000;
5740 
5741         return select(maxSocket + 1, readSet, writeSet, NULL, &timeVal);
5742     }
5743 
enet_socket_wait(ENetSocket socket,enet_uint32 * condition,enet_uint64 timeout)5744     int enet_socket_wait(ENetSocket socket, enet_uint32 *condition, enet_uint64 timeout) {
5745         fd_set readSet, writeSet;
5746         struct timeval timeVal;
5747         int selectCount;
5748 
5749         timeVal.tv_sec  = timeout / 1000;
5750         timeVal.tv_usec = (timeout % 1000) * 1000;
5751 
5752         FD_ZERO(&readSet);
5753         FD_ZERO(&writeSet);
5754 
5755         if (*condition & ENET_SOCKET_WAIT_SEND) {
5756             FD_SET(socket, &writeSet);
5757         }
5758 
5759         if (*condition & ENET_SOCKET_WAIT_RECEIVE) {
5760             FD_SET(socket, &readSet);
5761         }
5762 
5763         selectCount = select(socket + 1, &readSet, &writeSet, NULL, &timeVal);
5764 
5765         if (selectCount < 0) {
5766             return -1;
5767         }
5768 
5769         *condition = ENET_SOCKET_WAIT_NONE;
5770 
5771         if (selectCount == 0) {
5772             return 0;
5773         }
5774 
5775         if (FD_ISSET(socket, &writeSet)) {
5776             *condition |= ENET_SOCKET_WAIT_SEND;
5777         }
5778 
5779         if (FD_ISSET(socket, &readSet)) {
5780             *condition |= ENET_SOCKET_WAIT_RECEIVE;
5781         }
5782 
5783         return 0;
5784     } /* enet_socket_wait */
5785 
5786     #endif // _WIN32
5787 
5788 
5789 #ifdef __cplusplus
5790 }
5791 #endif
5792 
5793 #endif // ENET_IMPLEMENTATION
5794 #endif // ENET_INCLUDE_H
5795