示例#1
0
        public IncomingCommand QueueIncomingCommand(Protocol command, Packet packet, uint fragmentCount)
        {
            Channel channel = command.ChannelID == 0xFF ? null : Channels[command.ChannelID];

            var notifyError = fragmentCount > 0 ? null : new IncomingCommand();

            if (State == PeerState.DISCONNECT_LATER)
            {
                return(notifyError);
            }

            uint unreliableSequenceNumber = 0;
            uint reliableSequenceNumber   = 0;

            if (!(command is Protocol.Send.Unsequenced))
            {
                reliableSequenceNumber = command.ReliableSequenceNumber;
                ushort reliableWindow = (ushort)(reliableSequenceNumber / RELIABLE_WINDOW_SIZE);
                ushort currentWindow  = (ushort)(channel.IncomingReliableSequenceNumber / RELIABLE_WINDOW_SIZE);

                if (reliableSequenceNumber < channel.IncomingReliableSequenceNumber)
                {
                    reliableWindow += RELIABLE_WINDOWS;
                }

                if (reliableWindow < currentWindow || reliableWindow >= currentWindow + FREE_RELIABLE_WINDOWS - 1u)
                {
                    return(notifyError);
                }
            }


            LList <IncomingCommand> .Node currentCommand;
            IncomingCommand incomingCommand;

            switch (command)
            {
            case Protocol.Send.Fragment _:
            case Protocol.Send.Reliable _:
                if (reliableSequenceNumber == channel.IncomingReliableSequenceNumber)
                {
                    return(notifyError);
                }

                for (currentCommand = channel.IncomingReliableCommands.End.Prev;
                     currentCommand != channel.IncomingReliableCommands.End;
                     currentCommand = currentCommand.Prev)
                {
                    incomingCommand = currentCommand.Value;

                    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;
                        }

                        return(notifyError);
                    }
                }
                break;

            case Protocol.Send.Unreliable sendUnreliable:
                unreliableSequenceNumber = sendUnreliable.UnreliableSequenceNumber;

                if (reliableSequenceNumber == channel.IncomingReliableSequenceNumber &&
                    unreliableSequenceNumber <= channel.IncomingUnreliableSequenceNumber)
                {
                    return(notifyError);
                }

                for (currentCommand = channel.IncomingUnreliableCommands.End.Prev;
                     currentCommand != channel.IncomingUnreliableCommands.End;
                     currentCommand = currentCommand.Prev)
                {
                    incomingCommand = currentCommand.Value;

                    if (!(incomingCommand.Command is Protocol.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;
                        }

                        return(notifyError);
                    }
                }

                break;

            case Protocol.Send.Unsequenced _:
                currentCommand = channel.IncomingUnreliableCommands.End;
                break;

            default:
                return(notifyError);
            }

            incomingCommand = new IncomingCommand
            {
                ReliableSequenceNumber   = command.ReliableSequenceNumber,
                UnreliableSequenceNumber = (ushort)(unreliableSequenceNumber & 0xFFFF),
                Command            = command,
                FragmentCount      = fragmentCount,
                FragmentsRemaining = fragmentCount,
                Packet             = packet,
                Fragments          = new BitArray((int)fragmentCount), // CHECKME: (fragmentCount + 31) / 32
            };

            currentCommand.Next.Insert(incomingCommand.Node);

            switch (command)
            {
            case Protocol.Send.Fragment _:
            case Protocol.Send.Reliable _:
                DispatchIncomingReliableCommands(channel);
                break;

            default:
                DispatchIncomingUnreliableCommands(channel);
                break;
            }

            return(incomingCommand);
        }
示例#2
0
        private int HandleSendFragment(Peer peer, Protocol.Send.Fragment command, Buffer buffer)
        {
            if (command.ChannelID >= peer.ChannelCount)
            {
                return(-1);
            }

            if (peer.State != PeerState.CONNECTED && peer.State != PeerState.DISCONNECT_LATER)
            {
                return(-1);
            }

            if (command.DataLength > buffer.BytesLeft)
            {
                return(-1);
            }

            uint   fragmentLength      = command.DataLength;
            var    channel             = peer.Channels[command.ChannelID];
            uint   startSequenceNumber = command.StartSequenceNumber;
            ushort startWindow         = (ushort)(startSequenceNumber / Peer.RELIABLE_WINDOW_SIZE);
            ushort currentWindow       = (ushort)(channel.IncomingReliableSequenceNumber / Peer.RELIABLE_WINDOW_SIZE);

            if (startSequenceNumber < channel.IncomingReliableSequenceNumber)
            {
                startWindow += Peer.RELIABLE_WINDOWS;
            }

            if (startWindow < currentWindow || startWindow >= currentWindow + Peer.FREE_RELIABLE_WINDOWS - 1)
            {
                return(0);
            }

            uint fragmentNumber = command.FragmentNumber;
            uint fragmentCount  = command.FragmentCount;
            uint fragmentOffset = command.FragmentOffset;
            uint totalLength    = command.TotalLength;

            if (fragmentOffset >= totalLength ||
                fragmentOffset + fragmentLength > totalLength ||
                fragmentNumber >= fragmentCount)
            {
                return(-1);
            }


            IncomingCommand startCommand = null;

            for (var currentCommand = channel.IncomingReliableCommands.End.Prev;
                 currentCommand != channel.IncomingReliableCommands.End;
                 currentCommand = currentCommand.Prev)
            {
                var incomingCommand = currentCommand.Value;

                if (startSequenceNumber >= channel.IncomingReliableSequenceNumber)
                {
                    if (incomingCommand.ReliableSequenceNumber < channel.IncomingReliableSequenceNumber)
                    {
                        continue;
                    }
                }
                else if (incomingCommand.ReliableSequenceNumber >= channel.IncomingReliableSequenceNumber)
                {
                    break;
                }

                if (incomingCommand.ReliableSequenceNumber <= startSequenceNumber)
                {
                    if (incomingCommand.ReliableSequenceNumber < startSequenceNumber)
                    {
                        break;
                    }

                    if (!(incomingCommand.Command is Protocol.Send.Fragment) ||
                        totalLength != incomingCommand.Packet.DataLength ||
                        fragmentCount != incomingCommand.FragmentCount)
                    {
                        return(-1);
                    }

                    startCommand = incomingCommand;
                    break;
                }
            }

            if (startCommand == null)
            {
                var packet      = new Packet(totalLength, PacketFlags.RELIABLE);
                var hostCommand = command;

                hostCommand.ReliableSequenceNumber = (ushort)startSequenceNumber;
                hostCommand.StartSequenceNumber    = (ushort)startSequenceNumber;
                hostCommand.DataLength             = (ushort)fragmentLength;
                hostCommand.FragmentNumber         = fragmentNumber;
                hostCommand.FragmentCount          = fragmentCount;
                hostCommand.FragmentOffset         = fragmentOffset;
                hostCommand.TotalLength            = totalLength;

                startCommand = peer.QueueIncomingCommand(hostCommand, packet, fragmentCount);
            }

            if (!startCommand.Fragments[(int)fragmentNumber])
            {
                startCommand.FragmentsRemaining--;

                startCommand.Fragments[(int)fragmentNumber] = true;

                if (fragmentOffset + fragmentLength > startCommand.Packet.DataLength)
                {
                    fragmentLength = startCommand.Packet.DataLength - fragmentOffset;
                }

                buffer.ReadBytes(startCommand.Packet.Data, fragmentOffset, fragmentLength);

                if (startCommand.FragmentsRemaining <= 0)
                {
                    peer.DispatchIncomingReliableCommands(channel);
                }
            }

            return(0);
        }