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