diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs index 780e8f889c..79f5fe614e 100755 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs @@ -989,49 +989,96 @@ namespace OpenSim.Region.ClientStack.LindenUDP SendPacketFinal(outgoingPacket); } + static private readonly byte[] PacketAckHeader = new byte[] { + 0, + 0, 0, 0, 0, // sequence number + 0, // extra + 0xff, 0xff, 0xff, 0xfb // ID 65531 (low frequency bigendian) + }; + public void SendAcks(LLUDPClient udpClient) { + if(udpClient.PendingAcks.Count == 0) + return; + + UDPPacketBuffer buf = GetNewUDPBuffer(udpClient.RemoteEndPoint); + Buffer.BlockCopy(PacketAckHeader, 0, buf.Data, 0, 10); + byte[] data = buf.Data; + // count at position 10 + int pos = 11; + uint ack; - - if (udpClient.PendingAcks.Dequeue(out ack)) + int count = 0; + while (udpClient.PendingAcks.Dequeue(out ack)) { - List blocks = new List(); - PacketAckPacket.PacketsBlock block = new PacketAckPacket.PacketsBlock(); - block.ID = ack; - blocks.Add(block); + Utils.UIntToBytes(ack, data, pos); pos += 4; + ++count; - while (udpClient.PendingAcks.Dequeue(out ack)) + if (count == 255) { - block = new PacketAckPacket.PacketsBlock(); - block.ID = ack; - blocks.Add(block); + data[10] = 255; + buf.DataLength = pos; + SendUDPPacket(udpClient, buf, ThrottleOutPacketType.Unknown, null, false, false); + + buf = GetNewUDPBuffer(udpClient.RemoteEndPoint); + Buffer.BlockCopy(PacketAckHeader, 0, buf.Data, 0, 10); + data = buf.Data; + pos = 11; + count = 0; } - - PacketAckPacket packet = new PacketAckPacket(); - packet.Header.Reliable = false; - packet.Packets = blocks.ToArray(); - - SendPacket(udpClient, packet, ThrottleOutPacketType.Unknown, true, null); + } + if (count > 0) + { + data[10] = (byte)count; + buf.DataLength = pos; + SendUDPPacket(udpClient, buf, ThrottleOutPacketType.Unknown, null, false, false); } } + static private readonly byte[] StartPingCheckHeader = new byte[] { + 0, + 0, 0, 0, 0, // sequence number + 0, // extra + 1 // ID 1 (high frequency) + }; + public void SendPing(LLUDPClient udpClient) { - StartPingCheckPacket pc = (StartPingCheckPacket)PacketPool.Instance.GetPacket(PacketType.StartPingCheck); + UDPPacketBuffer buf = GetNewUDPBuffer(udpClient.RemoteEndPoint); + Buffer.BlockCopy(StartPingCheckHeader, 0, buf.Data, 0, 7); + byte[] data = buf.Data; - pc.PingID.PingID = (byte)udpClient.CurrentPingSequence++; - // We *could* get OldestUnacked, but it would hurt performance and not provide any benefit - pc.PingID.OldestUnacked = 0; + data[7] = udpClient.CurrentPingSequence++; + // older seq number of our un ack packets, so viewers could clean deduplication lists TODO + //Utils.UIntToBytes(0, data, 8); + data[8] = 0; + data[9] = 0; + data[10] = 0; + data[11] = 0; + + buf.DataLength = 12; + SendUDPPacket(udpClient, buf, ThrottleOutPacketType.Unknown, null, false, false); - SendPacket(udpClient, pc, ThrottleOutPacketType.Unknown, false, null); udpClient.m_lastStartpingTimeMS = Util.EnvironmentTickCount(); } + static private readonly byte[] CompletePingCheckHeader = new byte[] { + 0, + 0, 0, 0, 0, // sequence number + 0, // extra + 2 // ID 1 (high frequency) + }; + public void CompletePing(LLUDPClient udpClient, byte pingID) { - CompletePingCheckPacket completePing = new CompletePingCheckPacket(); - completePing.PingID.PingID = pingID; - SendPacket(udpClient, completePing, ThrottleOutPacketType.Unknown, false, null); + UDPPacketBuffer buf = GetNewUDPBuffer(udpClient.RemoteEndPoint); + Buffer.BlockCopy(CompletePingCheckHeader, 0, buf.Data, 0, 7); + byte[] data = buf.Data; + + data[7] = pingID; + + buf.DataLength = 8; + SendUDPPacket(udpClient, buf, ThrottleOutPacketType.Unknown, null, false, false); } public void HandleUnacked(LLClientView client) @@ -1121,8 +1168,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP int dataLength = buffer.DataLength; - // NOTE: I'm seeing problems with some viewers when ACKs are appended to zerocoded packets so I've disabled that here - if (!isZerocoded && !isResend && outgoingPacket.UnackedMethod == null) + // only append acks on plain reliable messages + if (flags == Helpers.MSG_RELIABLE && outgoingPacket.UnackedMethod == null) { // Keep appending ACKs until there is no room left in the buffer or there are // no more ACKs to append