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