Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/usability/src/external/enet/protocol.c @ 9573

Last change on this file since 9573 was 7459, checked in by adrfried, 14 years ago

Merged ipv6 branch

Orxonox now includes a modified version of ENet 1.3.0

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