Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/enet-1.1/protocol.c @ 14

Last change on this file since 14 was 13, checked in by landauf, 17 years ago

added enet

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