Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/ipv6/src/external/enet/peer.c @ 7392

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

original enet source included

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