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