summaryrefslogtreecommitdiff
path: root/src/enet/peer.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/enet/peer.c')
-rw-r--r--src/enet/peer.c816
1 files changed, 0 insertions, 816 deletions
diff --git a/src/enet/peer.c b/src/enet/peer.c
deleted file mode 100644
index d778ce1d6..000000000
--- a/src/enet/peer.c
+++ /dev/null
@@ -1,816 +0,0 @@
-/**
- @file peer.c
- @brief ENet peer management functions
-*/
-#include <string.h>
-#define ENET_BUILDING_LIB 1
-#include "enet/enet.h"
-
-/** @defgroup peer ENet peer functions
- @{
-*/
-
-/** Configures throttle parameter for a peer.
-
- Unreliable packets are dropped by ENet in response to the varying conditions
- of the Internet connection to the peer. The throttle represents a probability
- that an unreliable packet should not be dropped and thus sent by ENet to the peer.
- The lowest mean round trip time from the sending of a reliable packet to the
- receipt of its acknowledgement is measured over an amount of time specified by
- the interval parameter in milliseconds. If a measured round trip time happens to
- be significantly less than the mean round trip time measured over the interval,
- then the throttle probability is increased to allow more traffic by an amount
- specified in the acceleration parameter, which is a ratio to the ENET_PEER_PACKET_THROTTLE_SCALE
- constant. If a measured round trip time happens to be significantly greater than
- the mean round trip time measured over the interval, then the throttle probability
- is decreased to limit traffic by an amount specified in the deceleration parameter, which
- is a ratio to the ENET_PEER_PACKET_THROTTLE_SCALE constant. When the throttle has
- a value of ENET_PEER_PACKET_THROTTLE_SCALE, on unreliable packets are dropped by
- ENet, and so 100% of all unreliable packets will be sent. When the throttle has a
- value of 0, all unreliable packets are dropped by ENet, and so 0% of all unreliable
- packets will be sent. Intermediate values for the throttle represent intermediate
- probabilities between 0% and 100% of unreliable packets being sent. The bandwidth
- limits of the local and foreign hosts are taken into account to determine a
- sensible limit for the throttle probability above which it should not raise even in
- the best of conditions.
-
- @param peer peer to configure
- @param interval interval, in milliseconds, over which to measure lowest mean RTT; the default value is ENET_PEER_PACKET_THROTTLE_INTERVAL.
- @param acceleration rate at which to increase the throttle probability as mean RTT declines
- @param deceleration rate at which to decrease the throttle probability as mean RTT increases
-*/
-void
-enet_peer_throttle_configure (ENetPeer * peer, enet_uint32 interval, enet_uint32 acceleration, enet_uint32 deceleration)
-{
- ENetProtocol command;
-
- peer -> packetThrottleInterval = interval;
- peer -> packetThrottleAcceleration = acceleration;
- peer -> packetThrottleDeceleration = deceleration;
-
- command.header.command = ENET_PROTOCOL_COMMAND_THROTTLE_CONFIGURE | ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE;
- command.header.channelID = 0xFF;
-
- command.throttleConfigure.packetThrottleInterval = ENET_HOST_TO_NET_32 (interval);
- command.throttleConfigure.packetThrottleAcceleration = ENET_HOST_TO_NET_32 (acceleration);
- command.throttleConfigure.packetThrottleDeceleration = ENET_HOST_TO_NET_32 (deceleration);
-
- enet_peer_queue_outgoing_command (peer, & command, NULL, 0, 0);
-}
-
-int
-enet_peer_throttle (ENetPeer * peer, enet_uint32 rtt)
-{
- if (peer -> lastRoundTripTime <= peer -> lastRoundTripTimeVariance)
- {
- peer -> packetThrottle = peer -> packetThrottleLimit;
- }
- else
- if (rtt < peer -> lastRoundTripTime)
- {
- peer -> packetThrottle += peer -> packetThrottleAcceleration;
-
- if (peer -> packetThrottle > peer -> packetThrottleLimit)
- peer -> packetThrottle = peer -> packetThrottleLimit;
-
- return 1;
- }
- else
- if (rtt > peer -> lastRoundTripTime + 2 * peer -> lastRoundTripTimeVariance)
- {
- if (peer -> packetThrottle > peer -> packetThrottleDeceleration)
- peer -> packetThrottle -= peer -> packetThrottleDeceleration;
- else
- peer -> packetThrottle = 0;
-
- return -1;
- }
-
- return 0;
-}
-
-/** Queues a packet to be sent.
- @param peer destination for the packet
- @param channelID channel on which to send
- @param packet packet to send
- @retval 0 on success
- @retval < 0 on failure
-*/
-int
-enet_peer_send (ENetPeer * peer, enet_uint8 channelID, ENetPacket * packet)
-{
- ENetChannel * channel = & peer -> channels [channelID];
- ENetProtocol command;
- size_t fragmentLength;
-
- if (peer -> state != ENET_PEER_STATE_CONNECTED ||
- channelID >= peer -> channelCount)
- return -1;
-
- fragmentLength = peer -> mtu - sizeof (ENetProtocolHeader) - sizeof (ENetProtocolSendFragment);
-
- if (packet -> dataLength > fragmentLength)
- {
- enet_uint16 startSequenceNumber = ENET_HOST_TO_NET_16 (channel -> outgoingReliableSequenceNumber + 1);
- enet_uint32 fragmentCount = ENET_HOST_TO_NET_32 ((packet -> dataLength + fragmentLength - 1) / fragmentLength),
- fragmentNumber,
- fragmentOffset;
- ENetList fragments;
- ENetOutgoingCommand * fragment;
-
- enet_list_clear (& fragments);
-
- for (fragmentNumber = 0,
- fragmentOffset = 0;
- fragmentOffset < packet -> dataLength;
- ++ fragmentNumber,
- fragmentOffset += fragmentLength)
- {
- if (packet -> dataLength - fragmentOffset < fragmentLength)
- fragmentLength = packet -> dataLength - fragmentOffset;
-
- fragment = (ENetOutgoingCommand *) enet_malloc (sizeof (ENetOutgoingCommand));
- if (fragment == NULL)
- {
- while (! enet_list_empty (& fragments))
- {
- fragment = (ENetOutgoingCommand *) enet_list_remove (enet_list_begin (& fragments));
-
- enet_free (fragment);
- }
-
- return -1;
- }
-
- fragment -> fragmentOffset = fragmentOffset;
- fragment -> fragmentLength = fragmentLength;
- fragment -> packet = packet;
- fragment -> command.header.command = ENET_PROTOCOL_COMMAND_SEND_FRAGMENT | ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE;
- fragment -> command.header.channelID = channelID;
- fragment -> command.sendFragment.startSequenceNumber = startSequenceNumber;
- fragment -> command.sendFragment.dataLength = ENET_HOST_TO_NET_16 (fragmentLength);
- fragment -> command.sendFragment.fragmentCount = fragmentCount;
- fragment -> command.sendFragment.fragmentNumber = ENET_HOST_TO_NET_32 (fragmentNumber);
- fragment -> command.sendFragment.totalLength = ENET_HOST_TO_NET_32 (packet -> dataLength);
- fragment -> command.sendFragment.fragmentOffset = ENET_NET_TO_HOST_32 (fragmentOffset);
-
- enet_list_insert (enet_list_end (& fragments), fragment);
- }
-
- packet -> referenceCount += fragmentNumber;
-
- while (! enet_list_empty (& fragments))
- {
- fragment = (ENetOutgoingCommand *) enet_list_remove (enet_list_begin (& fragments));
-
- enet_peer_setup_outgoing_command (peer, fragment);
- }
-
- return 0;
- }
-
- command.header.channelID = channelID;
-
- if (packet -> flags & ENET_PACKET_FLAG_RELIABLE)
- {
- command.header.command = ENET_PROTOCOL_COMMAND_SEND_RELIABLE | ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE;
- command.sendReliable.dataLength = ENET_HOST_TO_NET_16 (packet -> dataLength);
- }
- else
- if (packet -> flags & ENET_PACKET_FLAG_UNSEQUENCED)
- {
- command.header.command = ENET_PROTOCOL_COMMAND_SEND_UNSEQUENCED | ENET_PROTOCOL_COMMAND_FLAG_UNSEQUENCED;
- command.sendUnsequenced.unsequencedGroup = ENET_HOST_TO_NET_16 (peer -> outgoingUnsequencedGroup + 1);
- command.sendUnsequenced.dataLength = ENET_HOST_TO_NET_16 (packet -> dataLength);
- }
- else
- if (channel -> outgoingUnreliableSequenceNumber >= 0xFFFF)
- {
- command.header.command = ENET_PROTOCOL_COMMAND_SEND_RELIABLE | ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE;
- command.sendReliable.dataLength = ENET_HOST_TO_NET_16 (packet -> dataLength);
- }
- else
- {
- command.header.command = ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE;
- command.sendUnreliable.unreliableSequenceNumber = ENET_HOST_TO_NET_16 (channel -> outgoingUnreliableSequenceNumber + 1);
- command.sendUnreliable.dataLength = ENET_HOST_TO_NET_16 (packet -> dataLength);
- }
-
- if (enet_peer_queue_outgoing_command (peer, & command, packet, 0, packet -> dataLength) == NULL)
- return -1;
-
- return 0;
-}
-
-/** Attempts to dequeue any incoming queued packet.
- @param peer peer to dequeue packets from
- @param channelID holds the channel ID of the channel the packet was received on success
- @returns a pointer to the packet, or NULL if there are no available incoming queued packets
-*/
-ENetPacket *
-enet_peer_receive (ENetPeer * peer, enet_uint8 * channelID)
-{
- ENetIncomingCommand * incomingCommand;
- ENetPacket * packet;
-
- if (enet_list_empty (& peer -> dispatchedCommands))
- return NULL;
-
- incomingCommand = (ENetIncomingCommand *) enet_list_remove (enet_list_begin (& peer -> dispatchedCommands));
-
- if (channelID != NULL)
- * channelID = incomingCommand -> command.header.channelID;
-
- packet = incomingCommand -> packet;
-
- -- packet -> referenceCount;
-
- if (incomingCommand -> fragments != NULL)
- enet_free (incomingCommand -> fragments);
-
- enet_free (incomingCommand);
-
- return packet;
-}
-
-static void
-enet_peer_reset_outgoing_commands (ENetList * queue)
-{
- ENetOutgoingCommand * outgoingCommand;
-
- while (! enet_list_empty (queue))
- {
- outgoingCommand = (ENetOutgoingCommand *) enet_list_remove (enet_list_begin (queue));
-
- if (outgoingCommand -> packet != NULL)
- {
- -- outgoingCommand -> packet -> referenceCount;
-
- if (outgoingCommand -> packet -> referenceCount == 0)
- enet_packet_destroy (outgoingCommand -> packet);
- }
-
- enet_free (outgoingCommand);
- }
-}
-
-static void
-enet_peer_reset_incoming_commands (ENetList * queue)
-{
- ENetIncomingCommand * incomingCommand;
-
- while (! enet_list_empty (queue))
- {
- incomingCommand = (ENetIncomingCommand *) enet_list_remove (enet_list_begin (queue));
-
- if (incomingCommand -> packet != NULL)
- {
- -- incomingCommand -> packet -> referenceCount;
-
- if (incomingCommand -> packet -> referenceCount == 0)
- enet_packet_destroy (incomingCommand -> packet);
- }
-
- if (incomingCommand -> fragments != NULL)
- enet_free (incomingCommand -> fragments);
-
- enet_free (incomingCommand);
- }
-}
-
-void
-enet_peer_reset_queues (ENetPeer * peer)
-{
- ENetChannel * channel;
-
- if (peer -> needsDispatch)
- {
- enet_list_remove (& peer -> dispatchList);
-
- peer -> needsDispatch = 0;
- }
-
- while (! enet_list_empty (& peer -> acknowledgements))
- enet_free (enet_list_remove (enet_list_begin (& peer -> acknowledgements)));
-
- enet_peer_reset_outgoing_commands (& peer -> sentReliableCommands);
- enet_peer_reset_outgoing_commands (& peer -> sentUnreliableCommands);
- enet_peer_reset_outgoing_commands (& peer -> outgoingReliableCommands);
- enet_peer_reset_outgoing_commands (& peer -> outgoingUnreliableCommands);
- enet_peer_reset_incoming_commands (& peer -> dispatchedCommands);
-
- if (peer -> channels != NULL && peer -> channelCount > 0)
- {
- for (channel = peer -> channels;
- channel < & peer -> channels [peer -> channelCount];
- ++ channel)
- {
- enet_peer_reset_incoming_commands (& channel -> incomingReliableCommands);
- enet_peer_reset_incoming_commands (& channel -> incomingUnreliableCommands);
- }
-
- enet_free (peer -> channels);
- }
-
- peer -> channels = NULL;
- peer -> channelCount = 0;
-}
-
-/** Forcefully disconnects a peer.
- @param peer peer to forcefully disconnect
- @remarks The foreign host represented by the peer is not notified of the disconnection and will timeout
- on its connection to the local host.
-*/
-void
-enet_peer_reset (ENetPeer * peer)
-{
- peer -> outgoingPeerID = ENET_PROTOCOL_MAXIMUM_PEER_ID;
- peer -> connectID = 0;
-
- peer -> state = ENET_PEER_STATE_DISCONNECTED;
-
- peer -> incomingBandwidth = 0;
- peer -> outgoingBandwidth = 0;
- peer -> incomingBandwidthThrottleEpoch = 0;
- peer -> outgoingBandwidthThrottleEpoch = 0;
- peer -> incomingDataTotal = 0;
- peer -> outgoingDataTotal = 0;
- peer -> lastSendTime = 0;
- peer -> lastReceiveTime = 0;
- peer -> nextTimeout = 0;
- peer -> earliestTimeout = 0;
- peer -> packetLossEpoch = 0;
- peer -> packetsSent = 0;
- peer -> packetsLost = 0;
- peer -> packetLoss = 0;
- peer -> packetLossVariance = 0;
- peer -> packetThrottle = ENET_PEER_DEFAULT_PACKET_THROTTLE;
- peer -> packetThrottleLimit = ENET_PEER_PACKET_THROTTLE_SCALE;
- peer -> packetThrottleCounter = 0;
- peer -> packetThrottleEpoch = 0;
- peer -> packetThrottleAcceleration = ENET_PEER_PACKET_THROTTLE_ACCELERATION;
- peer -> packetThrottleDeceleration = ENET_PEER_PACKET_THROTTLE_DECELERATION;
- peer -> packetThrottleInterval = ENET_PEER_PACKET_THROTTLE_INTERVAL;
- peer -> lastRoundTripTime = ENET_PEER_DEFAULT_ROUND_TRIP_TIME;
- peer -> lowestRoundTripTime = ENET_PEER_DEFAULT_ROUND_TRIP_TIME;
- peer -> lastRoundTripTimeVariance = 0;
- peer -> highestRoundTripTimeVariance = 0;
- peer -> roundTripTime = ENET_PEER_DEFAULT_ROUND_TRIP_TIME;
- peer -> roundTripTimeVariance = 0;
- peer -> mtu = peer -> host -> mtu;
- peer -> reliableDataInTransit = 0;
- peer -> outgoingReliableSequenceNumber = 0;
- peer -> windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE;
- peer -> incomingUnsequencedGroup = 0;
- peer -> outgoingUnsequencedGroup = 0;
- peer -> eventData = 0;
-
- memset (peer -> unsequencedWindow, 0, sizeof (peer -> unsequencedWindow));
-
- enet_peer_reset_queues (peer);
-}
-
-/** Sends a ping request to a peer.
- @param peer destination for the ping request
- @remarks ping requests factor into the mean round trip time as designated by the
- roundTripTime field in the ENetPeer structure. Enet automatically pings all connected
- peers at regular intervals, however, this function may be called to ensure more
- frequent ping requests.
-*/
-void
-enet_peer_ping (ENetPeer * peer)
-{
- ENetProtocol command;
-
- if (peer -> state != ENET_PEER_STATE_CONNECTED)
- return;
-
- command.header.command = ENET_PROTOCOL_COMMAND_PING | ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE;
- command.header.channelID = 0xFF;
-
- enet_peer_queue_outgoing_command (peer, & command, NULL, 0, 0);
-}
-
-/** Force an immediate disconnection from a peer.
- @param peer peer to disconnect
- @param data data describing the disconnection
- @remarks No ENET_EVENT_DISCONNECT event will be generated. The foreign peer is not
- guarenteed to receive the disconnect notification, and is reset immediately upon
- return from this function.
-*/
-void
-enet_peer_disconnect_now (ENetPeer * peer, enet_uint32 data)
-{
- ENetProtocol command;
-
- if (peer -> state == ENET_PEER_STATE_DISCONNECTED)
- return;
-
- if (peer -> state != ENET_PEER_STATE_ZOMBIE &&
- peer -> state != ENET_PEER_STATE_DISCONNECTING)
- {
- enet_peer_reset_queues (peer);
-
- command.header.command = ENET_PROTOCOL_COMMAND_DISCONNECT | ENET_PROTOCOL_COMMAND_FLAG_UNSEQUENCED;
- command.header.channelID = 0xFF;
- command.disconnect.data = ENET_HOST_TO_NET_32 (data);
-
- enet_peer_queue_outgoing_command (peer, & command, NULL, 0, 0);
-
- enet_host_flush (peer -> host);
- }
-
- enet_peer_reset (peer);
-}
-
-/** Request a disconnection from a peer.
- @param peer peer to request a disconnection
- @param data data describing the disconnection
- @remarks An ENET_EVENT_DISCONNECT event will be generated by enet_host_service()
- once the disconnection is complete.
-*/
-void
-enet_peer_disconnect (ENetPeer * peer, enet_uint32 data)
-{
- ENetProtocol command;
-
- if (peer -> state == ENET_PEER_STATE_DISCONNECTING ||
- peer -> state == ENET_PEER_STATE_DISCONNECTED ||
- peer -> state == ENET_PEER_STATE_ACKNOWLEDGING_DISCONNECT ||
- peer -> state == ENET_PEER_STATE_ZOMBIE)
- return;
-
- enet_peer_reset_queues (peer);
-
- command.header.command = ENET_PROTOCOL_COMMAND_DISCONNECT;
- command.header.channelID = 0xFF;
- command.disconnect.data = ENET_HOST_TO_NET_32 (data);
-
- if (peer -> state == ENET_PEER_STATE_CONNECTED || peer -> state == ENET_PEER_STATE_DISCONNECT_LATER)
- command.header.command |= ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE;
- else
- command.header.command |= ENET_PROTOCOL_COMMAND_FLAG_UNSEQUENCED;
-
- enet_peer_queue_outgoing_command (peer, & command, NULL, 0, 0);
-
- if (peer -> state == ENET_PEER_STATE_CONNECTED || peer -> state == ENET_PEER_STATE_DISCONNECT_LATER)
- peer -> state = ENET_PEER_STATE_DISCONNECTING;
- else
- {
- enet_host_flush (peer -> host);
- enet_peer_reset (peer);
- }
-}
-
-/** Request a disconnection from a peer, but only after all queued outgoing packets are sent.
- @param peer peer to request a disconnection
- @param data data describing the disconnection
- @remarks An ENET_EVENT_DISCONNECT event will be generated by enet_host_service()
- once the disconnection is complete.
-*/
-void
-enet_peer_disconnect_later (ENetPeer * peer, enet_uint32 data)
-{
- if ((peer -> state == ENET_PEER_STATE_CONNECTED || peer -> state == ENET_PEER_STATE_DISCONNECT_LATER) &&
- ! (enet_list_empty (& peer -> outgoingReliableCommands) &&
- enet_list_empty (& peer -> outgoingUnreliableCommands) &&
- enet_list_empty (& peer -> sentReliableCommands)))
- {
- peer -> state = ENET_PEER_STATE_DISCONNECT_LATER;
- peer -> eventData = data;
- }
- else
- enet_peer_disconnect (peer, data);
-}
-
-ENetAcknowledgement *
-enet_peer_queue_acknowledgement (ENetPeer * peer, const ENetProtocol * command, enet_uint16 sentTime)
-{
- ENetAcknowledgement * acknowledgement;
-
- if (command -> header.channelID < peer -> channelCount)
- {
- ENetChannel * channel = & peer -> channels [command -> header.channelID];
- enet_uint16 reliableWindow = command -> header.reliableSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE,
- currentWindow = channel -> incomingReliableSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE;
-
- if (command -> header.reliableSequenceNumber < channel -> incomingReliableSequenceNumber)
- reliableWindow += ENET_PEER_RELIABLE_WINDOWS;
-
- if (reliableWindow >= currentWindow + ENET_PEER_FREE_RELIABLE_WINDOWS - 1 && reliableWindow <= currentWindow + ENET_PEER_FREE_RELIABLE_WINDOWS)
- return NULL;
- }
-
- acknowledgement = (ENetAcknowledgement *) enet_malloc (sizeof (ENetAcknowledgement));
- if (acknowledgement == NULL)
- return NULL;
-
- peer -> outgoingDataTotal += sizeof (ENetProtocolAcknowledge);
-
- acknowledgement -> sentTime = sentTime;
- acknowledgement -> command = * command;
-
- enet_list_insert (enet_list_end (& peer -> acknowledgements), acknowledgement);
-
- return acknowledgement;
-}
-
-void
-enet_peer_setup_outgoing_command (ENetPeer * peer, ENetOutgoingCommand * outgoingCommand)
-{
- ENetChannel * channel = & peer -> channels [outgoingCommand -> command.header.channelID];
-
- peer -> outgoingDataTotal += enet_protocol_command_size (outgoingCommand -> command.header.command) + outgoingCommand -> fragmentLength;
-
- if (outgoingCommand -> command.header.channelID == 0xFF)
- {
- ++ peer -> outgoingReliableSequenceNumber;
-
- outgoingCommand -> reliableSequenceNumber = peer -> outgoingReliableSequenceNumber;
- outgoingCommand -> unreliableSequenceNumber = 0;
- }
- else
- if (outgoingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE)
- {
- ++ channel -> outgoingReliableSequenceNumber;
- channel -> outgoingUnreliableSequenceNumber = 0;
-
- outgoingCommand -> reliableSequenceNumber = channel -> outgoingReliableSequenceNumber;
- outgoingCommand -> unreliableSequenceNumber = 0;
- }
- else
- if (outgoingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_FLAG_UNSEQUENCED)
- {
- ++ peer -> outgoingUnsequencedGroup;
-
- outgoingCommand -> reliableSequenceNumber = 0;
- outgoingCommand -> unreliableSequenceNumber = 0;
- }
- else
- {
- ++ channel -> outgoingUnreliableSequenceNumber;
-
- outgoingCommand -> reliableSequenceNumber = channel -> outgoingReliableSequenceNumber;
- outgoingCommand -> unreliableSequenceNumber = channel -> outgoingUnreliableSequenceNumber;
- }
-
- outgoingCommand -> sendAttempts = 0;
- outgoingCommand -> sentTime = 0;
- outgoingCommand -> roundTripTimeout = 0;
- outgoingCommand -> roundTripTimeoutLimit = 0;
- outgoingCommand -> command.header.reliableSequenceNumber = ENET_HOST_TO_NET_16 (outgoingCommand -> reliableSequenceNumber);
-
- if (outgoingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE)
- enet_list_insert (enet_list_end (& peer -> outgoingReliableCommands), outgoingCommand);
- else
- enet_list_insert (enet_list_end (& peer -> outgoingUnreliableCommands), outgoingCommand);
-}
-
-ENetOutgoingCommand *
-enet_peer_queue_outgoing_command (ENetPeer * peer, const ENetProtocol * command, ENetPacket * packet, enet_uint32 offset, enet_uint16 length)
-{
- ENetOutgoingCommand * outgoingCommand = (ENetOutgoingCommand *) enet_malloc (sizeof (ENetOutgoingCommand));
- if (outgoingCommand == NULL)
- return NULL;
-
- outgoingCommand -> command = * command;
- outgoingCommand -> fragmentOffset = offset;
- outgoingCommand -> fragmentLength = length;
- outgoingCommand -> packet = packet;
- if (packet != NULL)
- ++ packet -> referenceCount;
-
- enet_peer_setup_outgoing_command (peer, outgoingCommand);
-
- return outgoingCommand;
-}
-
-void
-enet_peer_dispatch_incoming_unreliable_commands (ENetPeer * peer, ENetChannel * channel)
-{
- ENetListIterator currentCommand;
-
- for (currentCommand = enet_list_begin (& channel -> incomingUnreliableCommands);
- currentCommand != enet_list_end (& channel -> incomingUnreliableCommands);
- currentCommand = enet_list_next (currentCommand))
- {
- ENetIncomingCommand * incomingCommand = (ENetIncomingCommand *) currentCommand;
-
- if ((incomingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_MASK) == ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE &&
- incomingCommand -> reliableSequenceNumber != channel -> incomingReliableSequenceNumber)
- break;
- }
-
- if (currentCommand == enet_list_begin (& channel -> incomingUnreliableCommands))
- return;
-
- enet_list_move (enet_list_end (& peer -> dispatchedCommands), enet_list_begin (& channel -> incomingUnreliableCommands), enet_list_previous (currentCommand));
-
- if (! peer -> needsDispatch)
- {
- enet_list_insert (enet_list_end (& peer -> host -> dispatchQueue), & peer -> dispatchList);
-
- peer -> needsDispatch = 1;
- }
-}
-
-void
-enet_peer_dispatch_incoming_reliable_commands (ENetPeer * peer, ENetChannel * channel)
-{
- ENetListIterator currentCommand;
-
- for (currentCommand = enet_list_begin (& channel -> incomingReliableCommands);
- currentCommand != enet_list_end (& channel -> incomingReliableCommands);
- currentCommand = enet_list_next (currentCommand))
- {
- ENetIncomingCommand * incomingCommand = (ENetIncomingCommand *) currentCommand;
-
- if (incomingCommand -> fragmentsRemaining > 0 ||
- incomingCommand -> reliableSequenceNumber != (enet_uint16) (channel -> incomingReliableSequenceNumber + 1))
- break;
-
- channel -> incomingReliableSequenceNumber = incomingCommand -> reliableSequenceNumber;
-
- if (incomingCommand -> fragmentCount > 0)
- channel -> incomingReliableSequenceNumber += incomingCommand -> fragmentCount - 1;
- }
-
- if (currentCommand == enet_list_begin (& channel -> incomingReliableCommands))
- return;
-
- enet_list_move (enet_list_end (& peer -> dispatchedCommands), enet_list_begin (& channel -> incomingReliableCommands), enet_list_previous (currentCommand));
-
- if (! peer -> needsDispatch)
- {
- enet_list_insert (enet_list_end (& peer -> host -> dispatchQueue), & peer -> dispatchList);
-
- peer -> needsDispatch = 1;
- }
-
- enet_peer_dispatch_incoming_unreliable_commands (peer, channel);
-}
-
-ENetIncomingCommand *
-enet_peer_queue_incoming_command (ENetPeer * peer, const ENetProtocol * command, ENetPacket * packet, enet_uint32 fragmentCount)
-{
- static ENetIncomingCommand dummyCommand;
-
- ENetChannel * channel = & peer -> channels [command -> header.channelID];
- enet_uint32 unreliableSequenceNumber = 0, reliableSequenceNumber;
- enet_uint16 reliableWindow, currentWindow;
- ENetIncomingCommand * incomingCommand;
- ENetListIterator currentCommand;
-
- if (peer -> state == ENET_PEER_STATE_DISCONNECT_LATER)
- goto freePacket;
-
- if ((command -> header.command & ENET_PROTOCOL_COMMAND_MASK) != ENET_PROTOCOL_COMMAND_SEND_UNSEQUENCED)
- {
- reliableSequenceNumber = command -> header.reliableSequenceNumber;
- reliableWindow = reliableSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE;
- currentWindow = channel -> incomingReliableSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE;
-
- if (reliableSequenceNumber < channel -> incomingReliableSequenceNumber)
- reliableWindow += ENET_PEER_RELIABLE_WINDOWS;
-
- if (reliableWindow < currentWindow || reliableWindow >= currentWindow + ENET_PEER_FREE_RELIABLE_WINDOWS - 1)
- goto freePacket;
- }
-
- switch (command -> header.command & ENET_PROTOCOL_COMMAND_MASK)
- {
- case ENET_PROTOCOL_COMMAND_SEND_FRAGMENT:
- case ENET_PROTOCOL_COMMAND_SEND_RELIABLE:
- if (reliableSequenceNumber == channel -> incomingReliableSequenceNumber)
- goto freePacket;
-
- for (currentCommand = enet_list_previous (enet_list_end (& channel -> incomingReliableCommands));
- currentCommand != enet_list_end (& channel -> incomingReliableCommands);
- currentCommand = enet_list_previous (currentCommand))
- {
- incomingCommand = (ENetIncomingCommand *) currentCommand;
-
- if (reliableSequenceNumber >= channel -> incomingReliableSequenceNumber)
- {
- if (incomingCommand -> reliableSequenceNumber < channel -> incomingReliableSequenceNumber)
- continue;
- }
- else
- if (incomingCommand -> reliableSequenceNumber >= channel -> incomingReliableSequenceNumber)
- break;
-
- if (incomingCommand -> reliableSequenceNumber <= reliableSequenceNumber)
- {
- if (incomingCommand -> reliableSequenceNumber < reliableSequenceNumber)
- break;
-
- goto freePacket;
- }
- }
- break;
-
- case ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE:
- unreliableSequenceNumber = ENET_NET_TO_HOST_16 (command -> sendUnreliable.unreliableSequenceNumber);
-
- for (currentCommand = enet_list_previous (enet_list_end (& channel -> incomingUnreliableCommands));
- currentCommand != enet_list_end (& channel -> incomingUnreliableCommands);
- currentCommand = enet_list_previous (currentCommand))
- {
- incomingCommand = (ENetIncomingCommand *) currentCommand;
-
- if ((incomingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_MASK) != ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE)
- continue;
-
- if (reliableSequenceNumber >= channel -> incomingReliableSequenceNumber)
- {
- if (incomingCommand -> reliableSequenceNumber < channel -> incomingReliableSequenceNumber)
- continue;
- }
- else
- if (incomingCommand -> reliableSequenceNumber >= channel -> incomingReliableSequenceNumber)
- break;
-
- if (incomingCommand -> reliableSequenceNumber < reliableSequenceNumber)
- break;
-
- if (incomingCommand -> reliableSequenceNumber > reliableSequenceNumber)
- continue;
-
- if (incomingCommand -> unreliableSequenceNumber <= unreliableSequenceNumber)
- {
- if (incomingCommand -> unreliableSequenceNumber < unreliableSequenceNumber)
- break;
-
- goto freePacket;
- }
- }
- break;
-
- case ENET_PROTOCOL_COMMAND_SEND_UNSEQUENCED:
- currentCommand = enet_list_end (& channel -> incomingUnreliableCommands);
- break;
-
- default:
- goto freePacket;
- }
-
- incomingCommand = (ENetIncomingCommand *) enet_malloc (sizeof (ENetIncomingCommand));
- if (incomingCommand == NULL)
- goto notifyError;
-
- incomingCommand -> reliableSequenceNumber = command -> header.reliableSequenceNumber;
- incomingCommand -> unreliableSequenceNumber = unreliableSequenceNumber & 0xFFFF;
- incomingCommand -> command = * command;
- incomingCommand -> fragmentCount = fragmentCount;
- incomingCommand -> fragmentsRemaining = fragmentCount;
- incomingCommand -> packet = packet;
- incomingCommand -> fragments = NULL;
-
- if (fragmentCount > 0)
- {
- incomingCommand -> fragments = (enet_uint32 *) enet_malloc ((fragmentCount + 31) / 32 * sizeof (enet_uint32));
- if (incomingCommand -> fragments == NULL)
- {
- enet_free (incomingCommand);
-
- goto notifyError;
- }
- memset (incomingCommand -> fragments, 0, (fragmentCount + 31) / 32 * sizeof (enet_uint32));
- }
-
- if (packet != NULL)
- ++ packet -> referenceCount;
-
- enet_list_insert (enet_list_next (currentCommand), incomingCommand);
-
- switch (command -> header.command & ENET_PROTOCOL_COMMAND_MASK)
- {
- case ENET_PROTOCOL_COMMAND_SEND_FRAGMENT:
- case ENET_PROTOCOL_COMMAND_SEND_RELIABLE:
- enet_peer_dispatch_incoming_reliable_commands (peer, channel);
- break;
-
- default:
- enet_peer_dispatch_incoming_unreliable_commands (peer, channel);
- break;
- }
-
- return incomingCommand;
-
-freePacket:
- if (fragmentCount > 0)
- goto notifyError;
-
- if (packet != NULL && packet -> referenceCount == 0)
- enet_packet_destroy (packet);
-
- return & dummyCommand;
-
-notifyError:
- if (packet != NULL && packet -> referenceCount == 0)
- enet_packet_destroy (packet);
-
- return NULL;
-}
-
-/** @} */