Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

patch libenet to support ipv6

This is only done for Linux so far.

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