diff options
Diffstat (limited to 'src/enet/peer.c')
-rw-r--r-- | src/enet/peer.c | 816 |
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; -} - -/** @} */ |