support for ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT

1.3.2 release prep
This commit is contained in:
eihrul
2011-05-31 07:48:27 +00:00
parent 33e2fc6201
commit f38c177db0
9 changed files with 258 additions and 34 deletions
+133
View File
@@ -23,6 +23,7 @@ static size_t commandSizes [ENET_PROTOCOL_COMMAND_COUNT] =
sizeof (ENetProtocolSendUnsequenced),
sizeof (ENetProtocolBandwidthLimit),
sizeof (ENetProtocolThrottleConfigure),
sizeof (ENetProtocolSendFragment)
};
size_t
@@ -319,6 +320,7 @@ enet_protocol_handle_connect (ENetHost * host, ENetProtocolHeader * header, ENet
channel -> outgoingReliableSequenceNumber = 0;
channel -> outgoingUnreliableSequenceNumber = 0;
channel -> incomingReliableSequenceNumber = 0;
channel -> incomingUnreliableSequenceNumber = 0;
enet_list_clear (& channel -> incomingReliableCommands);
enet_list_clear (& channel -> incomingUnreliableCommands);
@@ -605,6 +607,132 @@ enet_protocol_handle_send_fragment (ENetHost * host, ENetPeer * peer, const ENet
return 0;
}
static int
enet_protocol_handle_send_unreliable_fragment (ENetHost * host, ENetPeer * peer, const ENetProtocol * command, enet_uint8 ** currentData)
{
enet_uint32 fragmentNumber,
fragmentCount,
fragmentOffset,
fragmentLength,
reliableSequenceNumber,
startSequenceNumber,
totalLength;
enet_uint16 reliableWindow, currentWindow;
ENetChannel * channel;
ENetListIterator currentCommand;
ENetIncomingCommand * startCommand = NULL;
if (command -> header.channelID >= peer -> channelCount ||
(peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER))
return -1;
fragmentLength = ENET_NET_TO_HOST_16 (command -> sendFragment.dataLength);
* currentData += fragmentLength;
if (* currentData > & host -> receivedData [host -> receivedDataLength])
return -1;
channel = & peer -> channels [command -> header.channelID];
reliableSequenceNumber = command -> header.reliableSequenceNumber;
startSequenceNumber = ENET_NET_TO_HOST_16 (command -> sendFragment.startSequenceNumber);
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)
return 0;
if (reliableSequenceNumber == channel -> incomingReliableSequenceNumber &&
startSequenceNumber <= channel -> incomingUnreliableSequenceNumber)
return 0;
fragmentNumber = ENET_NET_TO_HOST_32 (command -> sendFragment.fragmentNumber);
fragmentCount = ENET_NET_TO_HOST_32 (command -> sendFragment.fragmentCount);
fragmentOffset = ENET_NET_TO_HOST_32 (command -> sendFragment.fragmentOffset);
totalLength = ENET_NET_TO_HOST_32 (command -> sendFragment.totalLength);
if (fragmentOffset >= totalLength ||
fragmentOffset + fragmentLength > totalLength ||
fragmentNumber >= fragmentCount)
return -1;
for (currentCommand = enet_list_previous (enet_list_end (& channel -> incomingUnreliableCommands));
currentCommand != enet_list_end (& channel -> incomingUnreliableCommands);
currentCommand = enet_list_previous (currentCommand))
{
ENetIncomingCommand * incomingCommand = (ENetIncomingCommand *) currentCommand;
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 <= startSequenceNumber)
{
if (incomingCommand -> unreliableSequenceNumber < startSequenceNumber)
break;
if ((incomingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_MASK) != ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE_FRAGMENT ||
totalLength != incomingCommand -> packet -> dataLength ||
fragmentCount != incomingCommand -> fragmentCount)
return -1;
startCommand = incomingCommand;
break;
}
}
if (startCommand == NULL)
{
ENetProtocol hostCommand = * command;
ENetPacket * packet = enet_packet_create (NULL, totalLength, ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT);
if (packet == NULL)
return -1;
hostCommand.sendFragment.startSequenceNumber = startSequenceNumber;
hostCommand.sendFragment.dataLength = fragmentLength;
hostCommand.sendFragment.fragmentNumber = fragmentNumber;
hostCommand.sendFragment.fragmentCount = fragmentCount;
hostCommand.sendFragment.fragmentOffset = fragmentOffset;
hostCommand.sendFragment.totalLength = totalLength;
startCommand = enet_peer_queue_incoming_command (peer, & hostCommand, packet, fragmentCount);
if (startCommand == NULL)
return -1;
}
if ((startCommand -> fragments [fragmentNumber / 32] & (1 << (fragmentNumber % 32))) == 0)
{
-- startCommand -> fragmentsRemaining;
startCommand -> fragments [fragmentNumber / 32] |= (1 << (fragmentNumber % 32));
if (fragmentOffset + fragmentLength > startCommand -> packet -> dataLength)
fragmentLength = startCommand -> packet -> dataLength - fragmentOffset;
memcpy (startCommand -> packet -> data + fragmentOffset,
(enet_uint8 *) command + sizeof (ENetProtocolSendFragment),
fragmentLength);
if (startCommand -> fragmentsRemaining <= 0)
enet_peer_dispatch_incoming_unreliable_commands (peer, channel);
}
return 0;
}
static int
enet_protocol_handle_ping (ENetHost * host, ENetPeer * peer, const ENetProtocol * command)
{
@@ -986,6 +1114,11 @@ enet_protocol_handle_incoming_commands (ENetHost * host, ENetEvent * event)
goto commandError;
break;
case ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE_FRAGMENT:
if (enet_protocol_handle_send_unreliable_fragment (host, peer, command, & currentData))
goto commandError;
break;
default:
goto commandError;
}