public void SetupOutgoingCommand(OutgoingCommand outgoingCommand) { OutgoingDataTotal += (uint)outgoingCommand.Command.Size + outgoingCommand.FragmentLength; if (outgoingCommand.Command.ChannelID == 0xFF) { OutgoingReliableSequenceNumber++; outgoingCommand.ReliableSequenceNumber = OutgoingReliableSequenceNumber; outgoingCommand.UnreliableSequenceNumber = 0; } else { var channel = Channels[outgoingCommand.Command.ChannelID]; if (outgoingCommand.Command.Flags.HasFlag(ProtocolFlag.ACKNOWLEDGE)) { channel.OutgoingReliableSequenceNumber++; channel.OutgoingUnreliableSequenceNumber = 0; outgoingCommand.ReliableSequenceNumber = channel.OutgoingReliableSequenceNumber; outgoingCommand.UnreliableSequenceNumber = 0; } else if (outgoingCommand.Command.Flags.HasFlag(ProtocolFlag.UNSEQUENCED)) { 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.ReliableSequenceNumber = outgoingCommand.ReliableSequenceNumber; if (outgoingCommand.Command.Flags.HasFlag(ProtocolFlag.ACKNOWLEDGE)) { OutgoingReliableCommands.End.Insert(outgoingCommand.Node); } else { OutgoingUnreliableCommands.End.Insert(outgoingCommand.Node); } }
public OutgoingCommand QueueOutgoingCommand(Protocol command, Packet packet, uint offset, ushort length) { var outgoingCommand = new OutgoingCommand { Command = command, FragmentOffset = offset, FragmentLength = length, Packet = packet, }; SetupOutgoingCommand(outgoingCommand); return(outgoingCommand); }
public int Send(byte channelID, Packet packet) { if (State != PeerState.CONNECTED || channelID >= ChannelCount) { return(-1); } var channel = Channels[channelID]; uint fragmentLength = MTU - Host.Version.MaxHeaderSizeSend - Protocol.Send.Fragment.SIZE; if (packet.DataLength > fragmentLength) { ushort startSequenceNumber = (ushort)(channel.OutgoingReliableSequenceNumber + 1); uint fragmentCount = (packet.DataLength + fragmentLength - 1u) / fragmentLength; uint fragmentNumber = 0; uint fragmentOffset = 0; for (; fragmentOffset < packet.DataLength; fragmentOffset += fragmentLength, fragmentNumber++) { if (packet.DataLength - fragmentOffset < fragmentLength) { fragmentLength = packet.DataLength - fragmentOffset; } var fragment = new OutgoingCommand { FragmentOffset = fragmentOffset, FragmentLength = (ushort)fragmentLength, Packet = packet, Command = new Protocol.Send.Fragment { Flags = ProtocolFlag.ACKNOWLEDGE, ChannelID = channelID, StartSequenceNumber = startSequenceNumber, DataLength = (ushort)fragmentLength, FragmentCount = fragmentCount, FragmentNumber = fragmentNumber, TotalLength = packet.DataLength, FragmentOffset = fragmentOffset, } }; SetupOutgoingCommand(fragment); } return(0); } Protocol command; if (packet.Flags.HasFlag(PacketFlags.RELIABLE)) { command = new Protocol.Send.Reliable { ChannelID = channelID, Flags = ProtocolFlag.ACKNOWLEDGE, DataLength = (ushort)packet.DataLength, }; } else if (packet.Flags.HasFlag(PacketFlags.UNSEQUENCED)) { command = new Protocol.Send.Unsequenced { ChannelID = channelID, Flags = ProtocolFlag.UNSEQUENCED, UnsequencedGroup = (ushort)(OutgoingUnsequencedGroup + 1), DataLength = (ushort)packet.DataLength, }; } else if (channel.OutgoingReliableSequenceNumber >= 0xFFFFu) { command = new Protocol.Send.Reliable { ChannelID = channelID, Flags = ProtocolFlag.ACKNOWLEDGE, DataLength = (ushort)packet.DataLength, }; } else { command = new Protocol.Send.Unreliable { ChannelID = channelID, UnreliableSequenceNumber = (ushort)(channel.OutgoingUnreliableSequenceNumber + 1), DataLength = (ushort)packet.DataLength, }; } if (QueueOutgoingCommand(command, packet, 0, (ushort)packet.DataLength) == null) { return(-1); } return(0); }
private static ProtocolCommand RemoveSentReliableCommand(Peer peer, ushort reliableSequenceNumber, byte channelID) { LList <OutgoingCommand> .Node currentCommand; OutgoingCommand outgoingCommand = null; bool wasSent = true; for (currentCommand = peer.SentReliableCommands.Begin; currentCommand != peer.SentReliableCommands.End; currentCommand = currentCommand.Next) { outgoingCommand = currentCommand.Value; if (outgoingCommand.ReliableSequenceNumber == reliableSequenceNumber && outgoingCommand.Command.ChannelID == channelID) { break; } } if (currentCommand == peer.SentReliableCommands.End) { for (currentCommand = peer.OutgoingReliableCommands.Begin; currentCommand != peer.OutgoingReliableCommands.End; currentCommand = currentCommand.Next) { outgoingCommand = currentCommand.Value; if (outgoingCommand.SendAttempts < 1) { return(ProtocolCommand.NONE); } if (outgoingCommand.ReliableSequenceNumber == reliableSequenceNumber && outgoingCommand.Command.ChannelID == channelID) { break; } } if (currentCommand == peer.OutgoingReliableCommands.End) { return(ProtocolCommand.NONE); } wasSent = false; } if (channelID < peer.ChannelCount) { var channel = peer.Channels[channelID]; ushort reliableWindow = (ushort)(reliableSequenceNumber / Peer.RELIABLE_WINDOW_SIZE); if (channel.ReliableWindows[reliableWindow] > 0) { channel.ReliableWindows[reliableWindow]--; if (channel.ReliableWindows[reliableWindow] == 0) { channel.UsedReliableWindows &= (ushort)~(1u << reliableWindow); } } } var commandNumber = outgoingCommand.Command.Command; outgoingCommand.Node.Remove(); if (outgoingCommand.Packet != null) { if (wasSent) { peer.ReliableDataInTransit -= outgoingCommand.FragmentLength; } } if (peer.SentReliableCommands.Empty) { return(commandNumber); } outgoingCommand = peer.SentReliableCommands.Begin.Value; peer.NextTimeout = outgoingCommand.SentTime + outgoingCommand.RoundTripTimeout; return(commandNumber); }