Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/external/enet/peer.c @ 11679

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

Updated Enet to version 1.3.1

updated patch

  • Property svn:eol-style set to native
File size: 29.9 KB
Line 
1/**
2 @file  peer.c
3 @brief ENet peer management functions
4*/
5#include <string.h>
6#define ENET_BUILDING_LIB 1
7#include "enet/enet.h"
8
9/** @defgroup peer ENet peer functions
10    @{
11*/
12
13/** Configures throttle parameter for a peer.
14
15    Unreliable packets are dropped by ENet in response to the varying conditions
16    of the Internet connection to the peer.  The throttle represents a probability
17    that an unreliable packet should not be dropped and thus sent by ENet to the peer.
18    The lowest mean round trip time from the sending of a reliable packet to the
19    receipt of its acknowledgement is measured over an amount of time specified by
20    the interval parameter in milliseconds.  If a measured round trip time happens to
21    be significantly less than the mean round trip time measured over the interval,
22    then the throttle probability is increased to allow more traffic by an amount
23    specified in the acceleration parameter, which is a ratio to the ENET_PEER_PACKET_THROTTLE_SCALE
24    constant.  If a measured round trip time happens to be significantly greater than
25    the mean round trip time measured over the interval, then the throttle probability
26    is decreased to limit traffic by an amount specified in the deceleration parameter, which
27    is a ratio to the ENET_PEER_PACKET_THROTTLE_SCALE constant.  When the throttle has
28    a value of ENET_PEER_PACKET_THROTTLE_SCALE, on unreliable packets are dropped by
29    ENet, and so 100% of all unreliable packets will be sent.  When the throttle has a
30    value of 0, all unreliable packets are dropped by ENet, and so 0% of all unreliable
31    packets will be sent.  Intermediate values for the throttle represent intermediate
32    probabilities between 0% and 100% of unreliable packets being sent.  The bandwidth
33    limits of the local and foreign hosts are taken into account to determine a
34    sensible limit for the throttle probability above which it should not raise even in
35    the best of conditions.
36
37    @param peer peer to configure
38    @param interval interval, in milliseconds, over which to measure lowest mean RTT; the default value is ENET_PEER_PACKET_THROTTLE_INTERVAL.
39    @param acceleration rate at which to increase the throttle probability as mean RTT declines
40    @param deceleration rate at which to decrease the throttle probability as mean RTT increases
41*/
42void
43enet_peer_throttle_configure (ENetPeer * peer, enet_uint32 interval, enet_uint32 acceleration, enet_uint32 deceleration)
44{
45    ENetProtocol command;
46
47    peer -> packetThrottleInterval = interval;
48    peer -> packetThrottleAcceleration = acceleration;
49    peer -> packetThrottleDeceleration = deceleration;
50
51    command.header.command = ENET_PROTOCOL_COMMAND_THROTTLE_CONFIGURE | ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE;
52    command.header.channelID = 0xFF;
53
54    command.throttleConfigure.packetThrottleInterval = ENET_HOST_TO_NET_32 (interval);
55    command.throttleConfigure.packetThrottleAcceleration = ENET_HOST_TO_NET_32 (acceleration);
56    command.throttleConfigure.packetThrottleDeceleration = ENET_HOST_TO_NET_32 (deceleration);
57
58    enet_peer_queue_outgoing_command (peer, & command, NULL, 0, 0);
59}
60
61int
62enet_peer_throttle (ENetPeer * peer, enet_uint32 rtt)
63{
64    if (peer -> lastRoundTripTime <= peer -> lastRoundTripTimeVariance)
65    {
66        peer -> packetThrottle = peer -> packetThrottleLimit;
67    }
68    else
69    if (rtt < peer -> lastRoundTripTime)
70    {
71        peer -> packetThrottle += peer -> packetThrottleAcceleration;
72
73        if (peer -> packetThrottle > peer -> packetThrottleLimit)
74          peer -> packetThrottle = peer -> packetThrottleLimit;
75
76        return 1;
77    }
78    else
79    if (rtt > peer -> lastRoundTripTime + 2 * peer -> lastRoundTripTimeVariance)
80    {
81        if (peer -> packetThrottle > peer -> packetThrottleDeceleration)
82          peer -> packetThrottle -= peer -> packetThrottleDeceleration;
83        else
84          peer -> packetThrottle = 0;
85
86        return -1;
87    }
88
89    return 0;
90}
91
92/** Queues a packet to be sent.
93    @param peer destination for the packet
94    @param channelID channel on which to send
95    @param packet packet to send
96    @retval 0 on success
97    @retval < 0 on failure
98*/
99int
100enet_peer_send (ENetPeer * peer, enet_uint8 channelID, ENetPacket * packet)
101{
102   ENetChannel * channel = & peer -> channels [channelID];
103   ENetProtocol command;
104   size_t fragmentLength;
105
106   if (peer -> state != ENET_PEER_STATE_CONNECTED ||
107       channelID >= peer -> channelCount)
108     return -1;
109
110   fragmentLength = peer -> mtu - sizeof (ENetProtocolHeader) - sizeof (ENetProtocolSendFragment);
111   if (peer -> host -> checksum != NULL)
112     fragmentLength -= sizeof(enet_uint32);
113
114   if (packet -> dataLength > fragmentLength)
115   {
116      enet_uint16 startSequenceNumber = ENET_HOST_TO_NET_16 (channel -> outgoingReliableSequenceNumber + 1);
117      enet_uint32 fragmentCount = ENET_HOST_TO_NET_32 ((packet -> dataLength + fragmentLength - 1) / fragmentLength),
118             fragmentNumber,
119             fragmentOffset;
120      ENetList fragments;
121      ENetOutgoingCommand * fragment;
122
123      enet_list_clear (& fragments);
124
125      for (fragmentNumber = 0,
126             fragmentOffset = 0;
127           fragmentOffset < packet -> dataLength;
128           ++ fragmentNumber,
129             fragmentOffset += fragmentLength)
130      {
131         if (packet -> dataLength - fragmentOffset < fragmentLength)
132           fragmentLength = packet -> dataLength - fragmentOffset;
133
134         fragment = (ENetOutgoingCommand *) enet_malloc (sizeof (ENetOutgoingCommand));
135         if (fragment == NULL)
136         {
137            while (! enet_list_empty (& fragments))
138            {
139               fragment = (ENetOutgoingCommand *) enet_list_remove (enet_list_begin (& fragments));
140               
141               enet_free (fragment);
142            }
143           
144            return -1;
145         }
146         
147         fragment -> fragmentOffset = fragmentOffset;
148         fragment -> fragmentLength = fragmentLength;
149         fragment -> packet = packet;
150         fragment -> command.header.command = ENET_PROTOCOL_COMMAND_SEND_FRAGMENT | ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE;
151         fragment -> command.header.channelID = channelID;
152         fragment -> command.sendFragment.startSequenceNumber = startSequenceNumber;
153         fragment -> command.sendFragment.dataLength = ENET_HOST_TO_NET_16 (fragmentLength);
154         fragment -> command.sendFragment.fragmentCount = fragmentCount;
155         fragment -> command.sendFragment.fragmentNumber = ENET_HOST_TO_NET_32 (fragmentNumber);
156         fragment -> command.sendFragment.totalLength = ENET_HOST_TO_NET_32 (packet -> dataLength);
157         fragment -> command.sendFragment.fragmentOffset = ENET_NET_TO_HOST_32 (fragmentOffset);
158       
159         enet_list_insert (enet_list_end (& fragments), fragment);
160      }
161
162      packet -> referenceCount += fragmentNumber;
163
164      while (! enet_list_empty (& fragments))
165      {
166         fragment = (ENetOutgoingCommand *) enet_list_remove (enet_list_begin (& fragments));
167 
168         enet_peer_setup_outgoing_command (peer, fragment);
169      }
170
171      return 0;
172   }
173
174   command.header.channelID = channelID;
175
176   if (packet -> flags & ENET_PACKET_FLAG_RELIABLE)
177   {
178      command.header.command = ENET_PROTOCOL_COMMAND_SEND_RELIABLE | ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE;
179      command.sendReliable.dataLength = ENET_HOST_TO_NET_16 (packet -> dataLength);
180   }
181   else
182   if (packet -> flags & ENET_PACKET_FLAG_UNSEQUENCED)
183   {
184      command.header.command = ENET_PROTOCOL_COMMAND_SEND_UNSEQUENCED | ENET_PROTOCOL_COMMAND_FLAG_UNSEQUENCED;
185      command.sendUnsequenced.unsequencedGroup = ENET_HOST_TO_NET_16 (peer -> outgoingUnsequencedGroup + 1);
186      command.sendUnsequenced.dataLength = ENET_HOST_TO_NET_16 (packet -> dataLength);
187   }
188   else 
189   if (channel -> outgoingUnreliableSequenceNumber >= 0xFFFF)
190   {
191      command.header.command = ENET_PROTOCOL_COMMAND_SEND_RELIABLE | ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE;
192      command.sendReliable.dataLength = ENET_HOST_TO_NET_16 (packet -> dataLength);
193   }
194   else
195   {
196      command.header.command = ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE;
197      command.sendUnreliable.unreliableSequenceNumber = ENET_HOST_TO_NET_16 (channel -> outgoingUnreliableSequenceNumber + 1);
198      command.sendUnreliable.dataLength = ENET_HOST_TO_NET_16 (packet -> dataLength);
199   }
200
201   if (enet_peer_queue_outgoing_command (peer, & command, packet, 0, packet -> dataLength) == NULL)
202     return -1;
203
204   return 0;
205}
206
207/** Attempts to dequeue any incoming queued packet.
208    @param peer peer to dequeue packets from
209    @param channelID holds the channel ID of the channel the packet was received on success
210    @returns a pointer to the packet, or NULL if there are no available incoming queued packets
211*/
212ENetPacket *
213enet_peer_receive (ENetPeer * peer, enet_uint8 * channelID)
214{
215   ENetIncomingCommand * incomingCommand;
216   ENetPacket * packet;
217   
218   if (enet_list_empty (& peer -> dispatchedCommands))
219     return NULL;
220
221   incomingCommand = (ENetIncomingCommand *) enet_list_remove (enet_list_begin (& peer -> dispatchedCommands));
222
223   if (channelID != NULL)
224     * channelID = incomingCommand -> command.header.channelID;
225
226   packet = incomingCommand -> packet;
227
228   -- packet -> referenceCount;
229
230   if (incomingCommand -> fragments != NULL)
231     enet_free (incomingCommand -> fragments);
232
233   enet_free (incomingCommand);
234
235   return packet;
236}
237
238static void
239enet_peer_reset_outgoing_commands (ENetList * queue)
240{
241    ENetOutgoingCommand * outgoingCommand;
242
243    while (! enet_list_empty (queue))
244    {
245       outgoingCommand = (ENetOutgoingCommand *) enet_list_remove (enet_list_begin (queue));
246
247       if (outgoingCommand -> packet != NULL)
248       {
249          -- outgoingCommand -> packet -> referenceCount;
250
251          if (outgoingCommand -> packet -> referenceCount == 0)
252            enet_packet_destroy (outgoingCommand -> packet);
253       }
254
255       enet_free (outgoingCommand);
256    }
257}
258
259static void
260enet_peer_reset_incoming_commands (ENetList * queue)
261{
262    ENetIncomingCommand * incomingCommand;
263
264    while (! enet_list_empty (queue))
265    {
266       incomingCommand = (ENetIncomingCommand *) enet_list_remove (enet_list_begin (queue));
267
268       if (incomingCommand -> packet != NULL)
269       {
270          -- incomingCommand -> packet -> referenceCount;
271
272          if (incomingCommand -> packet -> referenceCount == 0)
273            enet_packet_destroy (incomingCommand -> packet);
274       }
275
276       if (incomingCommand -> fragments != NULL)
277         enet_free (incomingCommand -> fragments);
278
279       enet_free (incomingCommand);
280    }
281}
282
283void
284enet_peer_reset_queues (ENetPeer * peer)
285{
286    ENetChannel * channel;
287
288    if (peer -> needsDispatch)
289    {
290       enet_list_remove (& peer -> dispatchList);
291
292       peer -> needsDispatch = 0;
293    }
294
295    while (! enet_list_empty (& peer -> acknowledgements))
296      enet_free (enet_list_remove (enet_list_begin (& peer -> acknowledgements)));
297
298    enet_peer_reset_outgoing_commands (& peer -> sentReliableCommands);
299    enet_peer_reset_outgoing_commands (& peer -> sentUnreliableCommands);
300    enet_peer_reset_outgoing_commands (& peer -> outgoingReliableCommands);
301    enet_peer_reset_outgoing_commands (& peer -> outgoingUnreliableCommands);
302    enet_peer_reset_incoming_commands (& peer -> dispatchedCommands);
303
304    if (peer -> channels != NULL && peer -> channelCount > 0)
305    {
306        for (channel = peer -> channels;
307             channel < & peer -> channels [peer -> channelCount];
308             ++ channel)
309        {
310            enet_peer_reset_incoming_commands (& channel -> incomingReliableCommands);
311            enet_peer_reset_incoming_commands (& channel -> incomingUnreliableCommands);
312        }
313
314        enet_free (peer -> channels);
315    }
316
317    peer -> channels = NULL;
318    peer -> channelCount = 0;
319}
320
321/** Forcefully disconnects a peer.
322    @param peer peer to forcefully disconnect
323    @remarks The foreign host represented by the peer is not notified of the disconnection and will timeout
324    on its connection to the local host.
325*/
326void
327enet_peer_reset (ENetPeer * peer)
328{
329    peer -> outgoingPeerID = ENET_PROTOCOL_MAXIMUM_PEER_ID;
330    peer -> connectID = 0;
331
332    peer -> state = ENET_PEER_STATE_DISCONNECTED;
333
334    peer -> incomingBandwidth = 0;
335    peer -> outgoingBandwidth = 0;
336    peer -> incomingBandwidthThrottleEpoch = 0;
337    peer -> outgoingBandwidthThrottleEpoch = 0;
338    peer -> incomingDataTotal = 0;
339    peer -> outgoingDataTotal = 0;
340    peer -> lastSendTime = 0;
341    peer -> lastReceiveTime = 0;
342    peer -> nextTimeout = 0;
343    peer -> earliestTimeout = 0;
344    peer -> packetLossEpoch = 0;
345    peer -> packetsSent = 0;
346    peer -> packetsLost = 0;
347    peer -> packetLoss = 0;
348    peer -> packetLossVariance = 0;
349    peer -> packetThrottle = ENET_PEER_DEFAULT_PACKET_THROTTLE;
350    peer -> packetThrottleLimit = ENET_PEER_PACKET_THROTTLE_SCALE;
351    peer -> packetThrottleCounter = 0;
352    peer -> packetThrottleEpoch = 0;
353    peer -> packetThrottleAcceleration = ENET_PEER_PACKET_THROTTLE_ACCELERATION;
354    peer -> packetThrottleDeceleration = ENET_PEER_PACKET_THROTTLE_DECELERATION;
355    peer -> packetThrottleInterval = ENET_PEER_PACKET_THROTTLE_INTERVAL;
356    peer -> lastRoundTripTime = ENET_PEER_DEFAULT_ROUND_TRIP_TIME;
357    peer -> lowestRoundTripTime = ENET_PEER_DEFAULT_ROUND_TRIP_TIME;
358    peer -> lastRoundTripTimeVariance = 0;
359    peer -> highestRoundTripTimeVariance = 0;
360    peer -> roundTripTime = ENET_PEER_DEFAULT_ROUND_TRIP_TIME;
361    peer -> roundTripTimeVariance = 0;
362    peer -> mtu = peer -> host -> mtu;
363    peer -> reliableDataInTransit = 0;
364    peer -> outgoingReliableSequenceNumber = 0;
365    peer -> windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE;
366    peer -> incomingUnsequencedGroup = 0;
367    peer -> outgoingUnsequencedGroup = 0;
368    peer -> eventData = 0;
369
370    memset (peer -> unsequencedWindow, 0, sizeof (peer -> unsequencedWindow));
371   
372    enet_peer_reset_queues (peer);
373}
374
375/** Sends a ping request to a peer.
376    @param peer destination for the ping request
377    @remarks ping requests factor into the mean round trip time as designated by the
378    roundTripTime field in the ENetPeer structure.  Enet automatically pings all connected
379    peers at regular intervals, however, this function may be called to ensure more
380    frequent ping requests.
381*/
382void
383enet_peer_ping (ENetPeer * peer)
384{
385    ENetProtocol command;
386
387    if (peer -> state != ENET_PEER_STATE_CONNECTED)
388      return;
389
390    command.header.command = ENET_PROTOCOL_COMMAND_PING | ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE;
391    command.header.channelID = 0xFF;
392   
393    enet_peer_queue_outgoing_command (peer, & command, NULL, 0, 0);
394}
395
396/** Force an immediate disconnection from a peer.
397    @param peer peer to disconnect
398    @param data data describing the disconnection
399    @remarks No ENET_EVENT_DISCONNECT event will be generated. The foreign peer is not
400    guarenteed to receive the disconnect notification, and is reset immediately upon
401    return from this function.
402*/
403void
404enet_peer_disconnect_now (ENetPeer * peer, enet_uint32 data)
405{
406    ENetProtocol command;
407
408    if (peer -> state == ENET_PEER_STATE_DISCONNECTED)
409      return;
410
411    if (peer -> state != ENET_PEER_STATE_ZOMBIE &&
412        peer -> state != ENET_PEER_STATE_DISCONNECTING)
413    {
414        enet_peer_reset_queues (peer);
415
416        command.header.command = ENET_PROTOCOL_COMMAND_DISCONNECT | ENET_PROTOCOL_COMMAND_FLAG_UNSEQUENCED;
417        command.header.channelID = 0xFF;
418        command.disconnect.data = ENET_HOST_TO_NET_32 (data);
419
420        enet_peer_queue_outgoing_command (peer, & command, NULL, 0, 0);
421
422        enet_host_flush (peer -> host);
423    }
424
425    enet_peer_reset (peer);
426}
427
428/** Request a disconnection from a peer.
429    @param peer peer to request a disconnection
430    @param data data describing the disconnection
431    @remarks An ENET_EVENT_DISCONNECT event will be generated by enet_host_service()
432    once the disconnection is complete.
433*/
434void
435enet_peer_disconnect (ENetPeer * peer, enet_uint32 data)
436{
437    ENetProtocol command;
438
439    if (peer -> state == ENET_PEER_STATE_DISCONNECTING ||
440        peer -> state == ENET_PEER_STATE_DISCONNECTED ||
441        peer -> state == ENET_PEER_STATE_ACKNOWLEDGING_DISCONNECT ||
442        peer -> state == ENET_PEER_STATE_ZOMBIE)
443      return;
444
445    enet_peer_reset_queues (peer);
446
447    command.header.command = ENET_PROTOCOL_COMMAND_DISCONNECT;
448    command.header.channelID = 0xFF;
449    command.disconnect.data = ENET_HOST_TO_NET_32 (data);
450
451    if (peer -> state == ENET_PEER_STATE_CONNECTED || peer -> state == ENET_PEER_STATE_DISCONNECT_LATER)
452      command.header.command |= ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE;
453    else
454      command.header.command |= ENET_PROTOCOL_COMMAND_FLAG_UNSEQUENCED;     
455   
456    enet_peer_queue_outgoing_command (peer, & command, NULL, 0, 0);
457
458    if (peer -> state == ENET_PEER_STATE_CONNECTED || peer -> state == ENET_PEER_STATE_DISCONNECT_LATER)
459      peer -> state = ENET_PEER_STATE_DISCONNECTING;
460    else
461    {
462        enet_host_flush (peer -> host);
463        enet_peer_reset (peer);
464    }
465}
466
467/** Request a disconnection from a peer, but only after all queued outgoing packets are sent.
468    @param peer peer to request a disconnection
469    @param data data describing the disconnection
470    @remarks An ENET_EVENT_DISCONNECT event will be generated by enet_host_service()
471    once the disconnection is complete.
472*/
473void
474enet_peer_disconnect_later (ENetPeer * peer, enet_uint32 data)
475{   
476    if ((peer -> state == ENET_PEER_STATE_CONNECTED || peer -> state == ENET_PEER_STATE_DISCONNECT_LATER) && 
477        ! (enet_list_empty (& peer -> outgoingReliableCommands) &&
478           enet_list_empty (& peer -> outgoingUnreliableCommands) && 
479           enet_list_empty (& peer -> sentReliableCommands)))
480    {
481        peer -> state = ENET_PEER_STATE_DISCONNECT_LATER;
482        peer -> eventData = data;
483    }
484    else
485      enet_peer_disconnect (peer, data);
486}
487
488ENetAcknowledgement *
489enet_peer_queue_acknowledgement (ENetPeer * peer, const ENetProtocol * command, enet_uint16 sentTime)
490{
491    ENetAcknowledgement * acknowledgement;
492
493    if (command -> header.channelID < peer -> channelCount)
494    {
495        ENetChannel * channel = & peer -> channels [command -> header.channelID];
496        enet_uint16 reliableWindow = command -> header.reliableSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE,
497                    currentWindow = channel -> incomingReliableSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE;
498
499        if (command -> header.reliableSequenceNumber < channel -> incomingReliableSequenceNumber)
500           reliableWindow += ENET_PEER_RELIABLE_WINDOWS;
501
502        if (reliableWindow >= currentWindow + ENET_PEER_FREE_RELIABLE_WINDOWS - 1 && reliableWindow <= currentWindow + ENET_PEER_FREE_RELIABLE_WINDOWS)
503          return NULL;
504    }
505
506    acknowledgement = (ENetAcknowledgement *) enet_malloc (sizeof (ENetAcknowledgement));
507    if (acknowledgement == NULL)
508      return NULL;
509
510    peer -> outgoingDataTotal += sizeof (ENetProtocolAcknowledge);
511
512    acknowledgement -> sentTime = sentTime;
513    acknowledgement -> command = * command;
514   
515    enet_list_insert (enet_list_end (& peer -> acknowledgements), acknowledgement);
516   
517    return acknowledgement;
518}
519
520void
521enet_peer_setup_outgoing_command (ENetPeer * peer, ENetOutgoingCommand * outgoingCommand)
522{
523    ENetChannel * channel = & peer -> channels [outgoingCommand -> command.header.channelID];
524
525    peer -> outgoingDataTotal += enet_protocol_command_size (outgoingCommand -> command.header.command) + outgoingCommand -> fragmentLength;
526
527    if (outgoingCommand -> command.header.channelID == 0xFF)
528    {
529       ++ peer -> outgoingReliableSequenceNumber;
530
531       outgoingCommand -> reliableSequenceNumber = peer -> outgoingReliableSequenceNumber;
532       outgoingCommand -> unreliableSequenceNumber = 0;
533    }
534    else
535    if (outgoingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE)
536    {
537       ++ channel -> outgoingReliableSequenceNumber;
538       channel -> outgoingUnreliableSequenceNumber = 0;
539
540       outgoingCommand -> reliableSequenceNumber = channel -> outgoingReliableSequenceNumber;
541       outgoingCommand -> unreliableSequenceNumber = 0;
542    }
543    else
544    if (outgoingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_FLAG_UNSEQUENCED)
545    {
546       ++ peer -> outgoingUnsequencedGroup;
547
548       outgoingCommand -> reliableSequenceNumber = 0;
549       outgoingCommand -> unreliableSequenceNumber = 0;
550    }
551    else
552    {
553       ++ channel -> outgoingUnreliableSequenceNumber;
554       
555       outgoingCommand -> reliableSequenceNumber = channel -> outgoingReliableSequenceNumber;
556       outgoingCommand -> unreliableSequenceNumber = channel -> outgoingUnreliableSequenceNumber;
557    }
558   
559    outgoingCommand -> sendAttempts = 0;
560    outgoingCommand -> sentTime = 0;
561    outgoingCommand -> roundTripTimeout = 0;
562    outgoingCommand -> roundTripTimeoutLimit = 0;
563    outgoingCommand -> command.header.reliableSequenceNumber = ENET_HOST_TO_NET_16 (outgoingCommand -> reliableSequenceNumber);
564
565    if (outgoingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE)
566      enet_list_insert (enet_list_end (& peer -> outgoingReliableCommands), outgoingCommand);
567    else
568      enet_list_insert (enet_list_end (& peer -> outgoingUnreliableCommands), outgoingCommand);
569}
570
571ENetOutgoingCommand *
572enet_peer_queue_outgoing_command (ENetPeer * peer, const ENetProtocol * command, ENetPacket * packet, enet_uint32 offset, enet_uint16 length)
573{
574    ENetOutgoingCommand * outgoingCommand = (ENetOutgoingCommand *) enet_malloc (sizeof (ENetOutgoingCommand));
575    if (outgoingCommand == NULL)
576      return NULL;
577
578    outgoingCommand -> command = * command;
579    outgoingCommand -> fragmentOffset = offset;
580    outgoingCommand -> fragmentLength = length;
581    outgoingCommand -> packet = packet;
582    if (packet != NULL)
583      ++ packet -> referenceCount;
584
585    enet_peer_setup_outgoing_command (peer, outgoingCommand);
586
587    return outgoingCommand;
588}
589
590void
591enet_peer_dispatch_incoming_unreliable_commands (ENetPeer * peer, ENetChannel * channel)
592{
593    ENetListIterator currentCommand;
594
595    for (currentCommand = enet_list_begin (& channel -> incomingUnreliableCommands);
596         currentCommand != enet_list_end (& channel -> incomingUnreliableCommands);
597         currentCommand = enet_list_next (currentCommand))
598    {
599       ENetIncomingCommand * incomingCommand = (ENetIncomingCommand *) currentCommand;
600
601       if ((incomingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_MASK) == ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE &&
602           incomingCommand -> reliableSequenceNumber != channel -> incomingReliableSequenceNumber)
603         break;
604    }
605
606    if (currentCommand == enet_list_begin (& channel -> incomingUnreliableCommands))
607      return;
608
609    enet_list_move (enet_list_end (& peer -> dispatchedCommands), enet_list_begin (& channel -> incomingUnreliableCommands), enet_list_previous (currentCommand));
610
611    if (! peer -> needsDispatch)
612    {
613       enet_list_insert (enet_list_end (& peer -> host -> dispatchQueue), & peer -> dispatchList);
614
615       peer -> needsDispatch = 1;
616    }
617}
618
619void
620enet_peer_dispatch_incoming_reliable_commands (ENetPeer * peer, ENetChannel * channel)
621{
622    ENetListIterator currentCommand;
623
624    for (currentCommand = enet_list_begin (& channel -> incomingReliableCommands);
625         currentCommand != enet_list_end (& channel -> incomingReliableCommands);
626         currentCommand = enet_list_next (currentCommand))
627    {
628       ENetIncomingCommand * incomingCommand = (ENetIncomingCommand *) currentCommand;
629         
630       if (incomingCommand -> fragmentsRemaining > 0 ||
631           incomingCommand -> reliableSequenceNumber != (enet_uint16) (channel -> incomingReliableSequenceNumber + 1))
632         break;
633
634       channel -> incomingReliableSequenceNumber = incomingCommand -> reliableSequenceNumber;
635
636       if (incomingCommand -> fragmentCount > 0)
637         channel -> incomingReliableSequenceNumber += incomingCommand -> fragmentCount - 1;
638    } 
639
640    if (currentCommand == enet_list_begin (& channel -> incomingReliableCommands))
641      return;
642
643    enet_list_move (enet_list_end (& peer -> dispatchedCommands), enet_list_begin (& channel -> incomingReliableCommands), enet_list_previous (currentCommand));
644
645    if (! peer -> needsDispatch)
646    {
647       enet_list_insert (enet_list_end (& peer -> host -> dispatchQueue), & peer -> dispatchList);
648
649       peer -> needsDispatch = 1;
650    }
651
652    enet_peer_dispatch_incoming_unreliable_commands (peer, channel);
653}
654
655ENetIncomingCommand *
656enet_peer_queue_incoming_command (ENetPeer * peer, const ENetProtocol * command, ENetPacket * packet, enet_uint32 fragmentCount)
657{
658    static ENetIncomingCommand dummyCommand;
659
660    ENetChannel * channel = & peer -> channels [command -> header.channelID];
661    enet_uint32 unreliableSequenceNumber = 0, reliableSequenceNumber;
662    enet_uint16 reliableWindow, currentWindow;
663    ENetIncomingCommand * incomingCommand;
664    ENetListIterator currentCommand;
665
666    if (peer -> state == ENET_PEER_STATE_DISCONNECT_LATER)
667      goto freePacket;
668
669    if ((command -> header.command & ENET_PROTOCOL_COMMAND_MASK) != ENET_PROTOCOL_COMMAND_SEND_UNSEQUENCED)
670    {
671        reliableSequenceNumber = command -> header.reliableSequenceNumber;
672        reliableWindow = reliableSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE;
673        currentWindow = channel -> incomingReliableSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE;
674
675        if (reliableSequenceNumber < channel -> incomingReliableSequenceNumber)
676           reliableWindow += ENET_PEER_RELIABLE_WINDOWS;
677
678        if (reliableWindow < currentWindow || reliableWindow >= currentWindow + ENET_PEER_FREE_RELIABLE_WINDOWS - 1)
679          goto freePacket;
680    }
681                   
682    switch (command -> header.command & ENET_PROTOCOL_COMMAND_MASK)
683    {
684    case ENET_PROTOCOL_COMMAND_SEND_FRAGMENT:
685    case ENET_PROTOCOL_COMMAND_SEND_RELIABLE:
686       if (reliableSequenceNumber == channel -> incomingReliableSequenceNumber)
687           goto freePacket;
688       
689       for (currentCommand = enet_list_previous (enet_list_end (& channel -> incomingReliableCommands));
690            currentCommand != enet_list_end (& channel -> incomingReliableCommands);
691            currentCommand = enet_list_previous (currentCommand))
692       {
693          incomingCommand = (ENetIncomingCommand *) currentCommand;
694
695          if (reliableSequenceNumber >= channel -> incomingReliableSequenceNumber)
696          {
697             if (incomingCommand -> reliableSequenceNumber < channel -> incomingReliableSequenceNumber)
698               continue;
699          }
700          else
701          if (incomingCommand -> reliableSequenceNumber >= channel -> incomingReliableSequenceNumber)
702            break;
703
704          if (incomingCommand -> reliableSequenceNumber <= reliableSequenceNumber)
705          {
706             if (incomingCommand -> reliableSequenceNumber < reliableSequenceNumber)
707               break;
708
709             goto freePacket;
710          }
711       }
712       break;
713
714    case ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE:
715       unreliableSequenceNumber = ENET_NET_TO_HOST_16 (command -> sendUnreliable.unreliableSequenceNumber);
716
717       for (currentCommand = enet_list_previous (enet_list_end (& channel -> incomingUnreliableCommands));
718            currentCommand != enet_list_end (& channel -> incomingUnreliableCommands);
719            currentCommand = enet_list_previous (currentCommand))
720       {
721          incomingCommand = (ENetIncomingCommand *) currentCommand;
722
723          if ((incomingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_MASK) != ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE)
724            continue;
725
726          if (reliableSequenceNumber >= channel -> incomingReliableSequenceNumber)
727          {
728             if (incomingCommand -> reliableSequenceNumber < channel -> incomingReliableSequenceNumber)
729               continue;
730          }
731          else
732          if (incomingCommand -> reliableSequenceNumber >= channel -> incomingReliableSequenceNumber)
733            break;
734
735          if (incomingCommand -> reliableSequenceNumber < reliableSequenceNumber)
736            break;
737
738          if (incomingCommand -> reliableSequenceNumber > reliableSequenceNumber)
739            continue;
740
741          if (incomingCommand -> unreliableSequenceNumber <= unreliableSequenceNumber)
742          {
743             if (incomingCommand -> unreliableSequenceNumber < unreliableSequenceNumber)
744               break;
745
746             goto freePacket;
747          }
748       }
749       break;
750
751    case ENET_PROTOCOL_COMMAND_SEND_UNSEQUENCED:
752       currentCommand = enet_list_end (& channel -> incomingUnreliableCommands);
753       break;
754
755    default:
756       goto freePacket;
757    }
758
759    incomingCommand = (ENetIncomingCommand *) enet_malloc (sizeof (ENetIncomingCommand));
760    if (incomingCommand == NULL)
761      goto notifyError;
762
763    incomingCommand -> reliableSequenceNumber = command -> header.reliableSequenceNumber;
764    incomingCommand -> unreliableSequenceNumber = unreliableSequenceNumber & 0xFFFF;
765    incomingCommand -> command = * command;
766    incomingCommand -> fragmentCount = fragmentCount;
767    incomingCommand -> fragmentsRemaining = fragmentCount;
768    incomingCommand -> packet = packet;
769    incomingCommand -> fragments = NULL;
770   
771    if (fragmentCount > 0)
772    { 
773       incomingCommand -> fragments = (enet_uint32 *) enet_malloc ((fragmentCount + 31) / 32 * sizeof (enet_uint32));
774       if (incomingCommand -> fragments == NULL)
775       {
776          enet_free (incomingCommand);
777
778          goto notifyError;
779       }
780       memset (incomingCommand -> fragments, 0, (fragmentCount + 31) / 32 * sizeof (enet_uint32));
781    }
782
783    if (packet != NULL)
784      ++ packet -> referenceCount;
785
786    enet_list_insert (enet_list_next (currentCommand), incomingCommand);
787
788    switch (command -> header.command & ENET_PROTOCOL_COMMAND_MASK)
789    {
790    case ENET_PROTOCOL_COMMAND_SEND_FRAGMENT:
791    case ENET_PROTOCOL_COMMAND_SEND_RELIABLE:
792       enet_peer_dispatch_incoming_reliable_commands (peer, channel);
793       break;
794
795    default:
796       enet_peer_dispatch_incoming_unreliable_commands (peer, channel);
797       break;
798    }
799
800    return incomingCommand;
801
802freePacket:
803    if (fragmentCount > 0)
804      goto notifyError;
805
806    if (packet != NULL && packet -> referenceCount == 0)
807      enet_packet_destroy (packet);
808
809    return & dummyCommand;
810
811notifyError:
812    if (packet != NULL && packet -> referenceCount == 0)
813      enet_packet_destroy (packet);
814
815    return NULL;
816}
817
818/** @} */
Note: See TracBrowser for help on using the repository browser.