Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/enet-1.1/peer.c @ 29

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

added enet

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