Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 7390 was 7389, checked in by adrfried, 14 years ago

fix some stuff

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 = { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } };
13const ENetHostAddress ENET_IPV4MAPPED_PREFIX = { { 0,0,0,0,0,0,0,0,0,0, 0xff, 0xff, 0,0,0,0 } };
14const ENetHostAddress ENET_HOST_BROADCAST = { { 0,0,0,0,0,0,0,0,0,0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff } };
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;
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        if (currentPeer -> state == ENET_PEER_STATE_DISCONNECTED ||
1401            currentPeer -> state == ENET_PEER_STATE_ZOMBIE)
1402          continue;
1403
1404        host -> headerFlags = 0;
1405        host -> commandCount = 0;
1406        host -> bufferCount = 1;
1407        host -> packetSize = sizeof (ENetProtocolHeader);
1408
1409        if (! enet_list_empty (& currentPeer -> acknowledgements))
1410          enet_protocol_send_acknowledgements (host, currentPeer);
1411
1412        if (checkForTimeouts != 0 &&
1413            ! enet_list_empty (& currentPeer -> sentReliableCommands) &&
1414            ENET_TIME_GREATER_EQUAL (host -> serviceTime, currentPeer -> nextTimeout) &&
1415            enet_protocol_check_timeouts (host, currentPeer, event) == 1)
1416          return 1;
1417
1418        if (! enet_list_empty (& currentPeer -> outgoingReliableCommands))
1419          enet_protocol_send_reliable_outgoing_commands (host, currentPeer);
1420        else
1421        if (enet_list_empty (& currentPeer -> sentReliableCommands) &&
1422            ENET_TIME_DIFFERENCE (host -> serviceTime, currentPeer -> lastReceiveTime) >= ENET_PEER_PING_INTERVAL &&
1423            currentPeer -> mtu - host -> packetSize >= sizeof (ENetProtocolPing))
1424        { 
1425            enet_peer_ping (currentPeer);
1426            enet_protocol_send_reliable_outgoing_commands (host, currentPeer);
1427        }
1428                     
1429        if (! enet_list_empty (& currentPeer -> outgoingUnreliableCommands))
1430          enet_protocol_send_unreliable_outgoing_commands (host, currentPeer);
1431
1432        if (host -> commandCount == 0)
1433          continue;
1434
1435        if (currentPeer -> packetLossEpoch == 0)
1436          currentPeer -> packetLossEpoch = host -> serviceTime;
1437        else
1438        if (ENET_TIME_DIFFERENCE (host -> serviceTime, currentPeer -> packetLossEpoch) >= ENET_PEER_PACKET_LOSS_INTERVAL &&
1439            currentPeer -> packetsSent > 0)
1440        {
1441           enet_uint32 packetLoss = currentPeer -> packetsLost * ENET_PEER_PACKET_LOSS_SCALE / currentPeer -> packetsSent;
1442
1443#ifdef ENET_DEBUG
1444#ifdef WIN32
1445           printf (
1446#else
1447           fprintf (stderr, 
1448#endif
1449                    "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);
1450#endif
1451         
1452           currentPeer -> packetLossVariance -= currentPeer -> packetLossVariance / 4;
1453
1454           if (packetLoss >= currentPeer -> packetLoss)
1455           {
1456              currentPeer -> packetLoss += (packetLoss - currentPeer -> packetLoss) / 8;
1457              currentPeer -> packetLossVariance += (packetLoss - currentPeer -> packetLoss) / 4;
1458           }
1459           else
1460           {
1461              currentPeer -> packetLoss -= (currentPeer -> packetLoss - packetLoss) / 8;
1462              currentPeer -> packetLossVariance += (currentPeer -> packetLoss - packetLoss) / 4;
1463           }
1464
1465           currentPeer -> packetLossEpoch = host -> serviceTime;
1466           currentPeer -> packetsSent = 0;
1467           currentPeer -> packetsLost = 0;
1468        }
1469
1470        host -> buffers -> data = headerData;
1471        if (host -> headerFlags & ENET_PROTOCOL_HEADER_FLAG_SENT_TIME)
1472        {
1473            header -> sentTime = ENET_HOST_TO_NET_16 (host -> serviceTime & 0xFFFF);
1474
1475            host -> buffers -> dataLength = sizeof (ENetProtocolHeader);
1476        }
1477        else
1478          host -> buffers -> dataLength = (size_t) & ((ENetProtocolHeader *) 0) -> sentTime;
1479
1480        shouldCompress = 0;
1481        if (host -> compressor.context != NULL && host -> compressor.compress != NULL)
1482        {
1483            size_t originalSize = host -> packetSize - sizeof(ENetProtocolHeader),
1484                   compressedSize = host -> compressor.compress (host -> compressor.context,
1485                                        & host -> buffers [1], host -> bufferCount - 1,
1486                                        originalSize,
1487                                        host -> packetData [1],
1488                                        originalSize);
1489            if (compressedSize > 0 && compressedSize < originalSize)
1490            {
1491                host -> headerFlags |= ENET_PROTOCOL_HEADER_FLAG_COMPRESSED;
1492                shouldCompress = compressedSize;
1493#ifdef ENET_DEBUG_COMPRESS
1494#ifdef WIN32
1495           printf (
1496#else
1497           fprintf (stderr,
1498#endif
1499                    "peer %u: compressed %u -> %u (%u%%)\n", currentPeer -> incomingPeerID, originalSize, compressedSize, (compressedSize * 100) / originalSize);
1500#endif
1501            }
1502        }
1503
1504        if (currentPeer -> outgoingPeerID < ENET_PROTOCOL_MAXIMUM_PEER_ID)
1505          host -> headerFlags |= currentPeer -> outgoingSessionID << ENET_PROTOCOL_HEADER_SESSION_SHIFT;
1506        header -> peerID = ENET_HOST_TO_NET_16 (currentPeer -> outgoingPeerID | host -> headerFlags);
1507        if (host -> checksum != NULL)
1508        {
1509            enet_uint32 * checksum = (enet_uint32 *) & headerData [host -> buffers -> dataLength];
1510            * checksum = currentPeer -> outgoingPeerID < ENET_PROTOCOL_MAXIMUM_PEER_ID ? currentPeer -> connectID : 0;
1511            host -> buffers -> dataLength += sizeof (enet_uint32);
1512            * checksum = host -> checksum (host -> buffers, host -> bufferCount);
1513        }
1514
1515        if (shouldCompress > 0)
1516        {
1517            host -> buffers [1].data = host -> packetData [1];
1518            host -> buffers [1].dataLength = shouldCompress;
1519            host -> bufferCount = 2;
1520        }
1521
1522        currentPeer -> lastSendTime = host -> serviceTime;
1523
1524        ENetAddressFamily family = enet_get_address_family (& currentPeer -> address);
1525        ENetSocket socket = family == ENET_IPV4 ? host -> socket4 : host -> socket6;
1526        if (socket == ENET_SOCKET_NULL)
1527          return -1;
1528        sentLength = enet_socket_send (socket,
1529                                           & currentPeer -> address,
1530                                           host -> buffers,
1531                                           host -> bufferCount,
1532                                           family);
1533
1534        enet_protocol_remove_sent_unreliable_commands (currentPeer);
1535
1536        if (sentLength < 0)
1537          return -1;
1538
1539        host -> totalSentData += sentLength;
1540        host -> totalSentPackets ++;
1541    }
1542   
1543    return 0;
1544}
1545
1546/** Sends any queued packets on the host specified to its designated peers.
1547
1548    @param host   host to flush
1549    @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().
1550    @ingroup host
1551*/
1552void
1553enet_host_flush (ENetHost * host)
1554{
1555    host -> serviceTime = enet_time_get ();
1556
1557    enet_protocol_send_outgoing_commands (host, NULL, 0);
1558}
1559
1560/** Checks for any queued events on the host and dispatches one if available.
1561
1562    @param host    host to check for events
1563    @param event   an event structure where event details will be placed if available
1564    @retval > 0 if an event was dispatched
1565    @retval 0 if no events are available
1566    @retval < 0 on failure
1567    @ingroup host
1568*/
1569int
1570enet_host_check_events (ENetHost * host, ENetEvent * event)
1571{
1572    if (event == NULL) return -1;
1573
1574    event -> type = ENET_EVENT_TYPE_NONE;
1575    event -> peer = NULL;
1576    event -> packet = NULL;
1577
1578    return enet_protocol_dispatch_incoming_commands (host, event);
1579}
1580
1581/** Waits for events on the host specified and shuttles packets between
1582    the host and its peers.
1583
1584    @param host    host to service
1585    @param event   an event structure where event details will be placed if one occurs
1586                   if event == NULL then no events will be delivered
1587    @param timeout number of milliseconds that ENet should wait for events
1588    @retval > 0 if an event occurred within the specified time limit
1589    @retval 0 if no event occurred
1590    @retval < 0 on failure
1591    @remarks enet_host_service should be called fairly regularly for adequate performance
1592    @ingroup host
1593*/
1594int
1595enet_host_service (ENetHost * host, ENetEvent * event, enet_uint32 timeout)
1596{
1597    enet_uint32 waitCondition;
1598
1599    if (event != NULL)
1600    {
1601        event -> type = ENET_EVENT_TYPE_NONE;
1602        event -> peer = NULL;
1603        event -> packet = NULL;
1604
1605        switch (enet_protocol_dispatch_incoming_commands (host, event))
1606        {
1607        case 1:
1608            return 1;
1609
1610        case -1:
1611            perror ("Error dispatching incoming packets");
1612
1613            return -1;
1614
1615        default:
1616            break;
1617        }
1618    }
1619
1620    host -> serviceTime = enet_time_get ();
1621   
1622    timeout += host -> serviceTime;
1623
1624    do
1625    {
1626       if (ENET_TIME_DIFFERENCE (host -> serviceTime, host -> bandwidthThrottleEpoch) >= ENET_HOST_BANDWIDTH_THROTTLE_INTERVAL)
1627         enet_host_bandwidth_throttle (host);
1628
1629       switch (enet_protocol_send_outgoing_commands (host, event, 1))
1630       {
1631       case 1:
1632          return 1;
1633
1634       case -1:
1635          perror ("Error sending outgoing packets");
1636
1637          return -1;
1638
1639       default:
1640          break;
1641       }
1642
1643       if (host -> socket4 != ENET_SOCKET_NULL)
1644         switch (enet_protocol_receive_incoming_commands (host, event, ENET_IPV4))
1645       {
1646       case 1:
1647          return 1;
1648
1649       case -1:
1650          perror ("Error receiving incoming packets");
1651
1652          return -1;
1653
1654       default:
1655          break;
1656       }
1657
1658       if (host -> socket6 != ENET_SOCKET_NULL)
1659         switch (enet_protocol_receive_incoming_commands (host, event, ENET_IPV6))
1660       {
1661       case 1:
1662          return 1;
1663
1664       case -1:
1665          perror ("Error receiving incoming packets");
1666
1667          return -1;
1668
1669       default:
1670          break;
1671       }
1672
1673       switch (enet_protocol_send_outgoing_commands (host, event, 1))
1674       {
1675       case 1:
1676          return 1;
1677
1678       case -1:
1679          perror ("Error sending outgoing packets");
1680
1681          return -1;
1682
1683       default:
1684          break;
1685       }
1686
1687       if (event != NULL)
1688       {
1689          switch (enet_protocol_dispatch_incoming_commands (host, event))
1690          {
1691          case 1:
1692             return 1;
1693
1694          case -1:
1695             perror ("Error dispatching incoming packets");
1696
1697             return -1;
1698
1699          default:
1700             break;
1701          }
1702       }
1703
1704       host -> serviceTime = enet_time_get ();
1705
1706       if (ENET_TIME_GREATER_EQUAL (host -> serviceTime, timeout))
1707         return 0;
1708
1709       waitCondition = ENET_SOCKET_WAIT_RECEIVE;
1710
1711       if (enet_socket_wait (host -> socket4, host -> socket6, & waitCondition, ENET_TIME_DIFFERENCE (timeout, host -> serviceTime)) != 0)
1712         return -1;
1713       
1714       host -> serviceTime = enet_time_get ();
1715    } while (waitCondition == ENET_SOCKET_WAIT_RECEIVE);
1716
1717    return 0; 
1718}
1719
Note: See TracBrowser for help on using the repository browser.