3 @brief ENet peer management functions
6 #define ENET_BUILDING_LIB 1
9 /** @defgroup peer ENet peer functions
13 /** Configures throttle parameter for a peer.
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.
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
43 enet_peer_throttle_configure (ENetPeer
* peer
, enet_uint32 interval
, enet_uint32 acceleration
, enet_uint32 deceleration
)
47 peer
-> packetThrottleInterval
= interval
;
48 peer
-> packetThrottleAcceleration
= acceleration
;
49 peer
-> packetThrottleDeceleration
= deceleration
;
51 command
.header
.command
= ENET_PROTOCOL_COMMAND_THROTTLE_CONFIGURE
| ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE
;
52 command
.header
.channelID
= 0xFF;
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
);
58 enet_peer_queue_outgoing_command (peer
, & command
, NULL
, 0, 0);
62 enet_peer_throttle (ENetPeer
* peer
, enet_uint32 rtt
)
64 if (peer
-> lastRoundTripTime
<= peer
-> lastRoundTripTimeVariance
)
66 peer
-> packetThrottle
= peer
-> packetThrottleLimit
;
69 if (rtt
< peer
-> lastRoundTripTime
)
71 peer
-> packetThrottle
+= peer
-> packetThrottleAcceleration
;
73 if (peer
-> packetThrottle
> peer
-> packetThrottleLimit
)
74 peer
-> packetThrottle
= peer
-> packetThrottleLimit
;
79 if (rtt
> peer
-> lastRoundTripTime
+ 2 * peer
-> lastRoundTripTimeVariance
)
81 if (peer
-> packetThrottle
> peer
-> packetThrottleDeceleration
)
82 peer
-> packetThrottle
-= peer
-> packetThrottleDeceleration
;
84 peer
-> packetThrottle
= 0;
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
97 @retval < 0 on failure
100 enet_peer_send (ENetPeer
* peer
, enet_uint8 channelID
, ENetPacket
* packet
)
102 ENetChannel
* channel
= & peer
-> channels
[channelID
];
103 ENetProtocol command
;
104 size_t fragmentLength
;
106 if (peer
-> state
!= ENET_PEER_STATE_CONNECTED
||
107 channelID
>= peer
-> channelCount
)
110 fragmentLength
= peer
-> mtu
- sizeof (ENetProtocolHeader
) - sizeof (ENetProtocolSendFragment
);
112 if (packet
-> dataLength
> fragmentLength
)
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
),
119 packet
-> flags
|= ENET_PACKET_FLAG_RELIABLE
;
120 packet
-> flags
&= ~ENET_PACKET_FLAG_UNSEQUENCED
;
122 for (fragmentNumber
= 0,
124 fragmentOffset
< packet
-> dataLength
;
126 fragmentOffset
+= fragmentLength
)
128 if (packet
-> dataLength
- fragmentOffset
< fragmentLength
)
129 fragmentLength
= packet
-> dataLength
- fragmentOffset
;
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
);
140 enet_peer_queue_outgoing_command (peer
, & command
, packet
, fragmentOffset
, fragmentLength
);
146 command
.header
.channelID
= channelID
;
148 if (! (packet
-> flags
& (ENET_PACKET_FLAG_RELIABLE
| ENET_PACKET_FLAG_UNSEQUENCED
)) && channel
-> outgoingUnreliableSequenceNumber
>= 0xFFFF)
149 packet
-> flags
|= ENET_PACKET_FLAG_RELIABLE
;
151 if (packet
-> flags
& ENET_PACKET_FLAG_RELIABLE
)
153 command
.header
.command
= ENET_PROTOCOL_COMMAND_SEND_RELIABLE
| ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE
;
154 command
.sendReliable
.dataLength
= ENET_HOST_TO_NET_16 (packet
-> dataLength
);
157 if (packet
-> flags
& ENET_PACKET_FLAG_UNSEQUENCED
)
159 command
.header
.command
= ENET_PROTOCOL_COMMAND_SEND_UNSEQUENCED
| ENET_PROTOCOL_COMMAND_FLAG_UNSEQUENCED
;
160 command
.sendUnsequenced
.unsequencedGroup
= ENET_HOST_TO_NET_16 (peer
-> outgoingUnsequencedGroup
+ 1);
161 command
.sendUnsequenced
.dataLength
= ENET_HOST_TO_NET_16 (packet
-> dataLength
);
165 command
.header
.command
= ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE
;
166 command
.sendUnreliable
.unreliableSequenceNumber
= ENET_HOST_TO_NET_16 (channel
-> outgoingUnreliableSequenceNumber
+ 1);
167 command
.sendUnreliable
.dataLength
= ENET_HOST_TO_NET_16 (packet
-> dataLength
);
170 enet_peer_queue_outgoing_command (peer
, & command
, packet
, 0, packet
-> dataLength
);
175 /** Attempts to dequeue any incoming queued packet.
176 @param peer peer to dequeue packets from
177 @param channelID channel on which to receive
178 @returns a pointer to the packet, or NULL if there are no available incoming queued packets
181 enet_peer_receive (ENetPeer
* peer
, enet_uint8 channelID
)
183 ENetChannel
* channel
= & peer
-> channels
[channelID
];
184 ENetIncomingCommand
* incomingCommand
= NULL
;
187 if (! enet_list_empty (& channel
-> incomingUnreliableCommands
))
189 incomingCommand
= (ENetIncomingCommand
*) enet_list_front (& channel
-> incomingUnreliableCommands
);
191 if ((incomingCommand
-> command
.header
.command
& ENET_PROTOCOL_COMMAND_MASK
) == ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE
)
193 if (incomingCommand
-> reliableSequenceNumber
!= channel
-> incomingReliableSequenceNumber
)
194 incomingCommand
= NULL
;
198 if (incomingCommand
== NULL
&&
199 ! enet_list_empty (& channel
-> incomingReliableCommands
))
201 incomingCommand
= (ENetIncomingCommand
*) enet_list_front (& channel
-> incomingReliableCommands
);
203 if (incomingCommand
-> fragmentsRemaining
> 0 ||
204 incomingCommand
-> reliableSequenceNumber
!= (enet_uint16
) (channel
-> incomingReliableSequenceNumber
+ 1))
207 channel
-> incomingReliableSequenceNumber
= incomingCommand
-> reliableSequenceNumber
;
209 if (incomingCommand
-> fragmentCount
> 0)
210 channel
-> incomingReliableSequenceNumber
+= incomingCommand
-> fragmentCount
- 1;
213 if (incomingCommand
== NULL
)
216 enet_list_remove (& incomingCommand
-> incomingCommandList
);
218 packet
= incomingCommand
-> packet
;
220 -- packet
-> referenceCount
;
222 if (incomingCommand
-> fragments
!= NULL
)
223 enet_free (incomingCommand
-> fragments
);
225 enet_free (incomingCommand
);
231 enet_peer_reset_outgoing_commands (ENetList
* queue
)
233 ENetOutgoingCommand
* outgoingCommand
;
235 while (! enet_list_empty (queue
))
237 outgoingCommand
= (ENetOutgoingCommand
*) enet_list_remove (enet_list_begin (queue
));
239 if (outgoingCommand
-> packet
!= NULL
)
241 -- outgoingCommand
-> packet
-> referenceCount
;
243 if (outgoingCommand
-> packet
-> referenceCount
== 0)
244 enet_packet_destroy (outgoingCommand
-> packet
);
247 enet_free (outgoingCommand
);
252 enet_peer_reset_incoming_commands (ENetList
* queue
)
254 ENetIncomingCommand
* incomingCommand
;
256 while (! enet_list_empty (queue
))
258 incomingCommand
= (ENetIncomingCommand
*) enet_list_remove (enet_list_begin (queue
));
260 if (incomingCommand
-> packet
!= NULL
)
262 -- incomingCommand
-> packet
-> referenceCount
;
264 if (incomingCommand
-> packet
-> referenceCount
== 0)
265 enet_packet_destroy (incomingCommand
-> packet
);
268 if (incomingCommand
-> fragments
!= NULL
)
269 enet_free (incomingCommand
-> fragments
);
271 enet_free (incomingCommand
);
276 enet_peer_reset_queues (ENetPeer
* peer
)
278 ENetChannel
* channel
;
280 while (! enet_list_empty (& peer
-> acknowledgements
))
281 enet_free (enet_list_remove (enet_list_begin (& peer
-> acknowledgements
)));
283 enet_peer_reset_outgoing_commands (& peer
-> sentReliableCommands
);
284 enet_peer_reset_outgoing_commands (& peer
-> sentUnreliableCommands
);
285 enet_peer_reset_outgoing_commands (& peer
-> outgoingReliableCommands
);
286 enet_peer_reset_outgoing_commands (& peer
-> outgoingUnreliableCommands
);
288 if (peer
-> channels
!= NULL
&& peer
-> channelCount
> 0)
290 for (channel
= peer
-> channels
;
291 channel
< & peer
-> channels
[peer
-> channelCount
];
294 enet_peer_reset_incoming_commands (& channel
-> incomingReliableCommands
);
295 enet_peer_reset_incoming_commands (& channel
-> incomingUnreliableCommands
);
298 enet_free (peer
-> channels
);
301 peer
-> channels
= NULL
;
302 peer
-> channelCount
= 0;
305 /** Forcefully disconnects a peer.
306 @param peer peer to forcefully disconnect
307 @remarks The foreign host represented by the peer is not notified of the disconnection and will timeout
308 on its connection to the local host.
311 enet_peer_reset (ENetPeer
* peer
)
313 peer
-> outgoingPeerID
= ENET_PROTOCOL_MAXIMUM_PEER_ID
;
314 peer
-> sessionID
= 0;
316 peer
-> state
= ENET_PEER_STATE_DISCONNECTED
;
318 peer
-> incomingBandwidth
= 0;
319 peer
-> outgoingBandwidth
= 0;
320 peer
-> incomingBandwidthThrottleEpoch
= 0;
321 peer
-> outgoingBandwidthThrottleEpoch
= 0;
322 peer
-> incomingDataTotal
= 0;
323 peer
-> outgoingDataTotal
= 0;
324 peer
-> lastSendTime
= 0;
325 peer
-> lastReceiveTime
= 0;
326 peer
-> nextTimeout
= 0;
327 peer
-> earliestTimeout
= 0;
328 peer
-> packetLossEpoch
= 0;
329 peer
-> packetsSent
= 0;
330 peer
-> packetsLost
= 0;
331 peer
-> packetLoss
= 0;
332 peer
-> packetLossVariance
= 0;
333 peer
-> packetThrottle
= ENET_PEER_DEFAULT_PACKET_THROTTLE
;
334 peer
-> packetThrottleLimit
= ENET_PEER_PACKET_THROTTLE_SCALE
;
335 peer
-> packetThrottleCounter
= 0;
336 peer
-> packetThrottleEpoch
= 0;
337 peer
-> packetThrottleAcceleration
= ENET_PEER_PACKET_THROTTLE_ACCELERATION
;
338 peer
-> packetThrottleDeceleration
= ENET_PEER_PACKET_THROTTLE_DECELERATION
;
339 peer
-> packetThrottleInterval
= ENET_PEER_PACKET_THROTTLE_INTERVAL
;
340 peer
-> lastRoundTripTime
= ENET_PEER_DEFAULT_ROUND_TRIP_TIME
;
341 peer
-> lowestRoundTripTime
= ENET_PEER_DEFAULT_ROUND_TRIP_TIME
;
342 peer
-> lastRoundTripTimeVariance
= 0;
343 peer
-> highestRoundTripTimeVariance
= 0;
344 peer
-> roundTripTime
= ENET_PEER_DEFAULT_ROUND_TRIP_TIME
;
345 peer
-> roundTripTimeVariance
= 0;
346 peer
-> mtu
= peer
-> host
-> mtu
;
347 peer
-> reliableDataInTransit
= 0;
348 peer
-> outgoingReliableSequenceNumber
= 0;
349 peer
-> windowSize
= ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE
;
350 peer
-> incomingUnsequencedGroup
= 0;
351 peer
-> outgoingUnsequencedGroup
= 0;
352 peer
-> disconnectData
= 0;
354 memset (peer
-> unsequencedWindow
, 0, sizeof (peer
-> unsequencedWindow
));
356 enet_peer_reset_queues (peer
);
359 /** Sends a ping request to a peer.
360 @param peer destination for the ping request
361 @remarks ping requests factor into the mean round trip time as designated by the
362 roundTripTime field in the ENetPeer structure. Enet automatically pings all connected
363 peers at regular intervals, however, this function may be called to ensure more
364 frequent ping requests.
367 enet_peer_ping (ENetPeer
* peer
)
369 ENetProtocol command
;
371 if (peer
-> state
!= ENET_PEER_STATE_CONNECTED
)
374 command
.header
.command
= ENET_PROTOCOL_COMMAND_PING
| ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE
;
375 command
.header
.channelID
= 0xFF;
377 enet_peer_queue_outgoing_command (peer
, & command
, NULL
, 0, 0);
380 /** Force an immediate disconnection from a peer.
381 @param peer peer to disconnect
382 @param data data describing the disconnection
383 @remarks No ENET_EVENT_DISCONNECT event will be generated. The foreign peer is not
384 guarenteed to receive the disconnect notification, and is reset immediately upon
385 return from this function.
388 enet_peer_disconnect_now (ENetPeer
* peer
, enet_uint32 data
)
390 ENetProtocol command
;
392 if (peer
-> state
== ENET_PEER_STATE_DISCONNECTED
)
395 if (peer
-> state
!= ENET_PEER_STATE_ZOMBIE
&&
396 peer
-> state
!= ENET_PEER_STATE_DISCONNECTING
)
398 enet_peer_reset_queues (peer
);
400 command
.header
.command
= ENET_PROTOCOL_COMMAND_DISCONNECT
| ENET_PROTOCOL_COMMAND_FLAG_UNSEQUENCED
;
401 command
.header
.channelID
= 0xFF;
402 command
.disconnect
.data
= ENET_HOST_TO_NET_32 (data
);
404 enet_peer_queue_outgoing_command (peer
, & command
, NULL
, 0, 0);
406 enet_host_flush (peer
-> host
);
409 enet_peer_reset (peer
);
412 /** Request a disconnection from a peer.
413 @param peer peer to request a disconnection
414 @param data data describing the disconnection
415 @remarks An ENET_EVENT_DISCONNECT event will be generated by enet_host_service()
416 once the disconnection is complete.
419 enet_peer_disconnect (ENetPeer
* peer
, enet_uint32 data
)
421 ENetProtocol command
;
423 if (peer
-> state
== ENET_PEER_STATE_DISCONNECTING
||
424 peer
-> state
== ENET_PEER_STATE_DISCONNECTED
||
425 peer
-> state
== ENET_PEER_STATE_ZOMBIE
)
428 enet_peer_reset_queues (peer
);
430 command
.header
.command
= ENET_PROTOCOL_COMMAND_DISCONNECT
;
431 command
.header
.channelID
= 0xFF;
432 command
.disconnect
.data
= ENET_HOST_TO_NET_32 (data
);
434 if (peer
-> state
== ENET_PEER_STATE_CONNECTED
|| peer
-> state
== ENET_PEER_STATE_DISCONNECT_LATER
)
435 command
.header
.command
|= ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE
;
437 command
.header
.command
|= ENET_PROTOCOL_COMMAND_FLAG_UNSEQUENCED
;
439 enet_peer_queue_outgoing_command (peer
, & command
, NULL
, 0, 0);
441 if (peer
-> state
== ENET_PEER_STATE_CONNECTED
|| peer
-> state
== ENET_PEER_STATE_DISCONNECT_LATER
)
442 peer
-> state
= ENET_PEER_STATE_DISCONNECTING
;
445 enet_host_flush (peer
-> host
);
446 enet_peer_reset (peer
);
450 /** Request a disconnection from a peer, but only after all queued outgoing packets are sent.
451 @param peer peer to request a disconnection
452 @param data data describing the disconnection
453 @remarks An ENET_EVENT_DISCONNECT event will be generated by enet_host_service()
454 once the disconnection is complete.
457 enet_peer_disconnect_later (ENetPeer
* peer
, enet_uint32 data
)
459 if ((peer
-> state
== ENET_PEER_STATE_CONNECTED
|| peer
-> state
== ENET_PEER_STATE_DISCONNECT_LATER
) &&
460 ! (enet_list_empty (& peer
-> outgoingReliableCommands
) &&
461 enet_list_empty (& peer
-> outgoingUnreliableCommands
) &&
462 enet_list_empty (& peer
-> sentReliableCommands
)))
464 peer
-> state
= ENET_PEER_STATE_DISCONNECT_LATER
;
465 peer
-> disconnectData
= data
;
468 enet_peer_disconnect (peer
, data
);
471 ENetAcknowledgement
*
472 enet_peer_queue_acknowledgement (ENetPeer
* peer
, const ENetProtocol
* command
, enet_uint16 sentTime
)
474 ENetAcknowledgement
* acknowledgement
;
476 if (command
-> header
.channelID
< peer
-> channelCount
)
478 ENetChannel
* channel
= & peer
-> channels
[command
-> header
.channelID
];
479 enet_uint16 reliableWindow
= command
-> header
.reliableSequenceNumber
/ ENET_PEER_RELIABLE_WINDOW_SIZE
,
480 currentWindow
= channel
-> incomingReliableSequenceNumber
/ ENET_PEER_RELIABLE_WINDOW_SIZE
;
482 if (command
-> header
.reliableSequenceNumber
< channel
-> incomingReliableSequenceNumber
)
483 reliableWindow
+= ENET_PEER_RELIABLE_WINDOWS
;
485 if (reliableWindow
>= currentWindow
+ ENET_PEER_FREE_RELIABLE_WINDOWS
- 1 && reliableWindow
<= currentWindow
+ ENET_PEER_FREE_RELIABLE_WINDOWS
)
489 peer
-> outgoingDataTotal
+= sizeof (ENetProtocolAcknowledge
);
491 acknowledgement
= (ENetAcknowledgement
*) enet_malloc (sizeof (ENetAcknowledgement
));
493 acknowledgement
-> sentTime
= sentTime
;
494 acknowledgement
-> command
= * command
;
496 enet_list_insert (enet_list_end (& peer
-> acknowledgements
), acknowledgement
);
498 return acknowledgement
;
501 ENetOutgoingCommand
*
502 enet_peer_queue_outgoing_command (ENetPeer
* peer
, const ENetProtocol
* command
, ENetPacket
* packet
, enet_uint32 offset
, enet_uint16 length
)
504 ENetChannel
* channel
= & peer
-> channels
[command
-> header
.channelID
];
505 ENetOutgoingCommand
* outgoingCommand
;
507 peer
-> outgoingDataTotal
+= enet_protocol_command_size (command
-> header
.command
) + length
;
509 outgoingCommand
= (ENetOutgoingCommand
*) enet_malloc (sizeof (ENetOutgoingCommand
));
511 if (command
-> header
.channelID
== 0xFF)
513 ++ peer
-> outgoingReliableSequenceNumber
;
515 outgoingCommand
-> reliableSequenceNumber
= peer
-> outgoingReliableSequenceNumber
;
516 outgoingCommand
-> unreliableSequenceNumber
= 0;
519 if (command
-> header
.command
& ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE
)
521 ++ channel
-> outgoingReliableSequenceNumber
;
522 channel
-> outgoingUnreliableSequenceNumber
= 0;
524 outgoingCommand
-> reliableSequenceNumber
= channel
-> outgoingReliableSequenceNumber
;
525 outgoingCommand
-> unreliableSequenceNumber
= 0;
528 if (command
-> header
.command
& ENET_PROTOCOL_COMMAND_FLAG_UNSEQUENCED
)
530 ++ peer
-> outgoingUnsequencedGroup
;
532 outgoingCommand
-> reliableSequenceNumber
= 0;
533 outgoingCommand
-> unreliableSequenceNumber
= 0;
537 ++ channel
-> outgoingUnreliableSequenceNumber
;
539 outgoingCommand
-> reliableSequenceNumber
= channel
-> outgoingReliableSequenceNumber
;
540 outgoingCommand
-> unreliableSequenceNumber
= channel
-> outgoingUnreliableSequenceNumber
;
543 outgoingCommand
-> sendAttempts
= 0;
544 outgoingCommand
-> sentTime
= 0;
545 outgoingCommand
-> roundTripTimeout
= 0;
546 outgoingCommand
-> roundTripTimeoutLimit
= 0;
547 outgoingCommand
-> fragmentOffset
= offset
;
548 outgoingCommand
-> fragmentLength
= length
;
549 outgoingCommand
-> packet
= packet
;
550 outgoingCommand
-> command
= * command
;
551 outgoingCommand
-> command
.header
.reliableSequenceNumber
= ENET_HOST_TO_NET_16 (outgoingCommand
-> reliableSequenceNumber
);
554 ++ packet
-> referenceCount
;
556 if (command
-> header
.command
& ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE
)
557 enet_list_insert (enet_list_end (& peer
-> outgoingReliableCommands
), outgoingCommand
);
559 enet_list_insert (enet_list_end (& peer
-> outgoingUnreliableCommands
), outgoingCommand
);
561 return outgoingCommand
;
564 ENetIncomingCommand
*
565 enet_peer_queue_incoming_command (ENetPeer
* peer
, const ENetProtocol
* command
, ENetPacket
* packet
, enet_uint32 fragmentCount
)
567 ENetChannel
* channel
= & peer
-> channels
[command
-> header
.channelID
];
568 enet_uint32 unreliableSequenceNumber
= 0, reliableSequenceNumber
;
569 enet_uint16 reliableWindow
, currentWindow
;
570 ENetIncomingCommand
* incomingCommand
;
571 ENetListIterator currentCommand
;
573 if (peer
-> state
== ENET_PEER_STATE_DISCONNECT_LATER
)
576 if ((command
-> header
.command
& ENET_PROTOCOL_COMMAND_MASK
) != ENET_PROTOCOL_COMMAND_SEND_UNSEQUENCED
)
578 reliableSequenceNumber
= command
-> header
.reliableSequenceNumber
;
579 reliableWindow
= reliableSequenceNumber
/ ENET_PEER_RELIABLE_WINDOW_SIZE
;
580 currentWindow
= channel
-> incomingReliableSequenceNumber
/ ENET_PEER_RELIABLE_WINDOW_SIZE
;
582 if (reliableSequenceNumber
< channel
-> incomingReliableSequenceNumber
)
583 reliableWindow
+= ENET_PEER_RELIABLE_WINDOWS
;
585 if (reliableWindow
< currentWindow
|| reliableWindow
>= currentWindow
+ ENET_PEER_FREE_RELIABLE_WINDOWS
- 1)
589 switch (command
-> header
.command
& ENET_PROTOCOL_COMMAND_MASK
)
591 case ENET_PROTOCOL_COMMAND_SEND_FRAGMENT
:
592 case ENET_PROTOCOL_COMMAND_SEND_RELIABLE
:
593 if (reliableSequenceNumber
== channel
-> incomingReliableSequenceNumber
)
596 for (currentCommand
= enet_list_previous (enet_list_end (& channel
-> incomingReliableCommands
));
597 currentCommand
!= enet_list_end (& channel
-> incomingReliableCommands
);
598 currentCommand
= enet_list_previous (currentCommand
))
600 incomingCommand
= (ENetIncomingCommand
*) currentCommand
;
602 if (reliableSequenceNumber
>= channel
-> incomingReliableSequenceNumber
)
604 if (incomingCommand
-> reliableSequenceNumber
< channel
-> incomingReliableSequenceNumber
)
608 if (incomingCommand
-> reliableSequenceNumber
>= channel
-> incomingReliableSequenceNumber
)
611 if (incomingCommand
-> reliableSequenceNumber
<= reliableSequenceNumber
)
613 if (incomingCommand
-> reliableSequenceNumber
< reliableSequenceNumber
)
621 case ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE
:
622 unreliableSequenceNumber
= ENET_NET_TO_HOST_16 (command
-> sendUnreliable
.unreliableSequenceNumber
);
624 for (currentCommand
= enet_list_previous (enet_list_end (& channel
-> incomingUnreliableCommands
));
625 currentCommand
!= enet_list_end (& channel
-> incomingUnreliableCommands
);
626 currentCommand
= enet_list_previous (currentCommand
))
628 incomingCommand
= (ENetIncomingCommand
*) currentCommand
;
630 if ((incomingCommand
-> command
.header
.command
& ENET_PROTOCOL_COMMAND_MASK
) != ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE
)
633 if (reliableSequenceNumber
>= channel
-> incomingReliableSequenceNumber
)
635 if (incomingCommand
-> reliableSequenceNumber
< channel
-> incomingReliableSequenceNumber
)
639 if (incomingCommand
-> reliableSequenceNumber
>= channel
-> incomingReliableSequenceNumber
)
642 if (incomingCommand
-> reliableSequenceNumber
< reliableSequenceNumber
)
645 if (incomingCommand
-> reliableSequenceNumber
> reliableSequenceNumber
)
648 if (incomingCommand
-> unreliableSequenceNumber
<= unreliableSequenceNumber
)
650 if (incomingCommand
-> unreliableSequenceNumber
< unreliableSequenceNumber
)
658 case ENET_PROTOCOL_COMMAND_SEND_UNSEQUENCED
:
659 currentCommand
= enet_list_end (& channel
-> incomingUnreliableCommands
);
666 incomingCommand
= (ENetIncomingCommand
*) enet_malloc (sizeof (ENetIncomingCommand
));
668 incomingCommand
-> reliableSequenceNumber
= command
-> header
.reliableSequenceNumber
;
669 incomingCommand
-> unreliableSequenceNumber
= unreliableSequenceNumber
& 0xFFFF;
670 incomingCommand
-> command
= * command
;
671 incomingCommand
-> fragmentCount
= fragmentCount
;
672 incomingCommand
-> fragmentsRemaining
= fragmentCount
;
673 incomingCommand
-> packet
= packet
;
674 incomingCommand
-> fragments
= NULL
;
676 if (fragmentCount
> 0)
678 incomingCommand
-> fragments
= (enet_uint32
*) enet_malloc ((fragmentCount
+ 31) / 32 * sizeof (enet_uint32
));
679 memset (incomingCommand
-> fragments
, 0, (fragmentCount
+ 31) / 32 * sizeof (enet_uint32
));
683 ++ packet
-> referenceCount
;
685 enet_list_insert (enet_list_next (currentCommand
), incomingCommand
);
687 return incomingCommand
;
692 if (packet
-> referenceCount
== 0)
693 enet_packet_destroy (packet
);