예제 #1
0
        private int HandleSendUnsequenced(Peer peer, Protocol.Send.Unsequenced 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 unsequencedGroup = command.UnsequencedGroup;
            uint index            = unsequencedGroup % Peer.UNSEQUENCED_WINDOW_SIZE;

            if (unsequencedGroup < peer.IncomingUnsequencedGroup)
            {
                unsequencedGroup += 0x10000u;
            }

            if (unsequencedGroup >= (uint)peer.IncomingUnsequencedGroup + Peer.FREE_UNSEQUENCED_WINDOWS * Peer.UNSEQUENCED_WINDOW_SIZE)
            {
                return(0);
            }

            unsequencedGroup &= 0xFFFFu;

            if (unsequencedGroup - index != peer.IncomingUnsequencedGroup)
            {
                peer.IncomingUnsequencedGroup = (ushort)(unsequencedGroup - index);

                peer.UnsequencedWindow.SetAll(false);
            }
            else if (peer.UnsequencedWindow[(int)index])
            {
                return(0);
            }

            var packet = new Packet(command.DataLength, PacketFlags.UNSEQUENCED);

            buffer.ReadBytes(packet.Data, 0, command.DataLength);

            if (peer.QueueIncomingCommand(command, packet, 0) == null)
            {
                return(-1);
            }

            peer.UnsequencedWindow[(int)index] = true;

            return(0);
        }
예제 #2
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);
        }