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       peer -> windowSize = (ENET_MIN (peer -> incomingBandwidth, host -> outgoingBandwidth) /
769                              ENET_PEER_WINDOW_SIZE_SCALE) * ENET_PROTOCOL_MINIMUM_WINDOW_SIZE;
770 
771     if (peer -> windowSize < ENET_PROTOCOL_MINIMUM_WINDOW_SIZE)
772       peer -> windowSize = ENET_PROTOCOL_MINIMUM_WINDOW_SIZE;
773     else
774     if (peer -> windowSize > ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE)
775       peer -> windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE;
776 
777     return 0;
778 }
779 
780 static int
enet_protocol_handle_throttle_configure(ENetHost * host,ENetPeer * peer,const ENetProtocol * command)781 enet_protocol_handle_throttle_configure (ENetHost * host, ENetPeer * peer, const ENetProtocol * command)
782 {
783     if (peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER)
784       return -1;
785 
786     peer -> packetThrottleInterval = ENET_NET_TO_HOST_32 (command -> throttleConfigure.packetThrottleInterval);
787     peer -> packetThrottleAcceleration = ENET_NET_TO_HOST_32 (command -> throttleConfigure.packetThrottleAcceleration);
788     peer -> packetThrottleDeceleration = ENET_NET_TO_HOST_32 (command -> throttleConfigure.packetThrottleDeceleration);
789 
790     return 0;
791 }
792 
793 static int
enet_protocol_handle_disconnect(ENetHost * host,ENetPeer * peer,const ENetProtocol * command)794 enet_protocol_handle_disconnect (ENetHost * host, ENetPeer * peer, const ENetProtocol * command)
795 {
796     if (peer -> state == ENET_PEER_STATE_DISCONNECTED || peer -> state == ENET_PEER_STATE_ZOMBIE || peer -> state == ENET_PEER_STATE_ACKNOWLEDGING_DISCONNECT)
797       return 0;
798 
799     enet_peer_reset_queues (peer);
800 
801     if (peer -> state == ENET_PEER_STATE_CONNECTION_SUCCEEDED || peer -> state == ENET_PEER_STATE_DISCONNECTING || peer -> state == ENET_PEER_STATE_CONNECTING)
802         enet_protocol_dispatch_state (host, peer, ENET_PEER_STATE_ZOMBIE);
803     else
804     if (peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER)
805     {
806         if (peer -> state == ENET_PEER_STATE_CONNECTION_PENDING) host -> recalculateBandwidthLimits = 1;
807 
808         enet_peer_reset (peer);
809     }
810     else
811     if (command -> header.command & ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE)
812       enet_protocol_change_state (host, peer, ENET_PEER_STATE_ACKNOWLEDGING_DISCONNECT);
813     else
814       enet_protocol_dispatch_state (host, peer, ENET_PEER_STATE_ZOMBIE);
815 
816     if (peer -> state != ENET_PEER_STATE_DISCONNECTED)
817       peer -> eventData = ENET_NET_TO_HOST_32 (command -> disconnect.data);
818 
819     return 0;
820 }
821 
822 static int
enet_protocol_handle_acknowledge(ENetHost * host,ENetEvent * event,ENetPeer * peer,const ENetProtocol * command)823 enet_protocol_handle_acknowledge (ENetHost * host, ENetEvent * event, ENetPeer * peer, const ENetProtocol * command)
824 {
825     enet_uint32 roundTripTime,
826            receivedSentTime,
827            receivedReliableSequenceNumber;
828     ENetProtocolCommand commandNumber;
829 
830     if (peer -> state == ENET_PEER_STATE_DISCONNECTED || peer -> state == ENET_PEER_STATE_ZOMBIE)
831       return 0;
832 
833     receivedSentTime = ENET_NET_TO_HOST_16 (command -> acknowledge.receivedSentTime);
834     receivedSentTime |= host -> serviceTime & 0xFFFF0000;
835     if ((receivedSentTime & 0x8000) > (host -> serviceTime & 0x8000))
836         receivedSentTime -= 0x10000;
837 
838     if (ENET_TIME_LESS (host -> serviceTime, receivedSentTime))
839       return 0;
840 
841     peer -> lastReceiveTime = host -> serviceTime;
842     peer -> earliestTimeout = 0;
843 
844     roundTripTime = ENET_TIME_DIFFERENCE (host -> serviceTime, receivedSentTime);
845 
846     enet_peer_throttle (peer, roundTripTime);
847 
848     peer -> roundTripTimeVariance -= peer -> roundTripTimeVariance / 4;
849 
850     if (roundTripTime >= peer -> roundTripTime)
851     {
852        peer -> roundTripTime += (roundTripTime - peer -> roundTripTime) / 8;
853        peer -> roundTripTimeVariance += (roundTripTime - peer -> roundTripTime) / 4;
854     }
855     else
856     {
857        peer -> roundTripTime -= (peer -> roundTripTime - roundTripTime) / 8;
858        peer -> roundTripTimeVariance += (peer -> roundTripTime - roundTripTime) / 4;
859     }
860 
861     if (peer -> roundTripTime < peer -> lowestRoundTripTime)
862       peer -> lowestRoundTripTime = peer -> roundTripTime;
863 
864     if (peer -> roundTripTimeVariance > peer -> highestRoundTripTimeVariance)
865       peer -> highestRoundTripTimeVariance = peer -> roundTripTimeVariance;
866 
867     if (peer -> packetThrottleEpoch == 0 ||
868         ENET_TIME_DIFFERENCE (host -> serviceTime, peer -> packetThrottleEpoch) >= peer -> packetThrottleInterval)
869     {
870         peer -> lastRoundTripTime = peer -> lowestRoundTripTime;
871         peer -> lastRoundTripTimeVariance = peer -> highestRoundTripTimeVariance;
872         peer -> lowestRoundTripTime = peer -> roundTripTime;
873         peer -> highestRoundTripTimeVariance = peer -> roundTripTimeVariance;
874         peer -> packetThrottleEpoch = host -> serviceTime;
875     }
876 
877     receivedReliableSequenceNumber = ENET_NET_TO_HOST_16 (command -> acknowledge.receivedReliableSequenceNumber);
878 
879     commandNumber = enet_protocol_remove_sent_reliable_command (peer, receivedReliableSequenceNumber, command -> header.channelID);
880 
881     switch (peer -> state)
882     {
883     case ENET_PEER_STATE_ACKNOWLEDGING_CONNECT:
884        if (commandNumber != ENET_PROTOCOL_COMMAND_VERIFY_CONNECT)
885          return -1;
886 
887        enet_protocol_notify_connect (host, peer, event);
888        break;
889 
890     case ENET_PEER_STATE_DISCONNECTING:
891        if (commandNumber != ENET_PROTOCOL_COMMAND_DISCONNECT)
892          return -1;
893 
894        enet_protocol_notify_disconnect (host, peer, event);
895        break;
896 
897     case ENET_PEER_STATE_DISCONNECT_LATER:
898        if (enet_list_empty (& peer -> outgoingReliableCommands) &&
899            enet_list_empty (& peer -> outgoingUnreliableCommands) &&
900            enet_list_empty (& peer -> sentReliableCommands))
901          enet_peer_disconnect (peer, peer -> eventData);
902        break;
903 
904     default:
905        break;
906     }
907 
908     return 0;
909 }
910 
911 static int
enet_protocol_handle_verify_connect(ENetHost * host,ENetEvent * event,ENetPeer * peer,const ENetProtocol * command)912 enet_protocol_handle_verify_connect (ENetHost * host, ENetEvent * event, ENetPeer * peer, const ENetProtocol * command)
913 {
914     enet_uint32 mtu, windowSize;
915     size_t channelCount;
916 
917     if (peer -> state != ENET_PEER_STATE_CONNECTING)
918       return 0;
919 
920     channelCount = ENET_NET_TO_HOST_32 (command -> verifyConnect.channelCount);
921 
922     if (channelCount < ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT || channelCount > ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT ||
923         ENET_NET_TO_HOST_32 (command -> verifyConnect.packetThrottleInterval) != peer -> packetThrottleInterval ||
924         ENET_NET_TO_HOST_32 (command -> verifyConnect.packetThrottleAcceleration) != peer -> packetThrottleAcceleration ||
925         ENET_NET_TO_HOST_32 (command -> verifyConnect.packetThrottleDeceleration) != peer -> packetThrottleDeceleration ||
926         command -> verifyConnect.connectID != peer -> connectID)
927     {
928         peer -> eventData = 0;
929 
930         enet_protocol_dispatch_state (host, peer, ENET_PEER_STATE_ZOMBIE);
931 
932         return -1;
933     }
934 
935     enet_protocol_remove_sent_reliable_command (peer, 1, 0xFF);
936 
937     if (channelCount < peer -> channelCount)
938       peer -> channelCount = channelCount;
939 
940     peer -> outgoingPeerID = ENET_NET_TO_HOST_16 (command -> verifyConnect.outgoingPeerID);
941     peer -> incomingSessionID = command -> verifyConnect.incomingSessionID;
942     peer -> outgoingSessionID = command -> verifyConnect.outgoingSessionID;
943 
944     mtu = ENET_NET_TO_HOST_32 (command -> verifyConnect.mtu);
945 
946     if (mtu < ENET_PROTOCOL_MINIMUM_MTU)
947       mtu = ENET_PROTOCOL_MINIMUM_MTU;
948     else
949     if (mtu > ENET_PROTOCOL_MAXIMUM_MTU)
950       mtu = ENET_PROTOCOL_MAXIMUM_MTU;
951 
952     if (mtu < peer -> mtu)
953       peer -> mtu = mtu;
954 
955     windowSize = ENET_NET_TO_HOST_32 (command -> verifyConnect.windowSize);
956 
957     if (windowSize < ENET_PROTOCOL_MINIMUM_WINDOW_SIZE)
958       windowSize = ENET_PROTOCOL_MINIMUM_WINDOW_SIZE;
959 
960     if (windowSize > ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE)
961       windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE;
962 
963     if (windowSize < peer -> windowSize)
964       peer -> windowSize = windowSize;
965 
966     peer -> incomingBandwidth = ENET_NET_TO_HOST_32 (command -> verifyConnect.incomingBandwidth);
967     peer -> outgoingBandwidth = ENET_NET_TO_HOST_32 (command -> verifyConnect.outgoingBandwidth);
968 
969     enet_protocol_notify_connect (host, peer, event);
970     return 0;
971 }
972 
973 static int
enet_protocol_handle_incoming_commands(ENetHost * host,ENetEvent * event)974 enet_protocol_handle_incoming_commands (ENetHost * host, ENetEvent * event)
975 {
976     ENetProtocolHeader * header;
977     ENetProtocol * command;
978     ENetPeer * peer;
979     enet_uint8 * currentData;
980     size_t headerSize;
981     enet_uint16 peerID, flags;
982     enet_uint8 sessionID;
983 
984     if (host -> receivedDataLength < (size_t) & ((ENetProtocolHeader *) 0) -> sentTime)
985       return 0;
986 
987     header = (ENetProtocolHeader *) host -> receivedData;
988 
989     peerID = ENET_NET_TO_HOST_16 (header -> peerID);
990     sessionID = (peerID & ENET_PROTOCOL_HEADER_SESSION_MASK) >> ENET_PROTOCOL_HEADER_SESSION_SHIFT;
991     flags = peerID & ENET_PROTOCOL_HEADER_FLAG_MASK;
992     peerID &= ~ (ENET_PROTOCOL_HEADER_FLAG_MASK | ENET_PROTOCOL_HEADER_SESSION_MASK);
993 
994     headerSize = (flags & ENET_PROTOCOL_HEADER_FLAG_SENT_TIME ? sizeof (ENetProtocolHeader) : (size_t) & ((ENetProtocolHeader *) 0) -> sentTime);
995     if (host -> checksum != NULL)
996       headerSize += sizeof (enet_uint32);
997 
998     if (peerID == ENET_PROTOCOL_MAXIMUM_PEER_ID)
999       peer = NULL;
1000     else
1001     if (peerID >= host -> peerCount)
1002       return 0;
1003     else
1004     {
1005        peer = & host -> peers [peerID];
1006 
1007        if (peer -> state == ENET_PEER_STATE_DISCONNECTED ||
1008            peer -> state == ENET_PEER_STATE_ZOMBIE ||
1009            ((host -> receivedAddress.host != peer -> address.host ||
1010              host -> receivedAddress.port != peer -> address.port) &&
1011              peer -> address.host != ENET_HOST_BROADCAST) ||
1012            (peer -> outgoingPeerID < ENET_PROTOCOL_MAXIMUM_PEER_ID &&
1013             sessionID != peer -> incomingSessionID))
1014          return 0;
1015     }
1016 
1017     if (flags & ENET_PROTOCOL_HEADER_FLAG_COMPRESSED)
1018     {
1019         size_t originalSize;
1020         if (host -> compressor.context == NULL || host -> compressor.decompress == NULL)
1021           return 0;
1022 
1023         originalSize = host -> compressor.decompress (host -> compressor.context,
1024                                     host -> receivedData + headerSize,
1025                                     host -> receivedDataLength - headerSize,
1026                                     host -> packetData [1] + headerSize,
1027                                     sizeof (host -> packetData [1]) - headerSize);
1028         if (originalSize <= 0 || originalSize > sizeof (host -> packetData [1]) - headerSize)
1029           return 0;
1030 
1031         memcpy (host -> packetData [1], header, headerSize);
1032         host -> receivedData = host -> packetData [1];
1033         host -> receivedDataLength = headerSize + originalSize;
1034     }
1035 
1036     if (host -> checksum != NULL)
1037     {
1038         enet_uint32 * checksum = (enet_uint32 *) & host -> receivedData [headerSize - sizeof (enet_uint32)],
1039                     desiredChecksum = * checksum;
1040         ENetBuffer buffer;
1041 
1042         * checksum = peer != NULL ? peer -> connectID : 0;
1043 
1044         buffer.data = host -> receivedData;
1045         buffer.dataLength = host -> receivedDataLength;
1046 
1047         if (host -> checksum (& buffer, 1) != desiredChecksum)
1048           return 0;
1049     }
1050 
1051     if (peer != NULL)
1052     {
1053        peer -> address.host = host -> receivedAddress.host;
1054        peer -> address.port = host -> receivedAddress.port;
1055        peer -> incomingDataTotal += host -> receivedDataLength;
1056     }
1057 
1058     currentData = host -> receivedData + headerSize;
1059 
1060     while (currentData < & host -> receivedData [host -> receivedDataLength])
1061     {
1062        enet_uint8 commandNumber;
1063        size_t commandSize;
1064 
1065        command = (ENetProtocol *) currentData;
1066 
1067        if (currentData + sizeof (ENetProtocolCommandHeader) > & host -> receivedData [host -> receivedDataLength])
1068          break;
1069 
1070        commandNumber = command -> header.command & ENET_PROTOCOL_COMMAND_MASK;
1071        if (commandNumber >= ENET_PROTOCOL_COMMAND_COUNT)
1072          break;
1073 
1074        commandSize = commandSizes [commandNumber];
1075        if (commandSize == 0 || currentData + commandSize > & host -> receivedData [host -> receivedDataLength])
1076          break;
1077 
1078        currentData += commandSize;
1079 
1080        if (peer == NULL && commandNumber != ENET_PROTOCOL_COMMAND_CONNECT)
1081          break;
1082 
1083        command -> header.reliableSequenceNumber = ENET_NET_TO_HOST_16 (command -> header.reliableSequenceNumber);
1084 
1085        switch (commandNumber)
1086        {
1087        case ENET_PROTOCOL_COMMAND_ACKNOWLEDGE:
1088           if (enet_protocol_handle_acknowledge (host, event, peer, command))
1089             goto commandError;
1090           break;
1091 
1092        case ENET_PROTOCOL_COMMAND_CONNECT:
1093           if (peer != NULL)
1094             goto commandError;
1095           peer = enet_protocol_handle_connect (host, header, command);
1096           if (peer == NULL)
1097             goto commandError;
1098           break;
1099 
1100        case ENET_PROTOCOL_COMMAND_VERIFY_CONNECT:
1101           if (enet_protocol_handle_verify_connect (host, event, peer, command))
1102             goto commandError;
1103           break;
1104 
1105        case ENET_PROTOCOL_COMMAND_DISCONNECT:
1106           if (enet_protocol_handle_disconnect (host, peer, command))
1107             goto commandError;
1108           break;
1109 
1110        case ENET_PROTOCOL_COMMAND_PING:
1111           if (enet_protocol_handle_ping (host, peer, command))
1112             goto commandError;
1113           break;
1114 
1115        case ENET_PROTOCOL_COMMAND_SEND_RELIABLE:
1116           if (enet_protocol_handle_send_reliable (host, peer, command, & currentData))
1117             goto commandError;
1118           break;
1119 
1120        case ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE:
1121           if (enet_protocol_handle_send_unreliable (host, peer, command, & currentData))
1122             goto commandError;
1123           break;
1124 
1125        case ENET_PROTOCOL_COMMAND_SEND_UNSEQUENCED:
1126           if (enet_protocol_handle_send_unsequenced (host, peer, command, & currentData))
1127             goto commandError;
1128           break;
1129 
1130        case ENET_PROTOCOL_COMMAND_SEND_FRAGMENT:
1131           if (enet_protocol_handle_send_fragment (host, peer, command, & currentData))
1132             goto commandError;
1133           break;
1134 
1135        case ENET_PROTOCOL_COMMAND_BANDWIDTH_LIMIT:
1136           if (enet_protocol_handle_bandwidth_limit (host, peer, command))
1137             goto commandError;
1138           break;
1139 
1140        case ENET_PROTOCOL_COMMAND_THROTTLE_CONFIGURE:
1141           if (enet_protocol_handle_throttle_configure (host, peer, command))
1142             goto commandError;
1143           break;
1144 
1145        case ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE_FRAGMENT:
1146           if (enet_protocol_handle_send_unreliable_fragment (host, peer, command, & currentData))
1147             goto commandError;
1148           break;
1149 
1150        default:
1151           goto commandError;
1152        }
1153 
1154        if (peer != NULL &&
1155            (command -> header.command & ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE) != 0)
1156        {
1157            enet_uint16 sentTime;
1158 
1159            if (! (flags & ENET_PROTOCOL_HEADER_FLAG_SENT_TIME))
1160              break;
1161 
1162            sentTime = ENET_NET_TO_HOST_16 (header -> sentTime);
1163 
1164            switch (peer -> state)
1165            {
1166            case ENET_PEER_STATE_DISCONNECTING:
1167            case ENET_PEER_STATE_ACKNOWLEDGING_CONNECT:
1168            case ENET_PEER_STATE_DISCONNECTED:
1169            case ENET_PEER_STATE_ZOMBIE:
1170               break;
1171 
1172            case ENET_PEER_STATE_ACKNOWLEDGING_DISCONNECT:
1173               if ((command -> header.command & ENET_PROTOCOL_COMMAND_MASK) == ENET_PROTOCOL_COMMAND_DISCONNECT)
1174                 enet_peer_queue_acknowledgement (peer, command, sentTime);
1175               break;
1176 
1177            default:
1178               enet_peer_queue_acknowledgement (peer, command, sentTime);
1179               break;
1180            }
1181        }
1182     }
1183 
1184 commandError:
1185     if (event != NULL && event -> type != ENET_EVENT_TYPE_NONE)
1186       return 1;
1187 
1188     return 0;
1189 }
1190 
1191 static int
enet_protocol_receive_incoming_commands(ENetHost * host,ENetEvent * event)1192 enet_protocol_receive_incoming_commands (ENetHost * host, ENetEvent * event)
1193 {
1194     for (;;)
1195     {
1196        int receivedLength;
1197        ENetBuffer buffer;
1198 
1199        buffer.data = host -> packetData [0];
1200        buffer.dataLength = sizeof (host -> packetData [0]);
1201 
1202        receivedLength = enet_socket_receive (host -> socket,
1203                                              & host -> receivedAddress,
1204                                              & buffer,
1205                                              1);
1206 
1207        if (receivedLength < 0)
1208          return -1;
1209 
1210        if (receivedLength == 0)
1211          return 0;
1212 
1213        host -> receivedData = host -> packetData [0];
1214        host -> receivedDataLength = receivedLength;
1215 
1216        host -> totalReceivedData += receivedLength;
1217        host -> totalReceivedPackets ++;
1218 
1219        if (host -> intercept != NULL)
1220        {
1221           switch (host -> intercept (host, event))
1222           {
1223           case 1:
1224              if (event != NULL && event -> type != ENET_EVENT_TYPE_NONE)
1225                return 1;
1226 
1227              continue;
1228 
1229           case -1:
1230              return -1;
1231 
1232           default:
1233              break;
1234           }
1235        }
1236 
1237        switch (enet_protocol_handle_incoming_commands (host, event))
1238        {
1239        case 1:
1240           return 1;
1241 
1242        case -1:
1243           return -1;
1244 
1245        default:
1246           break;
1247        }
1248     }
1249 
1250     return -1;
1251 }
1252 
1253 static void
enet_protocol_send_acknowledgements(ENetHost * host,ENetPeer * peer)1254 enet_protocol_send_acknowledgements (ENetHost * host, ENetPeer * peer)
1255 {
1256     ENetProtocol * command = & host -> commands [host -> commandCount];
1257     ENetBuffer * buffer = & host -> buffers [host -> bufferCount];
1258     ENetAcknowledgement * acknowledgement;
1259     ENetListIterator currentAcknowledgement;
1260     enet_uint16 reliableSequenceNumber;
1261 
1262     currentAcknowledgement = enet_list_begin (& peer -> acknowledgements);
1263 
1264     while (currentAcknowledgement != enet_list_end (& peer -> acknowledgements))
1265     {
1266        if (command >= & host -> commands [sizeof (host -> commands) / sizeof (ENetProtocol)] ||
1267            buffer >= & host -> buffers [sizeof (host -> buffers) / sizeof (ENetBuffer)] ||
1268            peer -> mtu - host -> packetSize < sizeof (ENetProtocolAcknowledge))
1269        {
1270           host -> continueSending = 1;
1271 
1272           break;
1273        }
1274 
1275        acknowledgement = (ENetAcknowledgement *) currentAcknowledgement;
1276 
1277        currentAcknowledgement = enet_list_next (currentAcknowledgement);
1278 
1279        buffer -> data = command;
1280        buffer -> dataLength = sizeof (ENetProtocolAcknowledge);
1281 
1282        host -> packetSize += buffer -> dataLength;
1283 
1284        reliableSequenceNumber = ENET_HOST_TO_NET_16 (acknowledgement -> command.header.reliableSequenceNumber);
1285 
1286        command -> header.command = ENET_PROTOCOL_COMMAND_ACKNOWLEDGE;
1287        command -> header.channelID = acknowledgement -> command.header.channelID;
1288        command -> header.reliableSequenceNumber = reliableSequenceNumber;
1289        command -> acknowledge.receivedReliableSequenceNumber = reliableSequenceNumber;
1290        command -> acknowledge.receivedSentTime = ENET_HOST_TO_NET_16 (acknowledgement -> sentTime);
1291 
1292        if ((acknowledgement -> command.header.command & ENET_PROTOCOL_COMMAND_MASK) == ENET_PROTOCOL_COMMAND_DISCONNECT)
1293          enet_protocol_dispatch_state (host, peer, ENET_PEER_STATE_ZOMBIE);
1294 
1295        enet_list_remove (& acknowledgement -> acknowledgementList);
1296        enet_free (acknowledgement);
1297 
1298        ++ command;
1299        ++ buffer;
1300     }
1301 
1302     host -> commandCount = command - host -> commands;
1303     host -> bufferCount = buffer - host -> buffers;
1304 }
1305 
1306 static void
enet_protocol_send_unreliable_outgoing_commands(ENetHost * host,ENetPeer * peer)1307 enet_protocol_send_unreliable_outgoing_commands (ENetHost * host, ENetPeer * peer)
1308 {
1309     ENetProtocol * command = & host -> commands [host -> commandCount];
1310     ENetBuffer * buffer = & host -> buffers [host -> bufferCount];
1311     ENetOutgoingCommand * outgoingCommand;
1312     ENetListIterator currentCommand;
1313 
1314     currentCommand = enet_list_begin (& peer -> outgoingUnreliableCommands);
1315 
1316     while (currentCommand != enet_list_end (& peer -> outgoingUnreliableCommands))
1317     {
1318        size_t commandSize;
1319 
1320        outgoingCommand = (ENetOutgoingCommand *) currentCommand;
1321        commandSize = commandSizes [outgoingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_MASK];
1322 
1323        if (command >= & host -> commands [sizeof (host -> commands) / sizeof (ENetProtocol)] ||
1324            buffer + 1 >= & host -> buffers [sizeof (host -> buffers) / sizeof (ENetBuffer)] ||
1325            peer -> mtu - host -> packetSize < commandSize ||
1326            (outgoingCommand -> packet != NULL &&
1327              peer -> mtu - host -> packetSize < commandSize + outgoingCommand -> fragmentLength))
1328        {
1329           host -> continueSending = 1;
1330 
1331           break;
1332        }
1333 
1334        currentCommand = enet_list_next (currentCommand);
1335 
1336        if (outgoingCommand -> packet != NULL && outgoingCommand -> fragmentOffset == 0)
1337        {
1338           peer -> packetThrottleCounter += ENET_PEER_PACKET_THROTTLE_COUNTER;
1339           peer -> packetThrottleCounter %= ENET_PEER_PACKET_THROTTLE_SCALE;
1340 
1341           if (peer -> packetThrottleCounter > peer -> packetThrottle)
1342           {
1343              enet_uint16 reliableSequenceNumber = outgoingCommand -> reliableSequenceNumber,
1344                          unreliableSequenceNumber = outgoingCommand -> unreliableSequenceNumber;
1345              for (;;)
1346              {
1347                 -- outgoingCommand -> packet -> referenceCount;
1348 
1349                 if (outgoingCommand -> packet -> referenceCount == 0)
1350                   enet_packet_destroy (outgoingCommand -> packet);
1351 
1352                 enet_list_remove (& outgoingCommand -> outgoingCommandList);
1353                 enet_free (outgoingCommand);
1354 
1355                 if (currentCommand == enet_list_end (& peer -> outgoingUnreliableCommands))
1356                   break;
1357 
1358                 outgoingCommand = (ENetOutgoingCommand *) currentCommand;
1359                 if (outgoingCommand -> reliableSequenceNumber != reliableSequenceNumber ||
1360                     outgoingCommand -> unreliableSequenceNumber != unreliableSequenceNumber)
1361                   break;
1362 
1363                 currentCommand = enet_list_next (currentCommand);
1364              }
1365 
1366              continue;
1367           }
1368        }
1369 
1370        buffer -> data = command;
1371        buffer -> dataLength = commandSize;
1372 
1373        host -> packetSize += buffer -> dataLength;
1374 
1375        * command = outgoingCommand -> command;
1376 
1377        enet_list_remove (& outgoingCommand -> outgoingCommandList);
1378 
1379        if (outgoingCommand -> packet != NULL)
1380        {
1381           ++ buffer;
1382 
1383           buffer -> data = outgoingCommand -> packet -> data + outgoingCommand -> fragmentOffset;
1384           buffer -> dataLength = outgoingCommand -> fragmentLength;
1385 
1386           host -> packetSize += buffer -> dataLength;
1387 
1388           enet_list_insert (enet_list_end (& peer -> sentUnreliableCommands), outgoingCommand);
1389        }
1390        else
1391          enet_free (outgoingCommand);
1392 
1393        ++ command;
1394        ++ buffer;
1395     }
1396 
1397     host -> commandCount = command - host -> commands;
1398     host -> bufferCount = buffer - host -> buffers;
1399 
1400     if (peer -> state == ENET_PEER_STATE_DISCONNECT_LATER &&
1401         enet_list_empty (& peer -> outgoingReliableCommands) &&
1402         enet_list_empty (& peer -> outgoingUnreliableCommands) &&
1403         enet_list_empty (& peer -> sentReliableCommands))
1404       enet_peer_disconnect (peer, peer -> eventData);
1405 }
1406 
1407 static int
enet_protocol_check_timeouts(ENetHost * host,ENetPeer * peer,ENetEvent * event)1408 enet_protocol_check_timeouts (ENetHost * host, ENetPeer * peer, ENetEvent * event)
1409 {
1410     ENetOutgoingCommand * outgoingCommand;
1411     ENetListIterator currentCommand, insertPosition;
1412 
1413     currentCommand = enet_list_begin (& peer -> sentReliableCommands);
1414     insertPosition = enet_list_begin (& peer -> outgoingReliableCommands);
1415 
1416     while (currentCommand != enet_list_end (& peer -> sentReliableCommands))
1417     {
1418        outgoingCommand = (ENetOutgoingCommand *) currentCommand;
1419 
1420        currentCommand = enet_list_next (currentCommand);
1421 
1422        if (ENET_TIME_DIFFERENCE (host -> serviceTime, outgoingCommand -> sentTime) < outgoingCommand -> roundTripTimeout)
1423          continue;
1424 
1425        if (peer -> earliestTimeout == 0 ||
1426            ENET_TIME_LESS (outgoingCommand -> sentTime, peer -> earliestTimeout))
1427          peer -> earliestTimeout = outgoingCommand -> sentTime;
1428 
1429        if (peer -> earliestTimeout != 0 &&
1430              (ENET_TIME_DIFFERENCE (host -> serviceTime, peer -> earliestTimeout) >= peer -> timeoutMaximum ||
1431                (outgoingCommand -> roundTripTimeout >= outgoingCommand -> roundTripTimeoutLimit &&
1432                  ENET_TIME_DIFFERENCE (host -> serviceTime, peer -> earliestTimeout) >= peer -> timeoutMinimum)))
1433        {
1434           enet_protocol_notify_disconnect (host, peer, event);
1435 
1436           return 1;
1437        }
1438 
1439        if (outgoingCommand -> packet != NULL)
1440          peer -> reliableDataInTransit -= outgoingCommand -> fragmentLength;
1441 
1442        ++ peer -> packetsLost;
1443 
1444        outgoingCommand -> roundTripTimeout *= 2;
1445 
1446        enet_list_insert (insertPosition, enet_list_remove (& outgoingCommand -> outgoingCommandList));
1447 
1448        if (currentCommand == enet_list_begin (& peer -> sentReliableCommands) &&
1449            ! enet_list_empty (& peer -> sentReliableCommands))
1450        {
1451           outgoingCommand = (ENetOutgoingCommand *) currentCommand;
1452 
1453           peer -> nextTimeout = outgoingCommand -> sentTime + outgoingCommand -> roundTripTimeout;
1454        }
1455     }
1456 
1457     return 0;
1458 }
1459 
1460 static int
enet_protocol_send_reliable_outgoing_commands(ENetHost * host,ENetPeer * peer)1461 enet_protocol_send_reliable_outgoing_commands (ENetHost * host, ENetPeer * peer)
1462 {
1463     ENetProtocol * command = & host -> commands [host -> commandCount];
1464     ENetBuffer * buffer = & host -> buffers [host -> bufferCount];
1465     ENetOutgoingCommand * outgoingCommand;
1466     ENetListIterator currentCommand;
1467     ENetChannel *channel;
1468     enet_uint16 reliableWindow;
1469     size_t commandSize;
1470     int windowExceeded = 0, windowWrap = 0, canPing = 1;
1471 
1472     currentCommand = enet_list_begin (& peer -> outgoingReliableCommands);
1473 
1474     while (currentCommand != enet_list_end (& peer -> outgoingReliableCommands))
1475     {
1476        outgoingCommand = (ENetOutgoingCommand *) currentCommand;
1477 
1478        channel = outgoingCommand -> command.header.channelID < peer -> channelCount ? & peer -> channels [outgoingCommand -> command.header.channelID] : NULL;
1479        reliableWindow = outgoingCommand -> reliableSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE;
1480        if (channel != NULL)
1481        {
1482            if (! windowWrap &&
1483                outgoingCommand -> sendAttempts < 1 &&
1484                ! (outgoingCommand -> reliableSequenceNumber % ENET_PEER_RELIABLE_WINDOW_SIZE) &&
1485                (channel -> reliableWindows [(reliableWindow + ENET_PEER_RELIABLE_WINDOWS - 1) % ENET_PEER_RELIABLE_WINDOWS] >= ENET_PEER_RELIABLE_WINDOW_SIZE ||
1486                  channel -> usedReliableWindows & ((((1 << ENET_PEER_FREE_RELIABLE_WINDOWS) - 1) << reliableWindow) |
1487                    (((1 << ENET_PEER_FREE_RELIABLE_WINDOWS) - 1) >> (ENET_PEER_RELIABLE_WINDOW_SIZE - reliableWindow)))))
1488              windowWrap = 1;
1489           if (windowWrap)
1490           {
1491              currentCommand = enet_list_next (currentCommand);
1492 
1493              continue;
1494           }
1495        }
1496 
1497        if (outgoingCommand -> packet != NULL)
1498        {
1499           if (! windowExceeded)
1500           {
1501              enet_uint32 windowSize = (peer -> packetThrottle * peer -> windowSize) / ENET_PEER_PACKET_THROTTLE_SCALE;
1502 
1503              if (peer -> reliableDataInTransit + outgoingCommand -> fragmentLength > ENET_MAX (windowSize, peer -> mtu))
1504                windowExceeded = 1;
1505           }
1506           if (windowExceeded)
1507           {
1508              currentCommand = enet_list_next (currentCommand);
1509 
1510              continue;
1511           }
1512        }
1513 
1514        canPing = 0;
1515 
1516        commandSize = commandSizes [outgoingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_MASK];
1517        if (command >= & host -> commands [sizeof (host -> commands) / sizeof (ENetProtocol)] ||
1518            buffer + 1 >= & host -> buffers [sizeof (host -> buffers) / sizeof (ENetBuffer)] ||
1519            peer -> mtu - host -> packetSize < commandSize ||
1520            (outgoingCommand -> packet != NULL &&
1521              (enet_uint16) (peer -> mtu - host -> packetSize) < (enet_uint16) (commandSize + outgoingCommand -> fragmentLength)))
1522        {
1523           host -> continueSending = 1;
1524 
1525           break;
1526        }
1527 
1528        currentCommand = enet_list_next (currentCommand);
1529 
1530        if (channel != NULL && outgoingCommand -> sendAttempts < 1)
1531        {
1532           channel -> usedReliableWindows |= 1 << reliableWindow;
1533           ++ channel -> reliableWindows [reliableWindow];
1534        }
1535 
1536        ++ outgoingCommand -> sendAttempts;
1537 
1538        if (outgoingCommand -> roundTripTimeout == 0)
1539        {
1540           outgoingCommand -> roundTripTimeout = peer -> roundTripTime + 4 * peer -> roundTripTimeVariance;
1541           outgoingCommand -> roundTripTimeoutLimit = peer -> timeoutLimit * outgoingCommand -> roundTripTimeout;
1542        }
1543 
1544        if (enet_list_empty (& peer -> sentReliableCommands))
1545          peer -> nextTimeout = host -> serviceTime + outgoingCommand -> roundTripTimeout;
1546 
1547        enet_list_insert (enet_list_end (& peer -> sentReliableCommands),
1548                          enet_list_remove (& outgoingCommand -> outgoingCommandList));
1549 
1550        outgoingCommand -> sentTime = host -> serviceTime;
1551 
1552        buffer -> data = command;
1553        buffer -> dataLength = commandSize;
1554 
1555        host -> packetSize += buffer -> dataLength;
1556        host -> headerFlags |= ENET_PROTOCOL_HEADER_FLAG_SENT_TIME;
1557 
1558        * command = outgoingCommand -> command;
1559 
1560        if (outgoingCommand -> packet != NULL)
1561        {
1562           ++ buffer;
1563 
1564           buffer -> data = outgoingCommand -> packet -> data + outgoingCommand -> fragmentOffset;
1565           buffer -> dataLength = outgoingCommand -> fragmentLength;
1566 
1567           host -> packetSize += outgoingCommand -> fragmentLength;
1568 
1569           peer -> reliableDataInTransit += outgoingCommand -> fragmentLength;
1570        }
1571 
1572        ++ peer -> packetsSent;
1573 
1574        ++ command;
1575        ++ buffer;
1576     }
1577 
1578     host -> commandCount = command - host -> commands;
1579     host -> bufferCount = buffer - host -> buffers;
1580 
1581     return canPing;
1582 }
1583 
1584 static int
enet_protocol_send_outgoing_commands(ENetHost * host,ENetEvent * event,int checkForTimeouts)1585 enet_protocol_send_outgoing_commands (ENetHost * host, ENetEvent * event, int checkForTimeouts)
1586 {
1587     enet_uint8 headerData [sizeof (ENetProtocolHeader) + sizeof (enet_uint32)];
1588     ENetProtocolHeader * header = (ENetProtocolHeader *) headerData;
1589     ENetPeer * currentPeer;
1590     int sentLength;
1591     size_t shouldCompress = 0;
1592 
1593     host -> continueSending = 1;
1594 
1595     while (host -> continueSending)
1596     for (host -> continueSending = 0,
1597            currentPeer = host -> peers;
1598          currentPeer < & host -> peers [host -> peerCount];
1599          ++ currentPeer)
1600     {
1601         if (currentPeer -> state == ENET_PEER_STATE_DISCONNECTED ||
1602             currentPeer -> state == ENET_PEER_STATE_ZOMBIE)
1603           continue;
1604 
1605         host -> headerFlags = 0;
1606         host -> commandCount = 0;
1607         host -> bufferCount = 1;
1608         host -> packetSize = sizeof (ENetProtocolHeader);
1609 
1610         if (! enet_list_empty (& currentPeer -> acknowledgements))
1611           enet_protocol_send_acknowledgements (host, currentPeer);
1612 
1613         if (checkForTimeouts != 0 &&
1614             ! enet_list_empty (& currentPeer -> sentReliableCommands) &&
1615             ENET_TIME_GREATER_EQUAL (host -> serviceTime, currentPeer -> nextTimeout) &&
1616             enet_protocol_check_timeouts (host, currentPeer, event) == 1)
1617         {
1618             if (event != NULL && event -> type != ENET_EVENT_TYPE_NONE)
1619               return 1;
1620             else
1621               continue;
1622         }
1623 
1624         if ((enet_list_empty (& currentPeer -> outgoingReliableCommands) ||
1625               enet_protocol_send_reliable_outgoing_commands (host, currentPeer)) &&
1626             enet_list_empty (& currentPeer -> sentReliableCommands) &&
1627             ENET_TIME_DIFFERENCE (host -> serviceTime, currentPeer -> lastReceiveTime) >= currentPeer -> pingInterval &&
1628             currentPeer -> mtu - host -> packetSize >= sizeof (ENetProtocolPing))
1629         {
1630             enet_peer_ping (currentPeer);
1631             enet_protocol_send_reliable_outgoing_commands (host, currentPeer);
1632         }
1633 
1634         if (! enet_list_empty (& currentPeer -> outgoingUnreliableCommands))
1635           enet_protocol_send_unreliable_outgoing_commands (host, currentPeer);
1636 
1637         if (host -> commandCount == 0)
1638           continue;
1639 
1640         if (currentPeer -> packetLossEpoch == 0)
1641           currentPeer -> packetLossEpoch = host -> serviceTime;
1642         else
1643         if (ENET_TIME_DIFFERENCE (host -> serviceTime, currentPeer -> packetLossEpoch) >= ENET_PEER_PACKET_LOSS_INTERVAL &&
1644             currentPeer -> packetsSent > 0)
1645         {
1646            enet_uint32 packetLoss = currentPeer -> packetsLost * ENET_PEER_PACKET_LOSS_SCALE / currentPeer -> packetsSent;
1647 
1648 #ifdef ENET_DEBUG
1649            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);
1650 #endif
1651 
1652            currentPeer -> packetLossVariance -= currentPeer -> packetLossVariance / 4;
1653 
1654            if (packetLoss >= currentPeer -> packetLoss)
1655            {
1656               currentPeer -> packetLoss += (packetLoss - currentPeer -> packetLoss) / 8;
1657               currentPeer -> packetLossVariance += (packetLoss - currentPeer -> packetLoss) / 4;
1658            }
1659            else
1660            {
1661               currentPeer -> packetLoss -= (currentPeer -> packetLoss - packetLoss) / 8;
1662               currentPeer -> packetLossVariance += (currentPeer -> packetLoss - packetLoss) / 4;
1663            }
1664 
1665            currentPeer -> packetLossEpoch = host -> serviceTime;
1666            currentPeer -> packetsSent = 0;
1667            currentPeer -> packetsLost = 0;
1668         }
1669 
1670         host -> buffers -> data = headerData;
1671         if (host -> headerFlags & ENET_PROTOCOL_HEADER_FLAG_SENT_TIME)
1672         {
1673             header -> sentTime = ENET_HOST_TO_NET_16 (host -> serviceTime & 0xFFFF);
1674 
1675             host -> buffers -> dataLength = sizeof (ENetProtocolHeader);
1676         }
1677         else
1678           host -> buffers -> dataLength = (size_t) & ((ENetProtocolHeader *) 0) -> sentTime;
1679 
1680         shouldCompress = 0;
1681         if (host -> compressor.context != NULL && host -> compressor.compress != NULL)
1682         {
1683             size_t originalSize = host -> packetSize - sizeof(ENetProtocolHeader),
1684                    compressedSize = host -> compressor.compress (host -> compressor.context,
1685                                         & host -> buffers [1], host -> bufferCount - 1,
1686                                         originalSize,
1687                                         host -> packetData [1],
1688                                         originalSize);
1689             if (compressedSize > 0 && compressedSize < originalSize)
1690             {
1691                 host -> headerFlags |= ENET_PROTOCOL_HEADER_FLAG_COMPRESSED;
1692                 shouldCompress = compressedSize;
1693 #ifdef ENET_DEBUG_COMPRESS
1694                 printf ("peer %u: compressed %u -> %u (%u%%)\n", currentPeer -> incomingPeerID, originalSize, compressedSize, (compressedSize * 100) / originalSize);
1695 #endif
1696             }
1697         }
1698 
1699         if (currentPeer -> outgoingPeerID < ENET_PROTOCOL_MAXIMUM_PEER_ID)
1700           host -> headerFlags |= currentPeer -> outgoingSessionID << ENET_PROTOCOL_HEADER_SESSION_SHIFT;
1701         header -> peerID = ENET_HOST_TO_NET_16 (currentPeer -> outgoingPeerID | host -> headerFlags);
1702         if (host -> checksum != NULL)
1703         {
1704             enet_uint32 * checksum = (enet_uint32 *) & headerData [host -> buffers -> dataLength];
1705             * checksum = currentPeer -> outgoingPeerID < ENET_PROTOCOL_MAXIMUM_PEER_ID ? currentPeer -> connectID : 0;
1706             host -> buffers -> dataLength += sizeof (enet_uint32);
1707             * checksum = host -> checksum (host -> buffers, host -> bufferCount);
1708         }
1709 
1710         if (shouldCompress > 0)
1711         {
1712             host -> buffers [1].data = host -> packetData [1];
1713             host -> buffers [1].dataLength = shouldCompress;
1714             host -> bufferCount = 2;
1715         }
1716 
1717         currentPeer -> lastSendTime = host -> serviceTime;
1718 
1719         sentLength = enet_socket_send (host -> socket, & currentPeer -> address, host -> buffers, host -> bufferCount);
1720 
1721         enet_protocol_remove_sent_unreliable_commands (currentPeer);
1722 
1723         if (sentLength < 0)
1724           return -1;
1725 
1726         host -> totalSentData += sentLength;
1727         host -> totalSentPackets ++;
1728     }
1729 
1730     return 0;
1731 }
1732 
1733 /** Sends any queued packets on the host specified to its designated peers.
1734 
1735     @param host   host to flush
1736     @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().
1737     @ingroup host
1738 */
1739 void
enet_host_flush(ENetHost * host)1740 enet_host_flush (ENetHost * host)
1741 {
1742     host -> serviceTime = enet_time_get ();
1743 
1744     enet_protocol_send_outgoing_commands (host, NULL, 0);
1745 }
1746 
1747 /** Checks for any queued events on the host and dispatches one if available.
1748 
1749     @param host    host to check for events
1750     @param event   an event structure where event details will be placed if available
1751     @retval > 0 if an event was dispatched
1752     @retval 0 if no events are available
1753     @retval < 0 on failure
1754     @ingroup host
1755 */
1756 int
enet_host_check_events(ENetHost * host,ENetEvent * event)1757 enet_host_check_events (ENetHost * host, ENetEvent * event)
1758 {
1759     if (event == NULL) return -1;
1760 
1761     event -> type = ENET_EVENT_TYPE_NONE;
1762     event -> peer = NULL;
1763     event -> packet = NULL;
1764 
1765     return enet_protocol_dispatch_incoming_commands (host, event);
1766 }
1767 
1768 /** Waits for events on the host specified and shuttles packets between
1769     the host and its peers.
1770 
1771     @param host    host to service
1772     @param event   an event structure where event details will be placed if one occurs
1773                    if event == NULL then no events will be delivered
1774     @param timeout number of milliseconds that ENet should wait for events
1775     @retval > 0 if an event occurred within the specified time limit
1776     @retval 0 if no event occurred
1777     @retval < 0 on failure
1778     @remarks enet_host_service should be called fairly regularly for adequate performance
1779     @ingroup host
1780 */
1781 int
enet_host_service(ENetHost * host,ENetEvent * event,enet_uint32 timeout)1782 enet_host_service (ENetHost * host, ENetEvent * event, enet_uint32 timeout)
1783 {
1784     enet_uint32 waitCondition;
1785 
1786     if (event != NULL)
1787     {
1788         event -> type = ENET_EVENT_TYPE_NONE;
1789         event -> peer = NULL;
1790         event -> packet = NULL;
1791 
1792         switch (enet_protocol_dispatch_incoming_commands (host, event))
1793         {
1794         case 1:
1795             return 1;
1796 
1797         case -1:
1798 #ifdef ENET_DEBUG
1799             perror ("Error dispatching incoming packets");
1800 #endif
1801 
1802             return -1;
1803 
1804         default:
1805             break;
1806         }
1807     }
1808 
1809     host -> serviceTime = enet_time_get ();
1810 
1811     timeout += host -> serviceTime;
1812 
1813     do
1814     {
1815        if (ENET_TIME_DIFFERENCE (host -> serviceTime, host -> bandwidthThrottleEpoch) >= ENET_HOST_BANDWIDTH_THROTTLE_INTERVAL)
1816          enet_host_bandwidth_throttle (host);
1817 
1818        switch (enet_protocol_send_outgoing_commands (host, event, 1))
1819        {
1820        case 1:
1821           return 1;
1822 
1823        case -1:
1824 #ifdef ENET_DEBUG
1825           perror ("Error sending outgoing packets");
1826 #endif
1827 
1828           return -1;
1829 
1830        default:
1831           break;
1832        }
1833 
1834        switch (enet_protocol_receive_incoming_commands (host, event))
1835        {
1836        case 1:
1837           return 1;
1838 
1839        case -1:
1840 #ifdef ENET_DEBUG
1841           perror ("Error receiving incoming packets");
1842 #endif
1843 
1844           return -1;
1845 
1846        default:
1847           break;
1848        }
1849 
1850        switch (enet_protocol_send_outgoing_commands (host, event, 1))
1851        {
1852        case 1:
1853           return 1;
1854 
1855        case -1:
1856 #ifdef ENET_DEBUG
1857           perror ("Error sending outgoing packets");
1858 #endif
1859 
1860           return -1;
1861 
1862        default:
1863           break;
1864        }
1865 
1866        if (event != NULL)
1867        {
1868           switch (enet_protocol_dispatch_incoming_commands (host, event))
1869           {
1870           case 1:
1871              return 1;
1872 
1873           case -1:
1874 #ifdef ENET_DEBUG
1875              perror ("Error dispatching incoming packets");
1876 #endif
1877 
1878              return -1;
1879 
1880           default:
1881              break;
1882           }
1883        }
1884 
1885        if (ENET_TIME_GREATER_EQUAL (host -> serviceTime, timeout))
1886          return 0;
1887 
1888        do
1889        {
1890           host -> serviceTime = enet_time_get ();
1891 
1892           if (ENET_TIME_GREATER_EQUAL (host -> serviceTime, timeout))
1893             return 0;
1894 
1895           waitCondition = ENET_SOCKET_WAIT_RECEIVE | ENET_SOCKET_WAIT_INTERRUPT;
1896 
1897           if (enet_socket_wait (host -> socket, & waitCondition, ENET_TIME_DIFFERENCE (timeout, host -> serviceTime)) != 0)
1898             return -1;
1899        }
1900        while (waitCondition & ENET_SOCKET_WAIT_INTERRUPT);
1901 
1902        host -> serviceTime = enet_time_get ();
1903     } while (waitCondition & ENET_SOCKET_WAIT_RECEIVE);
1904 
1905     return 0;
1906 }
1907 
1908