Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/ipv6/src/external/enet/protocol.c @ 7433

Last change on this file since 7433 was 7397, checked in by adrfried, 14 years ago

add _INIT macros for the address variables

File size: 62.1 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
12const ENetHostAddress ENET_HOST_ANY = ENET_HOST_ANY_INIT;
13const ENetHostAddress ENET_IPV4MAPPED_PREFIX = ENET_IPV4MAPPED_PREFIX_INIT;
14const ENetHostAddress ENET_HOST_BROADCAST = ENET_HOST_BROADCAST_INIT;
15
16static size_t commandSizes [ENET_PROTOCOL_COMMAND_COUNT] =
17{
18    0,
19    sizeof (ENetProtocolAcknowledge),
20    sizeof (ENetProtocolConnect),
21    sizeof (ENetProtocolVerifyConnect),
22    sizeof (ENetProtocolDisconnect),
23    sizeof (ENetProtocolPing),
24    sizeof (ENetProtocolSendReliable),
25    sizeof (ENetProtocolSendUnreliable),
26    sizeof (ENetProtocolSendFragment),
27    sizeof (ENetProtocolSendUnsequenced),
28    sizeof (ENetProtocolBandwidthLimit),
29    sizeof (ENetProtocolThrottleConfigure),
30};
31
32ENetHostAddress
33enet_address_map4 (enet_uint32 address)
34{
35    ENetHostAddress addr = ENET_IPV4MAPPED_PREFIX_INIT;
36    ((enet_uint32 *)addr.addr)[3] = address;
37    return addr;
38}
39
40ENetAddressFamily
41enet_get_address_family (const ENetAddress * address)
42{
43    if (!memcmp(& address->host, & ENET_IPV4MAPPED_PREFIX, ENET_IPV4MAPPED_PREFIX_LEN))
44        return ENET_IPV4;
45    return ENET_IPV6;
46}
47
48size_t
49enet_protocol_command_size (enet_uint8 commandNumber)
50{
51    return commandSizes [commandNumber & ENET_PROTOCOL_COMMAND_MASK];
52}
53
54static int
55enet_protocol_dispatch_incoming_commands (ENetHost * host, ENetEvent * event)
56{
57    while (! enet_list_empty (& host -> dispatchQueue))
58    {
59       ENetPeer * peer = (ENetPeer *) enet_list_remove (enet_list_begin (& host -> dispatchQueue));
60
61       peer -> needsDispatch = 0;
62
63       switch (peer -> state)
64       {
65       case ENET_PEER_STATE_CONNECTION_PENDING:
66       case ENET_PEER_STATE_CONNECTION_SUCCEEDED:
67           peer -> state = ENET_PEER_STATE_CONNECTED;
68
69           event -> type = ENET_EVENT_TYPE_CONNECT;
70           event -> peer = peer;
71           event -> data = peer -> eventData;
72
73           return 1;
74           
75       case ENET_PEER_STATE_ZOMBIE:
76           host -> recalculateBandwidthLimits = 1;
77
78           event -> type = ENET_EVENT_TYPE_DISCONNECT;
79           event -> peer = peer;
80           event -> data = peer -> eventData;
81
82           enet_peer_reset (peer);
83
84           return 1;
85
86       case ENET_PEER_STATE_CONNECTED:
87           if (enet_list_empty (& peer -> dispatchedCommands))
88             continue;
89
90           event -> packet = enet_peer_receive (peer, & event -> channelID);
91           if (event -> packet == NULL)
92             continue;
93             
94           event -> type = ENET_EVENT_TYPE_RECEIVE;
95           event -> peer = peer;
96
97           if (! enet_list_empty (& peer -> dispatchedCommands))
98           {
99              peer -> needsDispatch = 1;
100         
101              enet_list_insert (enet_list_end (& host -> dispatchQueue), & peer -> dispatchList);
102           }
103
104           return 1;
105       }
106    }
107
108    return 0;
109}
110
111static void
112enet_protocol_dispatch_state (ENetHost * host, ENetPeer * peer, ENetPeerState state)
113{
114    peer -> state = state;
115
116    if (! peer -> needsDispatch)
117    {
118       enet_list_insert (enet_list_end (& host -> dispatchQueue), & peer -> dispatchList);
119
120       peer -> needsDispatch = 1;
121    }   
122}
123   
124static void
125enet_protocol_notify_connect (ENetHost * host, ENetPeer * peer, ENetEvent * event)
126{
127    host -> recalculateBandwidthLimits = 1;
128
129    if (event != NULL)
130    {
131        peer -> state = ENET_PEER_STATE_CONNECTED;
132
133        event -> type = ENET_EVENT_TYPE_CONNECT;
134        event -> peer = peer;
135        event -> data = peer -> eventData;
136    }
137    else 
138        enet_protocol_dispatch_state (host, peer, peer -> state == ENET_PEER_STATE_CONNECTING ? ENET_PEER_STATE_CONNECTION_SUCCEEDED : ENET_PEER_STATE_CONNECTION_PENDING);
139}
140
141static void
142enet_protocol_notify_disconnect (ENetHost * host, ENetPeer * peer, ENetEvent * event)
143{
144    if (peer -> state >= ENET_PEER_STATE_CONNECTION_PENDING)
145       host -> recalculateBandwidthLimits = 1;
146
147    if (peer -> state != ENET_PEER_STATE_CONNECTING && peer -> state < ENET_PEER_STATE_CONNECTION_SUCCEEDED)
148        enet_peer_reset (peer);
149    else
150    if (event != NULL)
151    {
152        event -> type = ENET_EVENT_TYPE_DISCONNECT;
153        event -> peer = peer;
154        event -> data = 0;
155
156        enet_peer_reset (peer);
157    }
158    else 
159    {
160        peer -> eventData = 0;
161
162        enet_protocol_dispatch_state (host, peer, ENET_PEER_STATE_ZOMBIE);
163    }
164}
165
166static void
167enet_protocol_remove_sent_unreliable_commands (ENetPeer * peer)
168{
169    ENetOutgoingCommand * outgoingCommand;
170
171    while (! enet_list_empty (& peer -> sentUnreliableCommands))
172    {
173        outgoingCommand = (ENetOutgoingCommand *) enet_list_front (& peer -> sentUnreliableCommands);
174       
175        enet_list_remove (& outgoingCommand -> outgoingCommandList);
176
177        if (outgoingCommand -> packet != NULL)
178        {
179           -- outgoingCommand -> packet -> referenceCount;
180
181           if (outgoingCommand -> packet -> referenceCount == 0)
182             enet_packet_destroy (outgoingCommand -> packet);
183        }
184
185        enet_free (outgoingCommand);
186    }
187}
188
189static ENetProtocolCommand
190enet_protocol_remove_sent_reliable_command (ENetPeer * peer, enet_uint16 reliableSequenceNumber, enet_uint8 channelID)
191{
192    ENetOutgoingCommand * outgoingCommand;
193    ENetListIterator currentCommand;
194    ENetProtocolCommand commandNumber;
195
196    for (currentCommand = enet_list_begin (& peer -> sentReliableCommands);
197         currentCommand != enet_list_end (& peer -> sentReliableCommands);
198         currentCommand = enet_list_next (currentCommand))
199    {
200       outgoingCommand = (ENetOutgoingCommand *) currentCommand;
201       
202       if (outgoingCommand -> reliableSequenceNumber == reliableSequenceNumber &&
203           outgoingCommand -> command.header.channelID == channelID)
204         break;
205    }
206
207    if (currentCommand == enet_list_end (& peer -> sentReliableCommands))
208    {
209       for (currentCommand = enet_list_begin (& peer -> outgoingReliableCommands);
210            currentCommand != enet_list_end (& peer -> outgoingReliableCommands);
211            currentCommand = enet_list_next (currentCommand))
212       {
213          outgoingCommand = (ENetOutgoingCommand *) currentCommand;
214
215          if (outgoingCommand -> sendAttempts < 1) return ENET_PROTOCOL_COMMAND_NONE;
216
217          if (outgoingCommand -> reliableSequenceNumber == reliableSequenceNumber &&
218              outgoingCommand -> command.header.channelID == channelID)
219            break;
220       }
221
222       if (currentCommand == enet_list_end (& peer -> outgoingReliableCommands))
223         return ENET_PROTOCOL_COMMAND_NONE;
224    }
225
226    if (channelID < peer -> channelCount)
227    {
228       ENetChannel * channel = & peer -> channels [channelID];
229       enet_uint16 reliableWindow = reliableSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE;
230       if (channel -> reliableWindows [reliableWindow] > 0)
231       {
232          -- channel -> reliableWindows [reliableWindow];
233          if (! channel -> reliableWindows [reliableWindow])
234            channel -> usedReliableWindows &= ~ (1 << reliableWindow);
235       }
236    }
237
238    commandNumber = (ENetProtocolCommand) (outgoingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_MASK);
239   
240    enet_list_remove (& outgoingCommand -> outgoingCommandList);
241
242    if (outgoingCommand -> packet != NULL)
243    {
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 void
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
1290    currentCommand = enet_list_begin (& peer -> outgoingReliableCommands);
1291   
1292    while (currentCommand != enet_list_end (& peer -> outgoingReliableCommands))
1293    {
1294       outgoingCommand = (ENetOutgoingCommand *) currentCommand;
1295
1296       channel = outgoingCommand -> command.header.channelID < peer -> channelCount ? & peer -> channels [outgoingCommand -> command.header.channelID] : NULL;
1297       reliableWindow = outgoingCommand -> reliableSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE;
1298       if (channel != NULL && 
1299           outgoingCommand -> sendAttempts < 1 && 
1300           ! (outgoingCommand -> reliableSequenceNumber % ENET_PEER_RELIABLE_WINDOW_SIZE) &&
1301           (channel -> reliableWindows [(reliableWindow + ENET_PEER_RELIABLE_WINDOWS - 1) % ENET_PEER_RELIABLE_WINDOWS] >= ENET_PEER_RELIABLE_WINDOW_SIZE ||
1302             channel -> usedReliableWindows & ((((1 << ENET_PEER_FREE_RELIABLE_WINDOWS) - 1) << reliableWindow) | 
1303               (((1 << ENET_PEER_FREE_RELIABLE_WINDOWS) - 1) >> (ENET_PEER_RELIABLE_WINDOW_SIZE - reliableWindow)))))
1304         break;
1305 
1306       commandSize = commandSizes [outgoingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_MASK];
1307       if (command >= & host -> commands [sizeof (host -> commands) / sizeof (ENetProtocol)] ||
1308           buffer + 1 >= & host -> buffers [sizeof (host -> buffers) / sizeof (ENetBuffer)] ||
1309           peer -> mtu - host -> packetSize < commandSize)
1310       {
1311          host -> continueSending = 1;
1312         
1313          break;
1314       }
1315
1316       if (outgoingCommand -> packet != NULL)
1317       {
1318          if (peer -> reliableDataInTransit + outgoingCommand -> fragmentLength > peer -> windowSize)
1319            break;
1320
1321          if ((enet_uint16) (peer -> mtu - host -> packetSize) < (enet_uint16) (commandSize + outgoingCommand -> fragmentLength))
1322          {
1323             host -> continueSending = 1;
1324
1325             break;
1326          }
1327       }
1328     
1329       currentCommand = enet_list_next (currentCommand);
1330
1331       if (channel != NULL && outgoingCommand -> sendAttempts < 1)
1332       {
1333          channel -> usedReliableWindows |= 1 << reliableWindow;
1334          ++ channel -> reliableWindows [reliableWindow];
1335       }
1336
1337       ++ outgoingCommand -> sendAttempts;
1338 
1339       if (outgoingCommand -> roundTripTimeout == 0)
1340       {
1341          outgoingCommand -> roundTripTimeout = peer -> roundTripTime + 4 * peer -> roundTripTimeVariance;
1342          outgoingCommand -> roundTripTimeoutLimit = ENET_PEER_TIMEOUT_LIMIT * outgoingCommand -> roundTripTimeout;
1343       }
1344
1345       if (enet_list_empty (& peer -> sentReliableCommands))
1346         peer -> nextTimeout = host -> serviceTime + outgoingCommand -> roundTripTimeout;
1347
1348       enet_list_insert (enet_list_end (& peer -> sentReliableCommands),
1349                         enet_list_remove (& outgoingCommand -> outgoingCommandList));
1350
1351       outgoingCommand -> sentTime = host -> serviceTime;
1352
1353       buffer -> data = command;
1354       buffer -> dataLength = commandSize;
1355
1356       host -> packetSize += buffer -> dataLength;
1357       host -> headerFlags |= ENET_PROTOCOL_HEADER_FLAG_SENT_TIME;
1358
1359       * command = outgoingCommand -> command;
1360
1361       if (outgoingCommand -> packet != NULL)
1362       {
1363          ++ buffer;
1364         
1365          buffer -> data = outgoingCommand -> packet -> data + outgoingCommand -> fragmentOffset;
1366          buffer -> dataLength = outgoingCommand -> fragmentLength;
1367
1368          host -> packetSize += outgoingCommand -> fragmentLength;
1369
1370          peer -> reliableDataInTransit += outgoingCommand -> fragmentLength;
1371       }
1372
1373       ++ peer -> packetsSent;
1374       
1375       ++ command;
1376       ++ buffer;
1377    }
1378
1379    host -> commandCount = command - host -> commands;
1380    host -> bufferCount = buffer - host -> buffers;
1381}
1382
1383static int
1384enet_protocol_send_outgoing_commands (ENetHost * host, ENetEvent * event, int checkForTimeouts)
1385{
1386    enet_uint8 headerData [sizeof (ENetProtocolHeader) + sizeof (enet_uint32)];
1387    ENetProtocolHeader * header = (ENetProtocolHeader *) headerData;
1388    ENetPeer * currentPeer;
1389    int sentLength;
1390    size_t shouldCompress = 0;
1391 
1392    host -> continueSending = 1;
1393
1394    while (host -> continueSending)
1395    for (host -> continueSending = 0,
1396           currentPeer = host -> peers;
1397         currentPeer < & host -> peers [host -> peerCount];
1398         ++ currentPeer)
1399    {
1400        ENetAddressFamily family;
1401        ENetSocket socket;
1402
1403        if (currentPeer -> state == ENET_PEER_STATE_DISCONNECTED ||
1404            currentPeer -> state == ENET_PEER_STATE_ZOMBIE)
1405          continue;
1406
1407        host -> headerFlags = 0;
1408        host -> commandCount = 0;
1409        host -> bufferCount = 1;
1410        host -> packetSize = sizeof (ENetProtocolHeader);
1411
1412        if (! enet_list_empty (& currentPeer -> acknowledgements))
1413          enet_protocol_send_acknowledgements (host, currentPeer);
1414
1415        if (checkForTimeouts != 0 &&
1416            ! enet_list_empty (& currentPeer -> sentReliableCommands) &&
1417            ENET_TIME_GREATER_EQUAL (host -> serviceTime, currentPeer -> nextTimeout) &&
1418            enet_protocol_check_timeouts (host, currentPeer, event) == 1)
1419          return 1;
1420
1421        if (! enet_list_empty (& currentPeer -> outgoingReliableCommands))
1422          enet_protocol_send_reliable_outgoing_commands (host, currentPeer);
1423        else
1424        if (enet_list_empty (& currentPeer -> sentReliableCommands) &&
1425            ENET_TIME_DIFFERENCE (host -> serviceTime, currentPeer -> lastReceiveTime) >= ENET_PEER_PING_INTERVAL &&
1426            currentPeer -> mtu - host -> packetSize >= sizeof (ENetProtocolPing))
1427        { 
1428            enet_peer_ping (currentPeer);
1429            enet_protocol_send_reliable_outgoing_commands (host, currentPeer);
1430        }
1431                     
1432        if (! enet_list_empty (& currentPeer -> outgoingUnreliableCommands))
1433          enet_protocol_send_unreliable_outgoing_commands (host, currentPeer);
1434
1435        if (host -> commandCount == 0)
1436          continue;
1437
1438        if (currentPeer -> packetLossEpoch == 0)
1439          currentPeer -> packetLossEpoch = host -> serviceTime;
1440        else
1441        if (ENET_TIME_DIFFERENCE (host -> serviceTime, currentPeer -> packetLossEpoch) >= ENET_PEER_PACKET_LOSS_INTERVAL &&
1442            currentPeer -> packetsSent > 0)
1443        {
1444           enet_uint32 packetLoss = currentPeer -> packetsLost * ENET_PEER_PACKET_LOSS_SCALE / currentPeer -> packetsSent;
1445
1446#ifdef ENET_DEBUG
1447#ifdef WIN32
1448           printf (
1449#else
1450           fprintf (stderr, 
1451#endif
1452                    "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);
1453#endif
1454         
1455           currentPeer -> packetLossVariance -= currentPeer -> packetLossVariance / 4;
1456
1457           if (packetLoss >= currentPeer -> packetLoss)
1458           {
1459              currentPeer -> packetLoss += (packetLoss - currentPeer -> packetLoss) / 8;
1460              currentPeer -> packetLossVariance += (packetLoss - currentPeer -> packetLoss) / 4;
1461           }
1462           else
1463           {
1464              currentPeer -> packetLoss -= (currentPeer -> packetLoss - packetLoss) / 8;
1465              currentPeer -> packetLossVariance += (currentPeer -> packetLoss - packetLoss) / 4;
1466           }
1467
1468           currentPeer -> packetLossEpoch = host -> serviceTime;
1469           currentPeer -> packetsSent = 0;
1470           currentPeer -> packetsLost = 0;
1471        }
1472
1473        host -> buffers -> data = headerData;
1474        if (host -> headerFlags & ENET_PROTOCOL_HEADER_FLAG_SENT_TIME)
1475        {
1476            header -> sentTime = ENET_HOST_TO_NET_16 (host -> serviceTime & 0xFFFF);
1477
1478            host -> buffers -> dataLength = sizeof (ENetProtocolHeader);
1479        }
1480        else
1481          host -> buffers -> dataLength = (size_t) & ((ENetProtocolHeader *) 0) -> sentTime;
1482
1483        shouldCompress = 0;
1484        if (host -> compressor.context != NULL && host -> compressor.compress != NULL)
1485        {
1486            size_t originalSize = host -> packetSize - sizeof(ENetProtocolHeader),
1487                   compressedSize = host -> compressor.compress (host -> compressor.context,
1488                                        & host -> buffers [1], host -> bufferCount - 1,
1489                                        originalSize,
1490                                        host -> packetData [1],
1491                                        originalSize);
1492            if (compressedSize > 0 && compressedSize < originalSize)
1493            {
1494                host -> headerFlags |= ENET_PROTOCOL_HEADER_FLAG_COMPRESSED;
1495                shouldCompress = compressedSize;
1496#ifdef ENET_DEBUG_COMPRESS
1497#ifdef WIN32
1498           printf (
1499#else
1500           fprintf (stderr,
1501#endif
1502                    "peer %u: compressed %u -> %u (%u%%)\n", currentPeer -> incomingPeerID, originalSize, compressedSize, (compressedSize * 100) / originalSize);
1503#endif
1504            }
1505        }
1506
1507        if (currentPeer -> outgoingPeerID < ENET_PROTOCOL_MAXIMUM_PEER_ID)
1508          host -> headerFlags |= currentPeer -> outgoingSessionID << ENET_PROTOCOL_HEADER_SESSION_SHIFT;
1509        header -> peerID = ENET_HOST_TO_NET_16 (currentPeer -> outgoingPeerID | host -> headerFlags);
1510        if (host -> checksum != NULL)
1511        {
1512            enet_uint32 * checksum = (enet_uint32 *) & headerData [host -> buffers -> dataLength];
1513            * checksum = currentPeer -> outgoingPeerID < ENET_PROTOCOL_MAXIMUM_PEER_ID ? currentPeer -> connectID : 0;
1514            host -> buffers -> dataLength += sizeof (enet_uint32);
1515            * checksum = host -> checksum (host -> buffers, host -> bufferCount);
1516        }
1517
1518        if (shouldCompress > 0)
1519        {
1520            host -> buffers [1].data = host -> packetData [1];
1521            host -> buffers [1].dataLength = shouldCompress;
1522            host -> bufferCount = 2;
1523        }
1524
1525        currentPeer -> lastSendTime = host -> serviceTime;
1526
1527        family = enet_get_address_family (& currentPeer -> address);
1528        socket = family == ENET_IPV4 ? host -> socket4 : host -> socket6;
1529        if (socket == ENET_SOCKET_NULL)
1530          return -1;
1531        sentLength = enet_socket_send (socket,
1532                                           & currentPeer -> address,
1533                                           host -> buffers,
1534                                           host -> bufferCount,
1535                                           family);
1536
1537        enet_protocol_remove_sent_unreliable_commands (currentPeer);
1538
1539        if (sentLength < 0)
1540          return -1;
1541
1542        host -> totalSentData += sentLength;
1543        host -> totalSentPackets ++;
1544    }
1545   
1546    return 0;
1547}
1548
1549/** Sends any queued packets on the host specified to its designated peers.
1550
1551    @param host   host to flush
1552    @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().
1553    @ingroup host
1554*/
1555void
1556enet_host_flush (ENetHost * host)
1557{
1558    host -> serviceTime = enet_time_get ();
1559
1560    enet_protocol_send_outgoing_commands (host, NULL, 0);
1561}
1562
1563/** Checks for any queued events on the host and dispatches one if available.
1564
1565    @param host    host to check for events
1566    @param event   an event structure where event details will be placed if available
1567    @retval > 0 if an event was dispatched
1568    @retval 0 if no events are available
1569    @retval < 0 on failure
1570    @ingroup host
1571*/
1572int
1573enet_host_check_events (ENetHost * host, ENetEvent * event)
1574{
1575    if (event == NULL) return -1;
1576
1577    event -> type = ENET_EVENT_TYPE_NONE;
1578    event -> peer = NULL;
1579    event -> packet = NULL;
1580
1581    return enet_protocol_dispatch_incoming_commands (host, event);
1582}
1583
1584/** Waits for events on the host specified and shuttles packets between
1585    the host and its peers.
1586
1587    @param host    host to service
1588    @param event   an event structure where event details will be placed if one occurs
1589                   if event == NULL then no events will be delivered
1590    @param timeout number of milliseconds that ENet should wait for events
1591    @retval > 0 if an event occurred within the specified time limit
1592    @retval 0 if no event occurred
1593    @retval < 0 on failure
1594    @remarks enet_host_service should be called fairly regularly for adequate performance
1595    @ingroup host
1596*/
1597int
1598enet_host_service (ENetHost * host, ENetEvent * event, enet_uint32 timeout)
1599{
1600    enet_uint32 waitCondition;
1601
1602    if (event != NULL)
1603    {
1604        event -> type = ENET_EVENT_TYPE_NONE;
1605        event -> peer = NULL;
1606        event -> packet = NULL;
1607
1608        switch (enet_protocol_dispatch_incoming_commands (host, event))
1609        {
1610        case 1:
1611            return 1;
1612
1613        case -1:
1614            perror ("Error dispatching incoming packets");
1615
1616            return -1;
1617
1618        default:
1619            break;
1620        }
1621    }
1622
1623    host -> serviceTime = enet_time_get ();
1624   
1625    timeout += host -> serviceTime;
1626
1627    do
1628    {
1629       if (ENET_TIME_DIFFERENCE (host -> serviceTime, host -> bandwidthThrottleEpoch) >= ENET_HOST_BANDWIDTH_THROTTLE_INTERVAL)
1630         enet_host_bandwidth_throttle (host);
1631
1632       switch (enet_protocol_send_outgoing_commands (host, event, 1))
1633       {
1634       case 1:
1635          return 1;
1636
1637       case -1:
1638          perror ("Error sending outgoing packets");
1639
1640          return -1;
1641
1642       default:
1643          break;
1644       }
1645
1646       if (host -> socket4 != ENET_SOCKET_NULL)
1647         switch (enet_protocol_receive_incoming_commands (host, event, ENET_IPV4))
1648       {
1649       case 1:
1650          return 1;
1651
1652       case -1:
1653          perror ("Error receiving incoming packets");
1654
1655          return -1;
1656
1657       default:
1658          break;
1659       }
1660
1661       if (host -> socket6 != ENET_SOCKET_NULL)
1662         switch (enet_protocol_receive_incoming_commands (host, event, ENET_IPV6))
1663       {
1664       case 1:
1665          return 1;
1666
1667       case -1:
1668          perror ("Error receiving incoming packets");
1669
1670          return -1;
1671
1672       default:
1673          break;
1674       }
1675
1676       switch (enet_protocol_send_outgoing_commands (host, event, 1))
1677       {
1678       case 1:
1679          return 1;
1680
1681       case -1:
1682          perror ("Error sending outgoing packets");
1683
1684          return -1;
1685
1686       default:
1687          break;
1688       }
1689
1690       if (event != NULL)
1691       {
1692          switch (enet_protocol_dispatch_incoming_commands (host, event))
1693          {
1694          case 1:
1695             return 1;
1696
1697          case -1:
1698             perror ("Error dispatching incoming packets");
1699
1700             return -1;
1701
1702          default:
1703             break;
1704          }
1705       }
1706
1707       host -> serviceTime = enet_time_get ();
1708
1709       if (ENET_TIME_GREATER_EQUAL (host -> serviceTime, timeout))
1710         return 0;
1711
1712       waitCondition = ENET_SOCKET_WAIT_RECEIVE;
1713
1714       if (enet_socket_wait (host -> socket4, host -> socket6, & waitCondition, ENET_TIME_DIFFERENCE (timeout, host -> serviceTime)) != 0)
1715         return -1;
1716       
1717       host -> serviceTime = enet_time_get ();
1718    } while (waitCondition == ENET_SOCKET_WAIT_RECEIVE);
1719
1720    return 0; 
1721}
1722
Note: See TracBrowser for help on using the repository browser.