source: osgVisual/trunk/src/cluster/enet/protocol.c @ 278

Last change on this file since 278 was 65, checked in by Torben Dannhauer, 14 years ago

new cluster implementation added: ENet
ENet is a reliable UDP implementation with quite simple usage and high performance for transmission with small or medium size packet.

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