Exemple #1
0
        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);
            }
        }
Exemple #2
0
        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);
        }
Exemple #3
0
        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);
        }
Exemple #4
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);
        }