1 /**
2  @file  protocol.c
3  @brief ENet protocol functions
4 */
5 #include <stdio.h>
6 #include <string.h>
7 #define ENET_BUILDING_LIB 1
8 #include "enet/utility.h"
9 #include "enet/time.h"
10 #include "enet/enet.h"
11 
12 static size_t commandSizes [ENET_PROTOCOL_COMMAND_COUNT] =
13 {
14     0,
15     sizeof (ENetProtocolAcknowledge),
16     sizeof (ENetProtocolConnect),
17     sizeof (ENetProtocolVerifyConnect),
18     sizeof (ENetProtocolDisconnect),
19     sizeof (ENetProtocolPing),
20     sizeof (ENetProtocolSendReliable),
21     sizeof (ENetProtocolSendUnreliable),
22     sizeof (ENetProtocolSendFragment),
23     sizeof (ENetProtocolSendUnsequenced),
24     sizeof (ENetProtocolBandwidthLimit),
25     sizeof (ENetProtocolThrottleConfigure),
26     sizeof (ENetProtocolSendFragment)
27 };
28 
29 size_t
enet_protocol_command_size(enet_uint8 commandNumber)30 enet_protocol_command_size (enet_uint8 commandNumber)
31 {
32     return commandSizes [commandNumber & ENET_PROTOCOL_COMMAND_MASK];
33 }
34 
35 static void
enet_protocol_change_state(ENetHost * host,ENetPeer * peer,ENetPeerState state)36 enet_protocol_change_state (ENetHost * host, ENetPeer * peer, ENetPeerState state)
37 {
38     if (state == ENET_PEER_STATE_CONNECTED || state == ENET_PEER_STATE_DISCONNECT_LATER)
39       enet_peer_on_connect (peer);
40     else
41       enet_peer_on_disconnect (peer);
42 
43     peer -> state = state;
44 }
45 
46 static void
enet_protocol_dispatch_state(ENetHost * host,ENetPeer * peer,ENetPeerState state)47 enet_protocol_dispatch_state (ENetHost * host, ENetPeer * peer, ENetPeerState state)
48 {
49     enet_protocol_change_state (host, peer, state);
50 
51     if (! peer -> needsDispatch)
52     {
53        enet_list_insert (enet_list_end (& host -> dispatchQueue), & peer -> dispatchList);
54 
55        peer -> needsDispatch = 1;
56     }
57 }
58 
59 static int
enet_protocol_dispatch_incoming_commands(ENetHost * host,ENetEvent * event)60 enet_protocol_dispatch_incoming_commands (ENetHost * host, ENetEvent * event)
61 {
62     while (! enet_list_empty (& host -> dispatchQueue))
63     {
64        ENetPeer * peer = (ENetPeer *) enet_list_remove (enet_list_begin (& host -> dispatchQueue));
65 
66        peer -> needsDispatch = 0;
67 
68        switch (peer -> state)
69        {
70        case ENET_PEER_STATE_CONNECTION_PENDING:
71        case ENET_PEER_STATE_CONNECTION_SUCCEEDED:
72            enet_protocol_change_state (host, peer, ENET_PEER_STATE_CONNECTED);
73 
74            event -> type = ENET_EVENT_TYPE_CONNECT;
75            event -> peer = peer;
76            event -> data = peer -> eventData;
77 
78            return 1;
79 
80        case ENET_PEER_STATE_ZOMBIE:
81            host -> recalculateBandwidthLimits = 1;
82 
83            event -> type = ENET_EVENT_TYPE_DISCONNECT;
84            event -> peer = peer;
85            event -> data = peer -> eventData;
86 
87            enet_peer_reset (peer);
88 
89            return 1;
90 
91        case ENET_PEER_STATE_CONNECTED:
92            if (enet_list_empty (& peer -> dispatchedCommands))
93              continue;
94 
95            event -> packet = enet_peer_receive (peer, & event -> channelID);
96            if (event -> packet == NULL)
97              continue;
98 
99            event -> type = ENET_EVENT_TYPE_RECEIVE;
100            event -> peer = peer;
101 
102            if (! enet_list_empty (& peer -> dispatchedCommands))
103            {
104               peer -> needsDispatch = 1;
105 
106               enet_list_insert (enet_list_end (& host -> dispatchQueue), & peer -> dispatchList);
107            }
108 
109            return 1;
110 
111        default:
112            break;
113        }
114     }
115 
116     return 0;
117 }
118 
119 static void
enet_protocol_notify_connect(ENetHost * host,ENetPeer * peer,ENetEvent * event)120 enet_protocol_notify_connect (ENetHost * host, ENetPeer * peer, ENetEvent * event)
121 {
122     host -> recalculateBandwidthLimits = 1;
123 
124     if (event != NULL)
125     {
126         enet_protocol_change_state (host, peer, ENET_PEER_STATE_CONNECTED);
127 
128         event -> type = ENET_EVENT_TYPE_CONNECT;
129         event -> peer = peer;
130         event -> data = peer -> eventData;
131     }
132     else
133         enet_protocol_dispatch_state (host, peer, peer -> state == ENET_PEER_STATE_CONNECTING ? ENET_PEER_STATE_CONNECTION_SUCCEEDED : ENET_PEER_STATE_CONNECTION_PENDING);
134 }
135 
136 static void
enet_protocol_notify_disconnect(ENetHost * host,ENetPeer * peer,ENetEvent * event)137 enet_protocol_notify_disconnect (ENetHost * host, ENetPeer * peer, ENetEvent * event)
138 {
139     if (peer -> state >= ENET_PEER_STATE_CONNECTION_PENDING)
140        host -> recalculateBandwidthLimits = 1;
141 
142     if (peer -> state != ENET_PEER_STATE_CONNECTING && peer -> state < ENET_PEER_STATE_CONNECTION_SUCCEEDED)
143         enet_peer_reset (peer);
144     else
145     if (event != NULL)
146     {
147         event -> type = ENET_EVENT_TYPE_DISCONNECT;
148         event -> peer = peer;
149         event -> data = 0;
150 
151         enet_peer_reset (peer);
152     }
153     else
154     {
155         peer -> eventData = 0;
156 
157         enet_protocol_dispatch_state (host, peer, ENET_PEER_STATE_ZOMBIE);
158     }
159 }
160 
161 static void
enet_protocol_remove_sent_unreliable_commands(ENetPeer * peer)162 enet_protocol_remove_sent_unreliable_commands (ENetPeer * peer)
163 {
164     ENetOutgoingCommand * outgoingCommand;
165 
166     while (! enet_list_empty (& peer -> sentUnreliableCommands))
167     {
168         outgoingCommand = (ENetOutgoingCommand *) enet_list_front (& peer -> sentUnreliableCommands);
169 
170         enet_list_remove (& outgoingCommand -> outgoingCommandList);
171 
172         if (outgoingCommand -> packet != NULL)
173         {
174            -- outgoingCommand -> packet -> referenceCount;
175 
176            if (outgoingCommand -> packet -> referenceCount == 0)
177            {
178               outgoingCommand -> packet -> flags |= ENET_PACKET_FLAG_SENT;
179 
180               enet_packet_destroy (outgoingCommand -> packet);
181            }
182         }
183 
184         enet_free (outgoingCommand);
185     }
186 }
187 
188 static ENetProtocolCommand
enet_protocol_remove_sent_reliable_command(ENetPeer * peer,enet_uint16 reliableSequenceNumber,enet_uint8 channelID)189 enet_protocol_remove_sent_reliable_command (ENetPeer * peer, enet_uint16 reliableSequenceNumber, enet_uint8 channelID)
190 {
191     ENetOutgoingCommand * outgoingCommand = NULL;
192     ENetListIterator currentCommand;
193     ENetProtocolCommand commandNumber;
194     int wasSent = 1;
195 
196     for (currentCommand = enet_list_begin (& peer -> sentReliableCommands);
197          currentCommand != enet_list_end (& peer -> sentReliableCommands);
198          currentCommand = enet_list_next (currentCommand))
199     {
200        outgoingCommand = (ENetOutgoingCommand *) currentCommand;
201 
202        if (outgoingCommand -> reliableSequenceNumber == reliableSequenceNumber &&
203            outgoingCommand -> command.header.channelID == channelID)
204          break;
205     }
206 
207     if (currentCommand == enet_list_end (& peer -> sentReliableCommands))
208     {
209        for (currentCommand = enet_list_begin (& peer -> outgoingReliableCommands);
210             currentCommand != enet_list_end (& peer -> outgoingReliableCommands);
211             currentCommand = enet_list_next (currentCommand))
212        {
213           outgoingCommand = (ENetOutgoingCommand *) currentCommand;
214 
215           if (outgoingCommand -> sendAttempts < 1) return ENET_PROTOCOL_COMMAND_NONE;
216 
217           if (outgoingCommand -> reliableSequenceNumber == reliableSequenceNumber &&
218               outgoingCommand -> command.header.channelID == channelID)
219             break;
220        }
221 
222        if (currentCommand == enet_list_end (& peer -> outgoingReliableCommands))
223          return ENET_PROTOCOL_COMMAND_NONE;
224 
225        wasSent = 0;
226     }
227 
228     if (outgoingCommand == NULL)
229       return ENET_PROTOCOL_COMMAND_NONE;
230 
231     if (channelID < peer -> channelCount)
232     {
233        ENetChannel * channel = & peer -> channels [channelID];
234        enet_uint16 reliableWindow = reliableSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE;
235        if (channel -> reliableWindows [reliableWindow] > 0)
236        {
237           -- channel -> reliableWindows [reliableWindow];
238           if (! channel -> reliableWindows [reliableWindow])
239             channel -> usedReliableWindows &= ~ (1 << reliableWindow);
240        }
241     }
242 
243     commandNumber = (ENetProtocolCommand) (outgoingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_MASK);
244 
245     enet_list_remove (& outgoingCommand -> outgoingCommandList);
246 
247     if (outgoingCommand -> packet != NULL)
248     {
249        if (wasSent)
250          peer -> reliableDataInTransit -= outgoingCommand -> fragmentLength;
251 
252        -- outgoingCommand -> packet -> referenceCount;
253 
254        if (outgoingCommand -> packet -> referenceCount == 0)
255        {
256           outgoingCommand -> packet -> flags |= ENET_PACKET_FLAG_SENT;
257 
258           enet_packet_destroy (outgoingCommand -> packet);
259        }
260     }
261 
262     enet_free (outgoingCommand);
263 
264     if (enet_list_empty (& peer -> sentReliableCommands))
265       return commandNumber;
266 
267     outgoingCommand = (ENetOutgoingCommand *) enet_list_front (& peer -> sentReliableCommands);
268 
269     peer -> nextTimeout = outgoingCommand -> sentTime + outgoingCommand -> roundTripTimeout;
270 
271     return commandNumber;
272 }
273 
274 static ENetPeer *
enet_protocol_handle_connect(ENetHost * host,ENetProtocolHeader * header,ENetProtocol * command)275 enet_protocol_handle_connect (ENetHost * host, ENetProtocolHeader * header, ENetProtocol * command)
276 {
277     enet_uint8 incomingSessionID, outgoingSessionID;
278     enet_uint32 mtu, windowSize;
279     ENetChannel * channel;
280     size_t channelCount, duplicatePeers = 0;
281     ENetPeer * currentPeer, * peer = NULL;
282     ENetProtocol verifyCommand;
283 
284     channelCount = ENET_NET_TO_HOST_32 (command -> connect.channelCount);
285 
286     if (channelCount < ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT ||
287         channelCount > ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT)
288       return NULL;
289 
290     for (currentPeer = host -> peers;
291          currentPeer < & host -> peers [host -> peerCount];
292          ++ currentPeer)
293     {
294         if (currentPeer -> state == ENET_PEER_STATE_DISCONNECTED)
295         {
296             if (peer == NULL)
297               peer = currentPeer;
298         }
299         else
300         if (currentPeer -> state != ENET_PEER_STATE_CONNECTING &&
301             currentPeer -> address.host == host -> receivedAddress.host)
302         {
303             if (currentPeer -> address.port == host -> receivedAddress.port &&
304                 currentPeer -> connectID == command -> connect.connectID)
305               return NULL;
306 
307             ++ duplicatePeers;
308         }
309     }
310 
311     if (peer == NULL || duplicatePeers >= host -> duplicatePeers)
312       return NULL;
313 
314     if (channelCount > host -> channelLimit)
315       channelCount = host -> channelLimit;
316     peer -> channels = (ENetChannel *) enet_malloc (channelCount * sizeof (ENetChannel));
317     if (peer -> channels == NULL)
318       return NULL;
319     peer -> channelCount = channelCount;
320     peer -> state = ENET_PEER_STATE_ACKNOWLEDGING_CONNECT;
321     peer -> connectID = command -> connect.connectID;
322     peer -> address = host -> receivedAddress;
323     peer -> outgoingPeerID = ENET_NET_TO_HOST_16 (command -> connect.outgoingPeerID);
324     peer -> incomingBandwidth = ENET_NET_TO_HOST_32 (command -> connect.incomingBandwidth);
325     peer -> outgoingBandwidth = ENET_NET_TO_HOST_32 (command -> connect.outgoingBandwidth);
326     peer -> packetThrottleInterval = ENET_NET_TO_HOST_32 (command -> connect.packetThrottleInterval);
327     peer -> packetThrottleAcceleration = ENET_NET_TO_HOST_32 (command -> connect.packetThrottleAcceleration);
328     peer -> packetThrottleDeceleration = ENET_NET_TO_HOST_32 (command -> connect.packetThrottleDeceleration);
329     peer -> eventData = ENET_NET_TO_HOST_32 (command -> connect.data);
330 
331     incomingSessionID = command -> connect.incomingSessionID == 0xFF ? peer -> outgoingSessionID : command -> connect.incomingSessionID;
332     incomingSessionID = (incomingSessionID + 1) & (ENET_PROTOCOL_HEADER_SESSION_MASK >> ENET_PROTOCOL_HEADER_SESSION_SHIFT);
333     if (incomingSessionID == peer -> outgoingSessionID)
334       incomingSessionID = (incomingSessionID + 1) & (ENET_PROTOCOL_HEADER_SESSION_MASK >> ENET_PROTOCOL_HEADER_SESSION_SHIFT);
335     peer -> outgoingSessionID = incomingSessionID;
336 
337     outgoingSessionID = command -> connect.outgoingSessionID == 0xFF ? peer -> incomingSessionID : command -> connect.outgoingSessionID;
338     outgoingSessionID = (outgoingSessionID + 1) & (ENET_PROTOCOL_HEADER_SESSION_MASK >> ENET_PROTOCOL_HEADER_SESSION_SHIFT);
339     if (outgoingSessionID == peer -> incomingSessionID)
340       outgoingSessionID = (outgoingSessionID + 1) & (ENET_PROTOCOL_HEADER_SESSION_MASK >> ENET_PROTOCOL_HEADER_SESSION_SHIFT);
341     peer -> incomingSessionID = outgoingSessionID;
342 
343     for (channel = peer -> channels;
344          channel < & peer -> channels [channelCount];
345          ++ channel)
346     {
347         channel -> outgoingReliableSequenceNumber = 0;
348         channel -> outgoingUnreliableSequenceNumber = 0;
349         channel -> incomingReliableSequenceNumber = 0;
350         channel -> incomingUnreliableSequenceNumber = 0;
351 
352         enet_list_clear (& channel -> incomingReliableCommands);
353         enet_list_clear (& channel -> incomingUnreliableCommands);
354 
355         channel -> usedReliableWindows = 0;
356         memset (channel -> reliableWindows, 0, sizeof (channel -> reliableWindows));
357     }
358 
359     mtu = ENET_NET_TO_HOST_32 (command -> connect.mtu);
360 
361     if (mtu < ENET_PROTOCOL_MINIMUM_MTU)
362       mtu = ENET_PROTOCOL_MINIMUM_MTU;
363     else
364     if (mtu > ENET_PROTOCOL_MAXIMUM_MTU)
365       mtu = ENET_PROTOCOL_MAXIMUM_MTU;
366 
367     peer -> mtu = mtu;
368 
369     if (host -> outgoingBandwidth == 0 &&
370         peer -> incomingBandwidth == 0)
371       peer -> windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE;
372     else
373     if (host -> outgoingBandwidth == 0 ||
374         peer -> incomingBandwidth == 0)
375       peer -> windowSize = (ENET_MAX (host -> outgoingBandwidth, peer -> incomingBandwidth) /
376                                     ENET_PEER_WINDOW_SIZE_SCALE) *
377                                       ENET_PROTOCOL_MINIMUM_WINDOW_SIZE;
378     else
379       peer -> windowSize = (ENET_MIN (host -> outgoingBandwidth, peer -> incomingBandwidth) /
380                                     ENET_PEER_WINDOW_SIZE_SCALE) *
381                                       ENET_PROTOCOL_MINIMUM_WINDOW_SIZE;
382 
383     if (peer -> windowSize < ENET_PROTOCOL_MINIMUM_WINDOW_SIZE)
384       peer -> windowSize = ENET_PROTOCOL_MINIMUM_WINDOW_SIZE;
385     else
386     if (peer -> windowSize > ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE)
387       peer -> windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE;
388 
389     if (host -> incomingBandwidth == 0)
390       windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE;
391     else
392       windowSize = (host -> incomingBandwidth / ENET_PEER_WINDOW_SIZE_SCALE) *
393                      ENET_PROTOCOL_MINIMUM_WINDOW_SIZE;
394 
395     if (windowSize > ENET_NET_TO_HOST_32 (command -> connect.windowSize))
396       windowSize = ENET_NET_TO_HOST_32 (command -> connect.windowSize);
397 
398     if (windowSize < ENET_PROTOCOL_MINIMUM_WINDOW_SIZE)
399       windowSize = ENET_PROTOCOL_MINIMUM_WINDOW_SIZE;
400     else
401     if (windowSize > ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE)
402       windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE;
403 
404     verifyCommand.header.command = ENET_PROTOCOL_COMMAND_VERIFY_CONNECT | ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE;
405     verifyCommand.header.channelID = 0xFF;
406     verifyCommand.verifyConnect.outgoingPeerID = ENET_HOST_TO_NET_16 (peer -> incomingPeerID);
407     verifyCommand.verifyConnect.incomingSessionID = incomingSessionID;
408     verifyCommand.verifyConnect.outgoingSessionID = outgoingSessionID;
409     verifyCommand.verifyConnect.mtu = ENET_HOST_TO_NET_32 (peer -> mtu);
410     verifyCommand.verifyConnect.windowSize = ENET_HOST_TO_NET_32 (windowSize);
411     verifyCommand.verifyConnect.channelCount = ENET_HOST_TO_NET_32 (channelCount);
412     verifyCommand.verifyConnect.incomingBandwidth = ENET_HOST_TO_NET_32 (host -> incomingBandwidth);
413     verifyCommand.verifyConnect.outgoingBandwidth = ENET_HOST_TO_NET_32 (host -> outgoingBandwidth);
414     verifyCommand.verifyConnect.packetThrottleInterval = ENET_HOST_TO_NET_32 (peer -> packetThrottleInterval);
415     verifyCommand.verifyConnect.packetThrottleAcceleration = ENET_HOST_TO_NET_32 (peer -> packetThrottleAcceleration);
416     verifyCommand.verifyConnect.packetThrottleDeceleration = ENET_HOST_TO_NET_32 (peer -> packetThrottleDeceleration);
417     verifyCommand.verifyConnect.connectID = peer -> connectID;
418 
419     enet_peer_queue_outgoing_command (peer, & verifyCommand, NULL, 0, 0);
420 
421     return peer;
422 }
423 
424 static int
enet_protocol_handle_send_reliable(ENetHost * host,ENetPeer * peer,const ENetProtocol * command,enet_uint8 ** currentData)425 enet_protocol_handle_send_reliable (ENetHost * host, ENetPeer * peer, const ENetProtocol * command, enet_uint8 ** currentData)
426 {
427     size_t dataLength;
428 
429     if (command -> header.channelID >= peer -> channelCount ||
430         (peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER))
431       return -1;
432 
433     dataLength = ENET_NET_TO_HOST_16 (command -> sendReliable.dataLength);
434     * currentData += dataLength;
435     if (dataLength > host -> maximumPacketSize ||
436         * currentData < host -> receivedData ||
437         * currentData > & host -> receivedData [host -> receivedDataLength])
438       return -1;
439 
440     if (enet_peer_queue_incoming_command (peer, command, (const enet_uint8 *) command + sizeof (ENetProtocolSendReliable), dataLength, ENET_PACKET_FLAG_RELIABLE, 0) == NULL)
441       return -1;
442 
443     return 0;
444 }
445 
446 static int
enet_protocol_handle_send_unsequenced(ENetHost * host,ENetPeer * peer,const ENetProtocol * command,enet_uint8 ** currentData)447 enet_protocol_handle_send_unsequenced (ENetHost * host, ENetPeer * peer, const ENetProtocol * command, enet_uint8 ** currentData)
448 {
449     enet_uint32 unsequencedGroup, index;
450     size_t dataLength;
451 
452     if (command -> header.channelID >= peer -> channelCount ||
453         (peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER))
454       return -1;
455 
456     dataLength = ENET_NET_TO_HOST_16 (command -> sendUnsequenced.dataLength);
457     * currentData += dataLength;
458     if (dataLength > host -> maximumPacketSize ||
459         * currentData < host -> receivedData ||
460         * currentData > & host -> receivedData [host -> receivedDataLength])
461       return -1;
462 
463     unsequencedGroup = ENET_NET_TO_HOST_16 (command -> sendUnsequenced.unsequencedGroup);
464     index = unsequencedGroup % ENET_PEER_UNSEQUENCED_WINDOW_SIZE;
465 
466     if (unsequencedGroup < peer -> incomingUnsequencedGroup)
467       unsequencedGroup += 0x10000;
468 
469     if (unsequencedGroup >= (enet_uint32) peer -> incomingUnsequencedGroup + ENET_PEER_FREE_UNSEQUENCED_WINDOWS * ENET_PEER_UNSEQUENCED_WINDOW_SIZE)
470       return 0;
471 
472     unsequencedGroup &= 0xFFFF;
473 
474     if (unsequencedGroup - index != peer -> incomingUnsequencedGroup)
475     {
476         peer -> incomingUnsequencedGroup = unsequencedGroup - index;
477 
478         memset (peer -> unsequencedWindow, 0, sizeof (peer -> unsequencedWindow));
479     }
480     else
481     if (peer -> unsequencedWindow [index / 32] & (1 << (index % 32)))
482       return 0;
483 
484     if (enet_peer_queue_incoming_command (peer, command, (const enet_uint8 *) command + sizeof (ENetProtocolSendUnsequenced), dataLength, ENET_PACKET_FLAG_UNSEQUENCED, 0) == NULL)
485       return -1;
486 
487     peer -> unsequencedWindow [index / 32] |= 1 << (index % 32);
488 
489     return 0;
490 }
491 
492 static int
enet_protocol_handle_send_unreliable(ENetHost * host,ENetPeer * peer,const ENetProtocol * command,enet_uint8 ** currentData)493 enet_protocol_handle_send_unreliable (ENetHost * host, ENetPeer * peer, const ENetProtocol * command, enet_uint8 ** currentData)
494 {
495     size_t dataLength;
496 
497     if (command -> header.channelID >= peer -> channelCount ||
498         (peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER))
499       return -1;
500 
501     dataLength = ENET_NET_TO_HOST_16 (command -> sendUnreliable.dataLength);
502     * currentData += dataLength;
503     if (dataLength > host -> maximumPacketSize ||
504         * currentData < host -> receivedData ||
505         * currentData > & host -> receivedData [host -> receivedDataLength])
506       return -1;
507 
508     if (enet_peer_queue_incoming_command (peer, command, (const enet_uint8 *) command + sizeof (ENetProtocolSendUnreliable), dataLength, 0, 0) == NULL)
509       return -1;
510 
511     return 0;
512 }
513 
514 static int
enet_protocol_handle_send_fragment(ENetHost * host,ENetPeer * peer,const ENetProtocol * command,enet_uint8 ** currentData)515 enet_protocol_handle_send_fragment (ENetHost * host, ENetPeer * peer, const ENetProtocol * command, enet_uint8 ** currentData)
516 {
517     enet_uint32 fragmentNumber,
518            fragmentCount,
519            fragmentOffset,
520            fragmentLength,
521            startSequenceNumber,
522            totalLength;
523     ENetChannel * channel;
524     enet_uint16 startWindow, currentWindow;
525     ENetListIterator currentCommand;
526     ENetIncomingCommand * startCommand = NULL;
527 
528     if (command -> header.channelID >= peer -> channelCount ||
529         (peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER))
530       return -1;
531 
532     fragmentLength = ENET_NET_TO_HOST_16 (command -> sendFragment.dataLength);
533     * currentData += fragmentLength;
534     if (fragmentLength > host -> maximumPacketSize ||
535         * currentData < host -> receivedData ||
536         * currentData > & host -> receivedData [host -> receivedDataLength])
537       return -1;
538 
539     channel = & peer -> channels [command -> header.channelID];
540     startSequenceNumber = ENET_NET_TO_HOST_16 (command -> sendFragment.startSequenceNumber);
541     startWindow = startSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE;
542     currentWindow = channel -> incomingReliableSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE;
543 
544     if (startSequenceNumber < channel -> incomingReliableSequenceNumber)
545       startWindow += ENET_PEER_RELIABLE_WINDOWS;
546 
547     if (startWindow < currentWindow || startWindow >= currentWindow + ENET_PEER_FREE_RELIABLE_WINDOWS - 1)
548       return 0;
549 
550     fragmentNumber = ENET_NET_TO_HOST_32 (command -> sendFragment.fragmentNumber);
551     fragmentCount = ENET_NET_TO_HOST_32 (command -> sendFragment.fragmentCount);
552     fragmentOffset = ENET_NET_TO_HOST_32 (command -> sendFragment.fragmentOffset);
553     totalLength = ENET_NET_TO_HOST_32 (command -> sendFragment.totalLength);
554 
555     if (fragmentCount > ENET_PROTOCOL_MAXIMUM_FRAGMENT_COUNT ||
556         fragmentNumber >= fragmentCount ||
557         totalLength > host -> maximumPacketSize ||
558         fragmentOffset >= totalLength ||
559         fragmentLength > totalLength - fragmentOffset)
560       return -1;
561 
562     for (currentCommand = enet_list_previous (enet_list_end (& channel -> incomingReliableCommands));
563          currentCommand != enet_list_end (& channel -> incomingReliableCommands);
564          currentCommand = enet_list_previous (currentCommand))
565     {
566        ENetIncomingCommand * incomingCommand = (ENetIncomingCommand *) currentCommand;
567 
568        if (startSequenceNumber >= channel -> incomingReliableSequenceNumber)
569        {
570           if (incomingCommand -> reliableSequenceNumber < channel -> incomingReliableSequenceNumber)
571             continue;
572        }
573        else
574        if (incomingCommand -> reliableSequenceNumber >= channel -> incomingReliableSequenceNumber)
575          break;
576 
577        if (incomingCommand -> reliableSequenceNumber <= startSequenceNumber)
578        {
579           if (incomingCommand -> reliableSequenceNumber < startSequenceNumber)
580             break;
581 
582           if ((incomingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_MASK) != ENET_PROTOCOL_COMMAND_SEND_FRAGMENT ||
583               totalLength != incomingCommand -> packet -> dataLength ||
584               fragmentCount != incomingCommand -> fragmentCount)
585             return -1;
586 
587           startCommand = incomingCommand;
588           break;
589        }
590     }
591 
592     if (startCommand == NULL)
593     {
594        ENetProtocol hostCommand = * command;
595 
596        hostCommand.header.reliableSequenceNumber = startSequenceNumber;
597 
598        startCommand = enet_peer_queue_incoming_command (peer, & hostCommand, NULL, totalLength, ENET_PACKET_FLAG_RELIABLE, fragmentCount);
599        if (startCommand == NULL)
600          return -1;
601     }
602 
603     if ((startCommand -> fragments [fragmentNumber / 32] & (1 << (fragmentNumber % 32))) == 0)
604     {
605        -- startCommand -> fragmentsRemaining;
606 
607        startCommand -> fragments [fragmentNumber / 32] |= (1 << (fragmentNumber % 32));
608 
609        if (fragmentOffset + fragmentLength > startCommand -> packet -> dataLength)
610          fragmentLength = startCommand -> packet -> dataLength - fragmentOffset;
611 
612        memcpy (startCommand -> packet -> data + fragmentOffset,
613                (enet_uint8 *) command + sizeof (ENetProtocolSendFragment),
614                fragmentLength);
615 
616         if (startCommand -> fragmentsRemaining <= 0)
617           enet_peer_dispatch_incoming_reliable_commands (peer, channel);
618     }
619 
620     return 0;
621 }
622 
623 static int
enet_protocol_handle_send_unreliable_fragment(ENetHost * host,ENetPeer * peer,const ENetProtocol * command,enet_uint8 ** currentData)624 enet_protocol_handle_send_unreliable_fragment (ENetHost * host, ENetPeer * peer, const ENetProtocol * command, enet_uint8 ** currentData)
625 {
626     enet_uint32 fragmentNumber,
627            fragmentCount,
628            fragmentOffset,
629            fragmentLength,
630            reliableSequenceNumber,
631            startSequenceNumber,
632            totalLength;
633     enet_uint16 reliableWindow, currentWindow;
634     ENetChannel * channel;
635     ENetListIterator currentCommand;
636     ENetIncomingCommand * startCommand = NULL;
637 
638     if (command -> header.channelID >= peer -> channelCount ||
639         (peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER))
640       return -1;
641 
642     fragmentLength = ENET_NET_TO_HOST_16 (command -> sendFragment.dataLength);
643     * currentData += fragmentLength;
644     if (fragmentLength > host -> maximumPacketSize ||
645         * currentData < host -> receivedData ||
646         * currentData > & host -> receivedData [host -> receivedDataLength])
647       return -1;
648 
649     channel = & peer -> channels [command -> header.channelID];
650     reliableSequenceNumber = command -> header.reliableSequenceNumber;
651     startSequenceNumber = ENET_NET_TO_HOST_16 (command -> sendFragment.startSequenceNumber);
652 
653     reliableWindow = reliableSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE;
654     currentWindow = channel -> incomingReliableSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE;
655 
656     if (reliableSequenceNumber < channel -> incomingReliableSequenceNumber)
657       reliableWindow += ENET_PEER_RELIABLE_WINDOWS;
658 
659     if (reliableWindow < currentWindow || reliableWindow >= currentWindow + ENET_PEER_FREE_RELIABLE_WINDOWS - 1)
660       return 0;
661 
662     if (reliableSequenceNumber == channel -> incomingReliableSequenceNumber &&
663         startSequenceNumber <= channel -> incomingUnreliableSequenceNumber)
664       return 0;
665 
666     fragmentNumber = ENET_NET_TO_HOST_32 (command -> sendFragment.fragmentNumber);
667     fragmentCount = ENET_NET_TO_HOST_32 (command -> sendFragment.fragmentCount);
668     fragmentOffset = ENET_NET_TO_HOST_32 (command -> sendFragment.fragmentOffset);
669     totalLength = ENET_NET_TO_HOST_32 (command -> sendFragment.totalLength);
670 
671     if (fragmentCount > ENET_PROTOCOL_MAXIMUM_FRAGMENT_COUNT ||
672         fragmentNumber >= fragmentCount ||
673         totalLength > host -> maximumPacketSize ||
674         fragmentOffset >= totalLength ||
675         fragmentLength > totalLength - fragmentOffset)
676       return -1;
677 
678     for (currentCommand = enet_list_previous (enet_list_end (& channel -> incomingUnreliableCommands));
679          currentCommand != enet_list_end (& channel -> incomingUnreliableCommands);
680          currentCommand = enet_list_previous (currentCommand))
681     {
682        ENetIncomingCommand * incomingCommand = (ENetIncomingCommand *) currentCommand;
683 
684        if (reliableSequenceNumber >= channel -> incomingReliableSequenceNumber)
685        {
686           if (incomingCommand -> reliableSequenceNumber < channel -> incomingReliableSequenceNumber)
687             continue;
688        }
689        else
690        if (incomingCommand -> reliableSequenceNumber >= channel -> incomingReliableSequenceNumber)
691          break;
692 
693        if (incomingCommand -> reliableSequenceNumber < reliableSequenceNumber)
694          break;
695 
696        if (incomingCommand -> reliableSequenceNumber > reliableSequenceNumber)
697          continue;
698 
699        if (incomingCommand -> unreliableSequenceNumber <= startSequenceNumber)
700        {
701           if (incomingCommand -> unreliableSequenceNumber < startSequenceNumber)
702             break;
703 
704           if ((incomingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_MASK) != ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE_FRAGMENT ||
705               totalLength != incomingCommand -> packet -> dataLength ||
706               fragmentCount != incomingCommand -> fragmentCount)
707             return -1;
708 
709           startCommand = incomingCommand;
710           break;
711        }
712     }
713 
714     if (startCommand == NULL)
715     {
716        startCommand = enet_peer_queue_incoming_command (peer, command, NULL, totalLength, ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT, fragmentCount);
717        if (startCommand == NULL)
718          return -1;
719     }
720 
721     if ((startCommand -> fragments [fragmentNumber / 32] & (1 << (fragmentNumber % 32))) == 0)
722     {
723        -- startCommand -> fragmentsRemaining;
724 
725        startCommand -> fragments [fragmentNumber / 32] |= (1 << (fragmentNumber % 32));
726 
727        if (fragmentOffset + fragmentLength > startCommand -> packet -> dataLength)
728          fragmentLength = startCommand -> packet -> dataLength - fragmentOffset;
729 
730        memcpy (startCommand -> packet -> data + fragmentOffset,
731                (enet_uint8 *) command + sizeof (ENetProtocolSendFragment),
732                fragmentLength);
733 
734         if (startCommand -> fragmentsRemaining <= 0)
735           enet_peer_dispatch_incoming_unreliable_commands (peer, channel);
736     }
737 
738     return 0;
739 }
740 
741 static int
enet_protocol_handle_ping(ENetHost * host,ENetPeer * peer,const ENetProtocol * command)742 enet_protocol_handle_ping (ENetHost * host, ENetPeer * peer, const ENetProtocol * command)
743 {
744     if (peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER)
745       return -1;
746 
747     return 0;
748 }
749 
750 static int
enet_protocol_handle_bandwidth_limit(ENetHost * host,ENetPeer * peer,const ENetProtocol * command)751 enet_protocol_handle_bandwidth_limit (ENetHost * host, ENetPeer * peer, const ENetProtocol * command)
752 {
753     if (peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER)
754       return -1;
755 
756     if (peer -> incomingBandwidth != 0)
757       -- host -> bandwidthLimitedPeers;
758 
759     peer -> incomingBandwidth = ENET_NET_TO_HOST_32 (command -> bandwidthLimit.incomingBandwidth);
760     peer -> outgoingBandwidth = ENET_NET_TO_HOST_32 (command -> bandwidthLimit.outgoingBandwidth);
761 
762     if (peer -> incomingBandwidth != 0)
763       ++ host -> bandwidthLimitedPeers;
764 
765     if (peer -> incomingBandwidth == 0 && host -> outgoingBandwidth == 0)
766       peer -> windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE;
767     else
768     if (peer -> incomingBandwidth == 0 || host -> outgoingBandwidth == 0)
769       peer -> windowSize = (ENET_MAX (peer -> incomingBandwidth, host -> outgoingBandwidth) /
770                              ENET_PEER_WINDOW_SIZE_SCALE) * ENET_PROTOCOL_MINIMUM_WINDOW_SIZE;
771     else
772       peer -> windowSize = (ENET_MIN (peer -> incomingBandwidth, host -> outgoingBandwidth) /
773                              ENET_PEER_WINDOW_SIZE_SCALE) * ENET_PROTOCOL_MINIMUM_WINDOW_SIZE;
774 
775     if (peer -> windowSize < ENET_PROTOCOL_MINIMUM_WINDOW_SIZE)
776       peer -> windowSize = ENET_PROTOCOL_MINIMUM_WINDOW_SIZE;
777     else
778     if (peer -> windowSize > ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE)
779       peer -> windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE;
780 
781     return 0;
782 }
783 
784 static int
enet_protocol_handle_throttle_configure(ENetHost * host,ENetPeer * peer,const ENetProtocol * command)785 enet_protocol_handle_throttle_configure (ENetHost * host, ENetPeer * peer, const ENetProtocol * command)
786 {
787     if (peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER)
788       return -1;
789 
790     peer -> packetThrottleInterval = ENET_NET_TO_HOST_32 (command -> throttleConfigure.packetThrottleInterval);
791     peer -> packetThrottleAcceleration = ENET_NET_TO_HOST_32 (command -> throttleConfigure.packetThrottleAcceleration);
792     peer -> packetThrottleDeceleration = ENET_NET_TO_HOST_32 (command -> throttleConfigure.packetThrottleDeceleration);
793 
794     return 0;
795 }
796 
797 static int
enet_protocol_handle_disconnect(ENetHost * host,ENetPeer * peer,const ENetProtocol * command)798 enet_protocol_handle_disconnect (ENetHost * host, ENetPeer * peer, const ENetProtocol * command)
799 {
800     if (peer -> state == ENET_PEER_STATE_DISCONNECTED || peer -> state == ENET_PEER_STATE_ZOMBIE || peer -> state == ENET_PEER_STATE_ACKNOWLEDGING_DISCONNECT)
801       return 0;
802 
803     enet_peer_reset_queues (peer);
804 
805     if (peer -> state == ENET_PEER_STATE_CONNECTION_SUCCEEDED || peer -> state == ENET_PEER_STATE_DISCONNECTING || peer -> state == ENET_PEER_STATE_CONNECTING)
806         enet_protocol_dispatch_state (host, peer, ENET_PEER_STATE_ZOMBIE);
807     else
808     if (peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER)
809     {
810         if (peer -> state == ENET_PEER_STATE_CONNECTION_PENDING) host -> recalculateBandwidthLimits = 1;
811 
812         enet_peer_reset (peer);
813     }
814     else
815     if (command -> header.command & ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE)
816       enet_protocol_change_state (host, peer, ENET_PEER_STATE_ACKNOWLEDGING_DISCONNECT);
817     else
818       enet_protocol_dispatch_state (host, peer, ENET_PEER_STATE_ZOMBIE);
819 
820     if (peer -> state != ENET_PEER_STATE_DISCONNECTED)
821       peer -> eventData = ENET_NET_TO_HOST_32 (command -> disconnect.data);
822 
823     return 0;
824 }
825 
826 static int
enet_protocol_handle_acknowledge(ENetHost * host,ENetEvent * event,ENetPeer * peer,const ENetProtocol * command)827 enet_protocol_handle_acknowledge (ENetHost * host, ENetEvent * event, ENetPeer * peer, const ENetProtocol * command)
828 {
829     enet_uint32 roundTripTime,
830            receivedSentTime,
831            receivedReliableSequenceNumber;
832     ENetProtocolCommand commandNumber;
833 
834     if (peer -> state == ENET_PEER_STATE_DISCONNECTED || peer -> state == ENET_PEER_STATE_ZOMBIE)
835       return 0;
836 
837     receivedSentTime = ENET_NET_TO_HOST_16 (command -> acknowledge.receivedSentTime);
838     receivedSentTime |= host -> serviceTime & 0xFFFF0000;
839     if ((receivedSentTime & 0x8000) > (host -> serviceTime & 0x8000))
840         receivedSentTime -= 0x10000;
841 
842     if (ENET_TIME_LESS (host -> serviceTime, receivedSentTime))
843       return 0;
844 
845     peer -> lastReceiveTime = host -> serviceTime;
846     peer -> earliestTimeout = 0;
847 
848     roundTripTime = ENET_TIME_DIFFERENCE (host -> serviceTime, receivedSentTime);
849 
850     enet_peer_throttle (peer, roundTripTime);
851 
852     peer -> roundTripTimeVariance -= peer -> roundTripTimeVariance / 4;
853 
854     if (roundTripTime >= peer -> roundTripTime)
855     {
856        peer -> roundTripTime += (roundTripTime - peer -> roundTripTime) / 8;
857        peer -> roundTripTimeVariance += (roundTripTime - peer -> roundTripTime) / 4;
858     }
859     else
860     {
861        peer -> roundTripTime -= (peer -> roundTripTime - roundTripTime) / 8;
862        peer -> roundTripTimeVariance += (peer -> roundTripTime - roundTripTime) / 4;
863     }
864 
865     if (peer -> roundTripTime < peer -> lowestRoundTripTime)
866       peer -> lowestRoundTripTime = peer -> roundTripTime;
867 
868     if (peer -> roundTripTimeVariance > peer -> highestRoundTripTimeVariance)
869       peer -> highestRoundTripTimeVariance = peer -> roundTripTimeVariance;
870 
871     if (peer -> packetThrottleEpoch == 0 ||
872         ENET_TIME_DIFFERENCE (host -> serviceTime, peer -> packetThrottleEpoch) >= peer -> packetThrottleInterval)
873     {
874         peer -> lastRoundTripTime = peer -> lowestRoundTripTime;
875         peer -> lastRoundTripTimeVariance = peer -> highestRoundTripTimeVariance;
876         peer -> lowestRoundTripTime = peer -> roundTripTime;
877         peer -> highestRoundTripTimeVariance = peer -> roundTripTimeVariance;
878         peer -> packetThrottleEpoch = host -> serviceTime;
879     }
880 
881     receivedReliableSequenceNumber = ENET_NET_TO_HOST_16 (command -> acknowledge.receivedReliableSequenceNumber);
882 
883     commandNumber = enet_protocol_remove_sent_reliable_command (peer, receivedReliableSequenceNumber, command -> header.channelID);
884 
885     switch (peer -> state)
886     {
887     case ENET_PEER_STATE_ACKNOWLEDGING_CONNECT:
888        if (commandNumber != ENET_PROTOCOL_COMMAND_VERIFY_CONNECT)
889          return -1;
890 
891        enet_protocol_notify_connect (host, peer, event);
892        break;
893 
894     case ENET_PEER_STATE_DISCONNECTING:
895        if (commandNumber != ENET_PROTOCOL_COMMAND_DISCONNECT)
896          return -1;
897 
898        enet_protocol_notify_disconnect (host, peer, event);
899        break;
900 
901     case ENET_PEER_STATE_DISCONNECT_LATER:
902        if (enet_list_empty (& peer -> outgoingReliableCommands) &&
903            enet_list_empty (& peer -> outgoingUnreliableCommands) &&
904            enet_list_empty (& peer -> sentReliableCommands))
905          enet_peer_disconnect (peer, peer -> eventData);
906        break;
907 
908     default:
909        break;
910     }
911 
912     return 0;
913 }
914 
915 static int
enet_protocol_handle_verify_connect(ENetHost * host,ENetEvent * event,ENetPeer * peer,const ENetProtocol * command)916 enet_protocol_handle_verify_connect (ENetHost * host, ENetEvent * event, ENetPeer * peer, const ENetProtocol * command)
917 {
918     enet_uint32 mtu, windowSize;
919     size_t channelCount;
920 
921     if (peer -> state != ENET_PEER_STATE_CONNECTING)
922       return 0;
923 
924     channelCount = ENET_NET_TO_HOST_32 (command -> verifyConnect.channelCount);
925 
926     if (channelCount < ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT || channelCount > ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT ||
927         ENET_NET_TO_HOST_32 (command -> verifyConnect.packetThrottleInterval) != peer -> packetThrottleInterval ||
928         ENET_NET_TO_HOST_32 (command -> verifyConnect.packetThrottleAcceleration) != peer -> packetThrottleAcceleration ||
929         ENET_NET_TO_HOST_32 (command -> verifyConnect.packetThrottleDeceleration) != peer -> packetThrottleDeceleration ||
930         command -> verifyConnect.connectID != peer -> connectID)
931     {
932         peer -> eventData = 0;
933 
934         enet_protocol_dispatch_state (host, peer, ENET_PEER_STATE_ZOMBIE);
935 
936         return -1;
937     }
938 
939     enet_protocol_remove_sent_reliable_command (peer, 1, 0xFF);
940 
941     if (channelCount < peer -> channelCount)
942       peer -> channelCount = channelCount;
943 
944     peer -> outgoingPeerID = ENET_NET_TO_HOST_16 (command -> verifyConnect.outgoingPeerID);
945     peer -> incomingSessionID = command -> verifyConnect.incomingSessionID;
946     peer -> outgoingSessionID = command -> verifyConnect.outgoingSessionID;
947 
948     mtu = ENET_NET_TO_HOST_32 (command -> verifyConnect.mtu);
949 
950     if (mtu < ENET_PROTOCOL_MINIMUM_MTU)
951       mtu = ENET_PROTOCOL_MINIMUM_MTU;
952     else
953     if (mtu > ENET_PROTOCOL_MAXIMUM_MTU)
954       mtu = ENET_PROTOCOL_MAXIMUM_MTU;
955 
956     if (mtu < peer -> mtu)
957       peer -> mtu = mtu;
958 
959     windowSize = ENET_NET_TO_HOST_32 (command -> verifyConnect.windowSize);
960 
961     if (windowSize < ENET_PROTOCOL_MINIMUM_WINDOW_SIZE)
962       windowSize = ENET_PROTOCOL_MINIMUM_WINDOW_SIZE;
963 
964     if (windowSize > ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE)
965       windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE;
966 
967     if (windowSize < peer -> windowSize)
968       peer -> windowSize = windowSize;
969 
970     peer -> incomingBandwidth = ENET_NET_TO_HOST_32 (command -> verifyConnect.incomingBandwidth);
971     peer -> outgoingBandwidth = ENET_NET_TO_HOST_32 (command -> verifyConnect.outgoingBandwidth);
972 
973     enet_protocol_notify_connect (host, peer, event);
974     return 0;
975 }
976 
977 static int
enet_protocol_handle_incoming_commands(ENetHost * host,ENetEvent * event)978 enet_protocol_handle_incoming_commands (ENetHost * host, ENetEvent * event)
979 {
980     ENetProtocolHeader * header;
981     ENetProtocol * command;
982     ENetPeer * peer;
983     enet_uint8 * currentData;
984     size_t headerSize;
985     enet_uint16 peerID, flags;
986     enet_uint8 sessionID;
987 
988     if (host -> receivedDataLength < (size_t) & ((ENetProtocolHeader *) 0) -> sentTime)
989       return 0;
990 
991     header = (ENetProtocolHeader *) host -> receivedData;
992 
993     peerID = ENET_NET_TO_HOST_16 (header -> peerID);
994     sessionID = (peerID & ENET_PROTOCOL_HEADER_SESSION_MASK) >> ENET_PROTOCOL_HEADER_SESSION_SHIFT;
995     flags = peerID & ENET_PROTOCOL_HEADER_FLAG_MASK;
996     peerID &= ~ (ENET_PROTOCOL_HEADER_FLAG_MASK | ENET_PROTOCOL_HEADER_SESSION_MASK);
997 
998     headerSize = (flags & ENET_PROTOCOL_HEADER_FLAG_SENT_TIME ? sizeof (ENetProtocolHeader) : (size_t) & ((ENetProtocolHeader *) 0) -> sentTime);
999     if (host -> checksum != NULL)
1000       headerSize += sizeof (enet_uint32);
1001 
1002     if (peerID == ENET_PROTOCOL_MAXIMUM_PEER_ID)
1003       peer = NULL;
1004     else
1005     if (peerID >= host -> peerCount)
1006       return 0;
1007     else
1008     {
1009        peer = & host -> peers [peerID];
1010 
1011        if (peer -> state == ENET_PEER_STATE_DISCONNECTED ||
1012            peer -> state == ENET_PEER_STATE_ZOMBIE ||
1013            ((host -> receivedAddress.host != peer -> address.host ||
1014              host -> receivedAddress.port != peer -> address.port) &&
1015              peer -> address.host != ENET_HOST_BROADCAST) ||
1016            (peer -> outgoingPeerID < ENET_PROTOCOL_MAXIMUM_PEER_ID &&
1017             sessionID != peer -> incomingSessionID))
1018          return 0;
1019     }
1020 
1021     if (flags & ENET_PROTOCOL_HEADER_FLAG_COMPRESSED)
1022     {
1023         size_t originalSize;
1024         if (host -> compressor.context == NULL || host -> compressor.decompress == NULL)
1025           return 0;
1026 
1027         originalSize = host -> compressor.decompress (host -> compressor.context,
1028                                     host -> receivedData + headerSize,
1029                                     host -> receivedDataLength - headerSize,
1030                                     host -> packetData [1] + headerSize,
1031                                     sizeof (host -> packetData [1]) - headerSize);
1032         if (originalSize <= 0 || originalSize > sizeof (host -> packetData [1]) - headerSize)
1033           return 0;
1034 
1035         memcpy (host -> packetData [1], header, headerSize);
1036         host -> receivedData = host -> packetData [1];
1037         host -> receivedDataLength = headerSize + originalSize;
1038     }
1039 
1040     if (host -> checksum != NULL)
1041     {
1042         enet_uint32 * checksum = (enet_uint32 *) & host -> receivedData [headerSize - sizeof (enet_uint32)],
1043                     desiredChecksum = * checksum;
1044         ENetBuffer buffer;
1045 
1046         * checksum = peer != NULL ? peer -> connectID : 0;
1047 
1048         buffer.data = host -> receivedData;
1049         buffer.dataLength = host -> receivedDataLength;
1050 
1051         if (host -> checksum (& buffer, 1) != desiredChecksum)
1052           return 0;
1053     }
1054 
1055     if (peer != NULL)
1056     {
1057        peer -> address.host = host -> receivedAddress.host;
1058        peer -> address.port = host -> receivedAddress.port;
1059        peer -> incomingDataTotal += host -> receivedDataLength;
1060     }
1061 
1062     currentData = host -> receivedData + headerSize;
1063 
1064     while (currentData < & host -> receivedData [host -> receivedDataLength])
1065     {
1066        enet_uint8 commandNumber;
1067        size_t commandSize;
1068 
1069        command = (ENetProtocol *) currentData;
1070 
1071        if (currentData + sizeof (ENetProtocolCommandHeader) > & host -> receivedData [host -> receivedDataLength])
1072          break;
1073 
1074        commandNumber = command -> header.command & ENET_PROTOCOL_COMMAND_MASK;
1075        if (commandNumber >= ENET_PROTOCOL_COMMAND_COUNT)
1076          break;
1077 
1078        commandSize = commandSizes [commandNumber];
1079        if (commandSize == 0 || currentData + commandSize > & host -> receivedData [host -> receivedDataLength])
1080          break;
1081 
1082        currentData += commandSize;
1083 
1084        if (peer == NULL && commandNumber != ENET_PROTOCOL_COMMAND_CONNECT)
1085          break;
1086 
1087        command -> header.reliableSequenceNumber = ENET_NET_TO_HOST_16 (command -> header.reliableSequenceNumber);
1088 
1089        switch (commandNumber)
1090        {
1091        case ENET_PROTOCOL_COMMAND_ACKNOWLEDGE:
1092           if (enet_protocol_handle_acknowledge (host, event, peer, command))
1093             goto commandError;
1094           break;
1095 
1096        case ENET_PROTOCOL_COMMAND_CONNECT:
1097           if (peer != NULL)
1098             goto commandError;
1099           peer = enet_protocol_handle_connect (host, header, command);
1100           if (peer == NULL)
1101             goto commandError;
1102           break;
1103 
1104        case ENET_PROTOCOL_COMMAND_VERIFY_CONNECT:
1105           if (enet_protocol_handle_verify_connect (host, event, peer, command))
1106             goto commandError;
1107           break;
1108 
1109        case ENET_PROTOCOL_COMMAND_DISCONNECT:
1110           if (enet_protocol_handle_disconnect (host, peer, command))
1111             goto commandError;
1112           break;
1113 
1114        case ENET_PROTOCOL_COMMAND_PING:
1115           if (enet_protocol_handle_ping (host, peer, command))
1116             goto commandError;
1117           break;
1118 
1119        case ENET_PROTOCOL_COMMAND_SEND_RELIABLE:
1120           if (enet_protocol_handle_send_reliable (host, peer, command, & currentData))
1121             goto commandError;
1122           break;
1123 
1124        case ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE:
1125           if (enet_protocol_handle_send_unreliable (host, peer, command, & currentData))
1126             goto commandError;
1127           break;
1128 
1129        case ENET_PROTOCOL_COMMAND_SEND_UNSEQUENCED:
1130           if (enet_protocol_handle_send_unsequenced (host, peer, command, & currentData))
1131             goto commandError;
1132           break;
1133 
1134        case ENET_PROTOCOL_COMMAND_SEND_FRAGMENT:
1135           if (enet_protocol_handle_send_fragment (host, peer, command, & currentData))
1136             goto commandError;
1137           break;
1138 
1139        case ENET_PROTOCOL_COMMAND_BANDWIDTH_LIMIT:
1140           if (enet_protocol_handle_bandwidth_limit (host, peer, command))
1141             goto commandError;
1142           break;
1143 
1144        case ENET_PROTOCOL_COMMAND_THROTTLE_CONFIGURE:
1145           if (enet_protocol_handle_throttle_configure (host, peer, command))
1146             goto commandError;
1147           break;
1148 
1149        case ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE_FRAGMENT:
1150           if (enet_protocol_handle_send_unreliable_fragment (host, peer, command, & currentData))
1151             goto commandError;
1152           break;
1153 
1154        default:
1155           goto commandError;
1156        }
1157 
1158        if (peer != NULL &&
1159            (command -> header.command & ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE) != 0)
1160        {
1161            enet_uint16 sentTime;
1162 
1163            if (! (flags & ENET_PROTOCOL_HEADER_FLAG_SENT_TIME))
1164              break;
1165 
1166            sentTime = ENET_NET_TO_HOST_16 (header -> sentTime);
1167 
1168            switch (peer -> state)
1169            {
1170            case ENET_PEER_STATE_DISCONNECTING:
1171            case ENET_PEER_STATE_ACKNOWLEDGING_CONNECT:
1172            case ENET_PEER_STATE_DISCONNECTED:
1173            case ENET_PEER_STATE_ZOMBIE:
1174               break;
1175 
1176            case ENET_PEER_STATE_ACKNOWLEDGING_DISCONNECT:
1177               if ((command -> header.command & ENET_PROTOCOL_COMMAND_MASK) == ENET_PROTOCOL_COMMAND_DISCONNECT)
1178                 enet_peer_queue_acknowledgement (peer, command, sentTime);
1179               break;
1180 
1181            default:
1182               enet_peer_queue_acknowledgement (peer, command, sentTime);
1183               break;
1184            }
1185        }
1186     }
1187 
1188 commandError:
1189     if (event != NULL && event -> type != ENET_EVENT_TYPE_NONE)
1190       return 1;
1191 
1192     return 0;
1193 }
1194 
1195 static int
enet_protocol_receive_incoming_commands(ENetHost * host,ENetEvent * event)1196 enet_protocol_receive_incoming_commands (ENetHost * host, ENetEvent * event)
1197 {
1198     int packets;
1199 
1200     for (packets = 0; packets < 256; ++ packets)
1201     {
1202        int receivedLength;
1203        ENetBuffer buffer;
1204 
1205        buffer.data = host -> packetData [0];
1206        buffer.dataLength = sizeof (host -> packetData [0]);
1207 
1208        receivedLength = enet_socket_receive (host -> socket,
1209                                              & host -> receivedAddress,
1210                                              & buffer,
1211                                              1);
1212 
1213        if (receivedLength < 0)
1214          return -1;
1215 
1216        if (receivedLength == 0)
1217          return 0;
1218 
1219        host -> receivedData = host -> packetData [0];
1220        host -> receivedDataLength = receivedLength;
1221 
1222        host -> totalReceivedData += receivedLength;
1223        host -> totalReceivedPackets ++;
1224 
1225        if (host -> intercept != NULL)
1226        {
1227           switch (host -> intercept (host, event))
1228           {
1229           case 1:
1230              if (event != NULL && event -> type != ENET_EVENT_TYPE_NONE)
1231                return 1;
1232 
1233              continue;
1234 
1235           case -1:
1236              return -1;
1237 
1238           default:
1239              break;
1240           }
1241        }
1242 
1243        switch (enet_protocol_handle_incoming_commands (host, event))
1244        {
1245        case 1:
1246           return 1;
1247 
1248        case -1:
1249           return -1;
1250 
1251        default:
1252           break;
1253        }
1254     }
1255 
1256     return -1;
1257 }
1258 
1259 static void
enet_protocol_send_acknowledgements(ENetHost * host,ENetPeer * peer)1260 enet_protocol_send_acknowledgements (ENetHost * host, ENetPeer * peer)
1261 {
1262     ENetProtocol * command = & host -> commands [host -> commandCount];
1263     ENetBuffer * buffer = & host -> buffers [host -> bufferCount];
1264     ENetAcknowledgement * acknowledgement;
1265     ENetListIterator currentAcknowledgement;
1266     enet_uint16 reliableSequenceNumber;
1267 
1268     currentAcknowledgement = enet_list_begin (& peer -> acknowledgements);
1269 
1270     while (currentAcknowledgement != enet_list_end (& peer -> acknowledgements))
1271     {
1272        if (command >= & host -> commands [sizeof (host -> commands) / sizeof (ENetProtocol)] ||
1273            buffer >= & host -> buffers [sizeof (host -> buffers) / sizeof (ENetBuffer)] ||
1274            peer -> mtu - host -> packetSize < sizeof (ENetProtocolAcknowledge))
1275        {
1276           host -> continueSending = 1;
1277 
1278           break;
1279        }
1280 
1281        acknowledgement = (ENetAcknowledgement *) currentAcknowledgement;
1282 
1283        currentAcknowledgement = enet_list_next (currentAcknowledgement);
1284 
1285        buffer -> data = command;
1286        buffer -> dataLength = sizeof (ENetProtocolAcknowledge);
1287 
1288        host -> packetSize += buffer -> dataLength;
1289 
1290        reliableSequenceNumber = ENET_HOST_TO_NET_16 (acknowledgement -> command.header.reliableSequenceNumber);
1291 
1292        command -> header.command = ENET_PROTOCOL_COMMAND_ACKNOWLEDGE;
1293        command -> header.channelID = acknowledgement -> command.header.channelID;
1294        command -> header.reliableSequenceNumber = reliableSequenceNumber;
1295        command -> acknowledge.receivedReliableSequenceNumber = reliableSequenceNumber;
1296        command -> acknowledge.receivedSentTime = ENET_HOST_TO_NET_16 (acknowledgement -> sentTime);
1297 
1298        if ((acknowledgement -> command.header.command & ENET_PROTOCOL_COMMAND_MASK) == ENET_PROTOCOL_COMMAND_DISCONNECT)
1299          enet_protocol_dispatch_state (host, peer, ENET_PEER_STATE_ZOMBIE);
1300 
1301        enet_list_remove (& acknowledgement -> acknowledgementList);
1302        enet_free (acknowledgement);
1303 
1304        ++ command;
1305        ++ buffer;
1306     }
1307 
1308     host -> commandCount = command - host -> commands;
1309     host -> bufferCount = buffer - host -> buffers;
1310 }
1311 
1312 static void
enet_protocol_send_unreliable_outgoing_commands(ENetHost * host,ENetPeer * peer)1313 enet_protocol_send_unreliable_outgoing_commands (ENetHost * host, ENetPeer * peer)
1314 {
1315     ENetProtocol * command = & host -> commands [host -> commandCount];
1316     ENetBuffer * buffer = & host -> buffers [host -> bufferCount];
1317     ENetOutgoingCommand * outgoingCommand;
1318     ENetListIterator currentCommand;
1319 
1320     currentCommand = enet_list_begin (& peer -> outgoingUnreliableCommands);
1321 
1322     while (currentCommand != enet_list_end (& peer -> outgoingUnreliableCommands))
1323     {
1324        size_t commandSize;
1325 
1326        outgoingCommand = (ENetOutgoingCommand *) currentCommand;
1327        commandSize = commandSizes [outgoingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_MASK];
1328 
1329        if (command >= & host -> commands [sizeof (host -> commands) / sizeof (ENetProtocol)] ||
1330            buffer + 1 >= & host -> buffers [sizeof (host -> buffers) / sizeof (ENetBuffer)] ||
1331            peer -> mtu - host -> packetSize < commandSize ||
1332            (outgoingCommand -> packet != NULL &&
1333              peer -> mtu - host -> packetSize < commandSize + outgoingCommand -> fragmentLength))
1334        {
1335           host -> continueSending = 1;
1336 
1337           break;
1338        }
1339 
1340        currentCommand = enet_list_next (currentCommand);
1341 
1342        if (outgoingCommand -> packet != NULL && outgoingCommand -> fragmentOffset == 0)
1343        {
1344           peer -> packetThrottleCounter += ENET_PEER_PACKET_THROTTLE_COUNTER;
1345           peer -> packetThrottleCounter %= ENET_PEER_PACKET_THROTTLE_SCALE;
1346 
1347           if (peer -> packetThrottleCounter > peer -> packetThrottle)
1348           {
1349              enet_uint16 reliableSequenceNumber = outgoingCommand -> reliableSequenceNumber,
1350                          unreliableSequenceNumber = outgoingCommand -> unreliableSequenceNumber;
1351              for (;;)
1352              {
1353                 -- outgoingCommand -> packet -> referenceCount;
1354 
1355                 if (outgoingCommand -> packet -> referenceCount == 0)
1356                   enet_packet_destroy (outgoingCommand -> packet);
1357 
1358                 enet_list_remove (& outgoingCommand -> outgoingCommandList);
1359                 enet_free (outgoingCommand);
1360 
1361                 if (currentCommand == enet_list_end (& peer -> outgoingUnreliableCommands))
1362                   break;
1363 
1364                 outgoingCommand = (ENetOutgoingCommand *) currentCommand;
1365                 if (outgoingCommand -> reliableSequenceNumber != reliableSequenceNumber ||
1366                     outgoingCommand -> unreliableSequenceNumber != unreliableSequenceNumber)
1367                   break;
1368 
1369                 currentCommand = enet_list_next (currentCommand);
1370              }
1371 
1372              continue;
1373           }
1374        }
1375 
1376        buffer -> data = command;
1377        buffer -> dataLength = commandSize;
1378 
1379        host -> packetSize += buffer -> dataLength;
1380 
1381        * command = outgoingCommand -> command;
1382 
1383        enet_list_remove (& outgoingCommand -> outgoingCommandList);
1384 
1385        if (outgoingCommand -> packet != NULL)
1386        {
1387           ++ buffer;
1388 
1389           buffer -> data = outgoingCommand -> packet -> data + outgoingCommand -> fragmentOffset;
1390           buffer -> dataLength = outgoingCommand -> fragmentLength;
1391 
1392           host -> packetSize += buffer -> dataLength;
1393 
1394           enet_list_insert (enet_list_end (& peer -> sentUnreliableCommands), outgoingCommand);
1395        }
1396        else
1397          enet_free (outgoingCommand);
1398 
1399        ++ command;
1400        ++ buffer;
1401     }
1402 
1403     host -> commandCount = command - host -> commands;
1404     host -> bufferCount = buffer - host -> buffers;
1405 
1406     if (peer -> state == ENET_PEER_STATE_DISCONNECT_LATER &&
1407         enet_list_empty (& peer -> outgoingReliableCommands) &&
1408         enet_list_empty (& peer -> outgoingUnreliableCommands) &&
1409         enet_list_empty (& peer -> sentReliableCommands))
1410       enet_peer_disconnect (peer, peer -> eventData);
1411 }
1412 
1413 static int
enet_protocol_check_timeouts(ENetHost * host,ENetPeer * peer,ENetEvent * event)1414 enet_protocol_check_timeouts (ENetHost * host, ENetPeer * peer, ENetEvent * event)
1415 {
1416     ENetOutgoingCommand * outgoingCommand;
1417     ENetListIterator currentCommand, insertPosition;
1418 
1419     currentCommand = enet_list_begin (& peer -> sentReliableCommands);
1420     insertPosition = enet_list_begin (& peer -> outgoingReliableCommands);
1421 
1422     while (currentCommand != enet_list_end (& peer -> sentReliableCommands))
1423     {
1424        outgoingCommand = (ENetOutgoingCommand *) currentCommand;
1425 
1426        currentCommand = enet_list_next (currentCommand);
1427 
1428        if (ENET_TIME_DIFFERENCE (host -> serviceTime, outgoingCommand -> sentTime) < outgoingCommand -> roundTripTimeout)
1429          continue;
1430 
1431        if (peer -> earliestTimeout == 0 ||
1432            ENET_TIME_LESS (outgoingCommand -> sentTime, peer -> earliestTimeout))
1433          peer -> earliestTimeout = outgoingCommand -> sentTime;
1434 
1435        if (peer -> earliestTimeout != 0 &&
1436              (ENET_TIME_DIFFERENCE (host -> serviceTime, peer -> earliestTimeout) >= peer -> timeoutMaximum ||
1437                (outgoingCommand -> roundTripTimeout >= outgoingCommand -> roundTripTimeoutLimit &&
1438                  ENET_TIME_DIFFERENCE (host -> serviceTime, peer -> earliestTimeout) >= peer -> timeoutMinimum)))
1439        {
1440           enet_protocol_notify_disconnect (host, peer, event);
1441 
1442           return 1;
1443        }
1444 
1445        if (outgoingCommand -> packet != NULL)
1446          peer -> reliableDataInTransit -= outgoingCommand -> fragmentLength;
1447 
1448        ++ peer -> packetsLost;
1449 
1450        outgoingCommand -> roundTripTimeout *= 2;
1451 
1452        enet_list_insert (insertPosition, enet_list_remove (& outgoingCommand -> outgoingCommandList));
1453 
1454        if (currentCommand == enet_list_begin (& peer -> sentReliableCommands) &&
1455            ! enet_list_empty (& peer -> sentReliableCommands))
1456        {
1457           outgoingCommand = (ENetOutgoingCommand *) currentCommand;
1458 
1459           peer -> nextTimeout = outgoingCommand -> sentTime + outgoingCommand -> roundTripTimeout;
1460        }
1461     }
1462 
1463     return 0;
1464 }
1465 
1466 static int
enet_protocol_send_reliable_outgoing_commands(ENetHost * host,ENetPeer * peer)1467 enet_protocol_send_reliable_outgoing_commands (ENetHost * host, ENetPeer * peer)
1468 {
1469     ENetProtocol * command = & host -> commands [host -> commandCount];
1470     ENetBuffer * buffer = & host -> buffers [host -> bufferCount];
1471     ENetOutgoingCommand * outgoingCommand;
1472     ENetListIterator currentCommand;
1473     ENetChannel *channel;
1474     enet_uint16 reliableWindow;
1475     size_t commandSize;
1476     int windowExceeded = 0, windowWrap = 0, canPing = 1;
1477 
1478     currentCommand = enet_list_begin (& peer -> outgoingReliableCommands);
1479 
1480     while (currentCommand != enet_list_end (& peer -> outgoingReliableCommands))
1481     {
1482        outgoingCommand = (ENetOutgoingCommand *) currentCommand;
1483 
1484        channel = outgoingCommand -> command.header.channelID < peer -> channelCount ? & peer -> channels [outgoingCommand -> command.header.channelID] : NULL;
1485        reliableWindow = outgoingCommand -> reliableSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE;
1486        if (channel != NULL)
1487        {
1488            if (! windowWrap &&
1489                outgoingCommand -> sendAttempts < 1 &&
1490                ! (outgoingCommand -> reliableSequenceNumber % ENET_PEER_RELIABLE_WINDOW_SIZE) &&
1491                (channel -> reliableWindows [(reliableWindow + ENET_PEER_RELIABLE_WINDOWS - 1) % ENET_PEER_RELIABLE_WINDOWS] >= ENET_PEER_RELIABLE_WINDOW_SIZE ||
1492                  channel -> usedReliableWindows & ((((1 << ENET_PEER_FREE_RELIABLE_WINDOWS) - 1) << reliableWindow) |
1493                    (((1 << ENET_PEER_FREE_RELIABLE_WINDOWS) - 1) >> (ENET_PEER_RELIABLE_WINDOWS - reliableWindow)))))
1494              windowWrap = 1;
1495           if (windowWrap)
1496           {
1497              currentCommand = enet_list_next (currentCommand);
1498 
1499              continue;
1500           }
1501        }
1502 
1503        if (outgoingCommand -> packet != NULL)
1504        {
1505           if (! windowExceeded)
1506           {
1507              enet_uint32 windowSize = (peer -> packetThrottle * peer -> windowSize) / ENET_PEER_PACKET_THROTTLE_SCALE;
1508 
1509              if (peer -> reliableDataInTransit + outgoingCommand -> fragmentLength > ENET_MAX (windowSize, peer -> mtu))
1510                windowExceeded = 1;
1511           }
1512           if (windowExceeded)
1513           {
1514              currentCommand = enet_list_next (currentCommand);
1515 
1516              continue;
1517           }
1518        }
1519 
1520        canPing = 0;
1521 
1522        commandSize = commandSizes [outgoingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_MASK];
1523        if (command >= & host -> commands [sizeof (host -> commands) / sizeof (ENetProtocol)] ||
1524            buffer + 1 >= & host -> buffers [sizeof (host -> buffers) / sizeof (ENetBuffer)] ||
1525            peer -> mtu - host -> packetSize < commandSize ||
1526            (outgoingCommand -> packet != NULL &&
1527              (enet_uint16) (peer -> mtu - host -> packetSize) < (enet_uint16) (commandSize + outgoingCommand -> fragmentLength)))
1528        {
1529           host -> continueSending = 1;
1530 
1531           break;
1532        }
1533 
1534        currentCommand = enet_list_next (currentCommand);
1535 
1536        if (channel != NULL && outgoingCommand -> sendAttempts < 1)
1537        {
1538           channel -> usedReliableWindows |= 1 << reliableWindow;
1539           ++ channel -> reliableWindows [reliableWindow];
1540        }
1541 
1542        ++ outgoingCommand -> sendAttempts;
1543 
1544        if (outgoingCommand -> roundTripTimeout == 0)
1545        {
1546           outgoingCommand -> roundTripTimeout = peer -> roundTripTime + 4 * peer -> roundTripTimeVariance;
1547           outgoingCommand -> roundTripTimeoutLimit = peer -> timeoutLimit * outgoingCommand -> roundTripTimeout;
1548        }
1549 
1550        if (enet_list_empty (& peer -> sentReliableCommands))
1551          peer -> nextTimeout = host -> serviceTime + outgoingCommand -> roundTripTimeout;
1552 
1553        enet_list_insert (enet_list_end (& peer -> sentReliableCommands),
1554                          enet_list_remove (& outgoingCommand -> outgoingCommandList));
1555 
1556        outgoingCommand -> sentTime = host -> serviceTime;
1557 
1558        buffer -> data = command;
1559        buffer -> dataLength = commandSize;
1560 
1561        host -> packetSize += buffer -> dataLength;
1562        host -> headerFlags |= ENET_PROTOCOL_HEADER_FLAG_SENT_TIME;
1563 
1564        * command = outgoingCommand -> command;
1565 
1566        if (outgoingCommand -> packet != NULL)
1567        {
1568           ++ buffer;
1569 
1570           buffer -> data = outgoingCommand -> packet -> data + outgoingCommand -> fragmentOffset;
1571           buffer -> dataLength = outgoingCommand -> fragmentLength;
1572 
1573           host -> packetSize += outgoingCommand -> fragmentLength;
1574 
1575           peer -> reliableDataInTransit += outgoingCommand -> fragmentLength;
1576        }
1577 
1578        ++ peer -> packetsSent;
1579 
1580        ++ command;
1581        ++ buffer;
1582     }
1583 
1584     host -> commandCount = command - host -> commands;
1585     host -> bufferCount = buffer - host -> buffers;
1586 
1587     return canPing;
1588 }
1589 
1590 static int
enet_protocol_send_outgoing_commands(ENetHost * host,ENetEvent * event,int checkForTimeouts)1591 enet_protocol_send_outgoing_commands (ENetHost * host, ENetEvent * event, int checkForTimeouts)
1592 {
1593     enet_uint8 headerData [sizeof (ENetProtocolHeader) + sizeof (enet_uint32)];
1594     ENetProtocolHeader * header = (ENetProtocolHeader *) headerData;
1595     ENetPeer * currentPeer;
1596     int sentLength;
1597     size_t shouldCompress = 0;
1598 
1599     host -> continueSending = 1;
1600 
1601     while (host -> continueSending)
1602     for (host -> continueSending = 0,
1603            currentPeer = host -> peers;
1604          currentPeer < & host -> peers [host -> peerCount];
1605          ++ currentPeer)
1606     {
1607         if (currentPeer -> state == ENET_PEER_STATE_DISCONNECTED ||
1608             currentPeer -> state == ENET_PEER_STATE_ZOMBIE)
1609           continue;
1610 
1611         host -> headerFlags = 0;
1612         host -> commandCount = 0;
1613         host -> bufferCount = 1;
1614         host -> packetSize = sizeof (ENetProtocolHeader);
1615 
1616         if (! enet_list_empty (& currentPeer -> acknowledgements))
1617           enet_protocol_send_acknowledgements (host, currentPeer);
1618 
1619         if (checkForTimeouts != 0 &&
1620             ! enet_list_empty (& currentPeer -> sentReliableCommands) &&
1621             ENET_TIME_GREATER_EQUAL (host -> serviceTime, currentPeer -> nextTimeout) &&
1622             enet_protocol_check_timeouts (host, currentPeer, event) == 1)
1623         {
1624             if (event != NULL && event -> type != ENET_EVENT_TYPE_NONE)
1625               return 1;
1626             else
1627               continue;
1628         }
1629 
1630         if ((enet_list_empty (& currentPeer -> outgoingReliableCommands) ||
1631               enet_protocol_send_reliable_outgoing_commands (host, currentPeer)) &&
1632             enet_list_empty (& currentPeer -> sentReliableCommands) &&
1633             ENET_TIME_DIFFERENCE (host -> serviceTime, currentPeer -> lastReceiveTime) >= currentPeer -> pingInterval &&
1634             currentPeer -> mtu - host -> packetSize >= sizeof (ENetProtocolPing))
1635         {
1636             enet_peer_ping (currentPeer);
1637             enet_protocol_send_reliable_outgoing_commands (host, currentPeer);
1638         }
1639 
1640         if (! enet_list_empty (& currentPeer -> outgoingUnreliableCommands))
1641           enet_protocol_send_unreliable_outgoing_commands (host, currentPeer);
1642 
1643         if (host -> commandCount == 0)
1644           continue;
1645 
1646         if (currentPeer -> packetLossEpoch == 0)
1647           currentPeer -> packetLossEpoch = host -> serviceTime;
1648         else
1649         if (ENET_TIME_DIFFERENCE (host -> serviceTime, currentPeer -> packetLossEpoch) >= ENET_PEER_PACKET_LOSS_INTERVAL &&
1650             currentPeer -> packetsSent > 0)
1651         {
1652            enet_uint32 packetLoss = currentPeer -> packetsLost * ENET_PEER_PACKET_LOSS_SCALE / currentPeer -> packetsSent;
1653 
1654 #ifdef ENET_DEBUG
1655            printf ("peer %u: %f%%+-%f%% packet loss, %u+-%u ms round trip time, %f%% throttle, %u/%u outgoing, %u/%u incoming\n", currentPeer -> incomingPeerID, currentPeer -> packetLoss / (float) ENET_PEER_PACKET_LOSS_SCALE, currentPeer -> packetLossVariance / (float) ENET_PEER_PACKET_LOSS_SCALE, currentPeer -> roundTripTime, currentPeer -> roundTripTimeVariance, currentPeer -> packetThrottle / (float) ENET_PEER_PACKET_THROTTLE_SCALE, enet_list_size (& currentPeer -> outgoingReliableCommands), enet_list_size (& currentPeer -> outgoingUnreliableCommands), currentPeer -> channels != NULL ? enet_list_size (& currentPeer -> channels -> incomingReliableCommands) : 0, currentPeer -> channels != NULL ? enet_list_size (& currentPeer -> channels -> incomingUnreliableCommands) : 0);
1656 #endif
1657 
1658            currentPeer -> packetLossVariance -= currentPeer -> packetLossVariance / 4;
1659 
1660            if (packetLoss >= currentPeer -> packetLoss)
1661            {
1662               currentPeer -> packetLoss += (packetLoss - currentPeer -> packetLoss) / 8;
1663               currentPeer -> packetLossVariance += (packetLoss - currentPeer -> packetLoss) / 4;
1664            }
1665            else
1666            {
1667               currentPeer -> packetLoss -= (currentPeer -> packetLoss - packetLoss) / 8;
1668               currentPeer -> packetLossVariance += (currentPeer -> packetLoss - packetLoss) / 4;
1669            }
1670 
1671            currentPeer -> packetLossEpoch = host -> serviceTime;
1672            currentPeer -> packetsSent = 0;
1673            currentPeer -> packetsLost = 0;
1674         }
1675 
1676         host -> buffers -> data = headerData;
1677         if (host -> headerFlags & ENET_PROTOCOL_HEADER_FLAG_SENT_TIME)
1678         {
1679             header -> sentTime = ENET_HOST_TO_NET_16 (host -> serviceTime & 0xFFFF);
1680 
1681             host -> buffers -> dataLength = sizeof (ENetProtocolHeader);
1682         }
1683         else
1684           host -> buffers -> dataLength = (size_t) & ((ENetProtocolHeader *) 0) -> sentTime;
1685 
1686         shouldCompress = 0;
1687         if (host -> compressor.context != NULL && host -> compressor.compress != NULL)
1688         {
1689             size_t originalSize = host -> packetSize - sizeof(ENetProtocolHeader),
1690                    compressedSize = host -> compressor.compress (host -> compressor.context,
1691                                         & host -> buffers [1], host -> bufferCount - 1,
1692                                         originalSize,
1693                                         host -> packetData [1],
1694                                         originalSize);
1695             if (compressedSize > 0 && compressedSize < originalSize)
1696             {
1697                 host -> headerFlags |= ENET_PROTOCOL_HEADER_FLAG_COMPRESSED;
1698                 shouldCompress = compressedSize;
1699 #ifdef ENET_DEBUG_COMPRESS
1700                 printf ("peer %u: compressed %u -> %u (%u%%)\n", currentPeer -> incomingPeerID, originalSize, compressedSize, (compressedSize * 100) / originalSize);
1701 #endif
1702             }
1703         }
1704 
1705         if (currentPeer -> outgoingPeerID < ENET_PROTOCOL_MAXIMUM_PEER_ID)
1706           host -> headerFlags |= currentPeer -> outgoingSessionID << ENET_PROTOCOL_HEADER_SESSION_SHIFT;
1707         header -> peerID = ENET_HOST_TO_NET_16 (currentPeer -> outgoingPeerID | host -> headerFlags);
1708         if (host -> checksum != NULL)
1709         {
1710             enet_uint32 * checksum = (enet_uint32 *) & headerData [host -> buffers -> dataLength];
1711             * checksum = currentPeer -> outgoingPeerID < ENET_PROTOCOL_MAXIMUM_PEER_ID ? currentPeer -> connectID : 0;
1712             host -> buffers -> dataLength += sizeof (enet_uint32);
1713             * checksum = host -> checksum (host -> buffers, host -> bufferCount);
1714         }
1715 
1716         if (shouldCompress > 0)
1717         {
1718             host -> buffers [1].data = host -> packetData [1];
1719             host -> buffers [1].dataLength = shouldCompress;
1720             host -> bufferCount = 2;
1721         }
1722 
1723         currentPeer -> lastSendTime = host -> serviceTime;
1724 
1725         sentLength = enet_socket_send (host -> socket, & currentPeer -> address, host -> buffers, host -> bufferCount);
1726 
1727         enet_protocol_remove_sent_unreliable_commands (currentPeer);
1728 
1729         if (sentLength < 0)
1730           return -1;
1731 
1732         host -> totalSentData += sentLength;
1733         host -> totalSentPackets ++;
1734     }
1735 
1736     return 0;
1737 }
1738 
1739 /** Sends any queued packets on the host specified to its designated peers.
1740 
1741     @param host   host to flush
1742     @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().
1743     @ingroup host
1744 */
1745 void
enet_host_flush(ENetHost * host)1746 enet_host_flush (ENetHost * host)
1747 {
1748     host -> serviceTime = enet_time_get ();
1749 
1750     enet_protocol_send_outgoing_commands (host, NULL, 0);
1751 }
1752 
1753 /** Checks for any queued events on the host and dispatches one if available.
1754 
1755     @param host    host to check for events
1756     @param event   an event structure where event details will be placed if available
1757     @retval > 0 if an event was dispatched
1758     @retval 0 if no events are available
1759     @retval < 0 on failure
1760     @ingroup host
1761 */
1762 int
enet_host_check_events(ENetHost * host,ENetEvent * event)1763 enet_host_check_events (ENetHost * host, ENetEvent * event)
1764 {
1765     if (event == NULL) return -1;
1766 
1767     event -> type = ENET_EVENT_TYPE_NONE;
1768     event -> peer = NULL;
1769     event -> packet = NULL;
1770 
1771     return enet_protocol_dispatch_incoming_commands (host, event);
1772 }
1773 
1774 /** Waits for events on the host specified and shuttles packets between
1775     the host and its peers.
1776 
1777     @param host    host to service
1778     @param event   an event structure where event details will be placed if one occurs
1779                    if event == NULL then no events will be delivered
1780     @param timeout number of milliseconds that ENet should wait for events
1781     @retval > 0 if an event occurred within the specified time limit
1782     @retval 0 if no event occurred
1783     @retval < 0 on failure
1784     @remarks enet_host_service should be called fairly regularly for adequate performance
1785     @ingroup host
1786 */
1787 int
enet_host_service(ENetHost * host,ENetEvent * event,enet_uint32 timeout)1788 enet_host_service (ENetHost * host, ENetEvent * event, enet_uint32 timeout)
1789 {
1790     enet_uint32 waitCondition;
1791 
1792     if (event != NULL)
1793     {
1794         event -> type = ENET_EVENT_TYPE_NONE;
1795         event -> peer = NULL;
1796         event -> packet = NULL;
1797 
1798         switch (enet_protocol_dispatch_incoming_commands (host, event))
1799         {
1800         case 1:
1801             return 1;
1802 
1803         case -1:
1804 #ifdef ENET_DEBUG
1805             perror ("Error dispatching incoming packets");
1806 #endif
1807 
1808             return -1;
1809 
1810         default:
1811             break;
1812         }
1813     }
1814 
1815     host -> serviceTime = enet_time_get ();
1816 
1817     timeout += host -> serviceTime;
1818 
1819     do
1820     {
1821        if (ENET_TIME_DIFFERENCE (host -> serviceTime, host -> bandwidthThrottleEpoch) >= ENET_HOST_BANDWIDTH_THROTTLE_INTERVAL)
1822          enet_host_bandwidth_throttle (host);
1823 
1824        switch (enet_protocol_send_outgoing_commands (host, event, 1))
1825        {
1826        case 1:
1827           return 1;
1828 
1829        case -1:
1830 #ifdef ENET_DEBUG
1831           perror ("Error sending outgoing packets");
1832 #endif
1833 
1834           return -1;
1835 
1836        default:
1837           break;
1838        }
1839 
1840        switch (enet_protocol_receive_incoming_commands (host, event))
1841        {
1842        case 1:
1843           return 1;
1844 
1845        case -1:
1846 #ifdef ENET_DEBUG
1847           perror ("Error receiving incoming packets");
1848 #endif
1849 
1850           return -1;
1851 
1852        default:
1853           break;
1854        }
1855 
1856        switch (enet_protocol_send_outgoing_commands (host, event, 1))
1857        {
1858        case 1:
1859           return 1;
1860 
1861        case -1:
1862 #ifdef ENET_DEBUG
1863           perror ("Error sending outgoing packets");
1864 #endif
1865 
1866           return -1;
1867 
1868        default:
1869           break;
1870        }
1871 
1872        if (event != NULL)
1873        {
1874           switch (enet_protocol_dispatch_incoming_commands (host, event))
1875           {
1876           case 1:
1877              return 1;
1878 
1879           case -1:
1880 #ifdef ENET_DEBUG
1881              perror ("Error dispatching incoming packets");
1882 #endif
1883 
1884              return -1;
1885 
1886           default:
1887              break;
1888           }
1889        }
1890 
1891        if (ENET_TIME_GREATER_EQUAL (host -> serviceTime, timeout))
1892          return 0;
1893 
1894        do
1895        {
1896           host -> serviceTime = enet_time_get ();
1897 
1898           if (ENET_TIME_GREATER_EQUAL (host -> serviceTime, timeout))
1899             return 0;
1900 
1901           waitCondition = ENET_SOCKET_WAIT_RECEIVE | ENET_SOCKET_WAIT_INTERRUPT;
1902 
1903           if (enet_socket_wait (host -> socket, & waitCondition, ENET_TIME_DIFFERENCE (timeout, host -> serviceTime)) != 0)
1904             return -1;
1905        }
1906        while (waitCondition & ENET_SOCKET_WAIT_INTERRUPT);
1907 
1908        host -> serviceTime = enet_time_get ();
1909     } while (waitCondition & ENET_SOCKET_WAIT_RECEIVE);
1910 
1911     return 0;
1912 }
1913 
1914