Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/cpp11_v2/src/external/enet/protocol.c @ 10775

Last change on this file since 10775 was 8088, checked in by adrfried, 14 years ago

Updated Enet to version 1.3.1

updated patch

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