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