From b56eb2fe63a3bc1aaa954a24c46a1725d5bb704d Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Wed, 20 Feb 2019 03:05:23 +0000 Subject: estate kick now just kill user connection if on same region. The teleport home we did, does not make much sense, and would need more work anyways --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) (limited to 'OpenSim/Region/ClientStack') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index b7d5a80..943be07 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -1677,8 +1677,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP public void SendKillObject(List localIDs) { - // foreach (uint id in localIDs) - // m_log.DebugFormat("[CLIENT]: Sending KillObjectPacket to {0} for {1} in {2}", Name, id, regionHandle); + // foreach (uint id in localIDs) + // m_log.DebugFormat("[CLIENT]: Sending KillObjectPacket to {0} for {1} in {2}", Name, id, regionHandle); // remove pending entities to reduce looping chances. lock (m_entityProps.SyncRoot) @@ -1702,10 +1702,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP if(++nsent >= 200) { - kill.Header.Reliable = true; - kill.Header.Zerocoded = true; OutPacket(kill, ThrottleOutPacketType.Task); - perpacket = localIDs.Count - i - 1; if(perpacket == 0) break; @@ -1720,8 +1717,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP if(nsent != 0) { - kill.Header.Reliable = true; - kill.Header.Zerocoded = true; OutPacket(kill, ThrottleOutPacketType.Task); } } @@ -10047,7 +10042,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP UUID.TryParse(Utils.BytesToString(messagePacket.ParamList[1].Parameter), out Prey); - OnEstateTeleportOneUserHomeRequest(this, invoice, SenderID, Prey); + OnEstateTeleportOneUserHomeRequest(this, invoice, SenderID, Prey, false); } return true; case "teleporthomeallusers": @@ -10195,7 +10190,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP UUID.TryParse(Utils.BytesToString(messagePacket.ParamList[0].Parameter), out Prey); - OnEstateTeleportOneUserHomeRequest(this, invoice, SenderID, Prey); + OnEstateTeleportOneUserHomeRequest(this, invoice, SenderID, Prey, true); } return true; -- cgit v1.1 From d01165818dad7bd81aed07fa983951fecc5a80cd Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Mon, 25 Feb 2019 21:46:23 +0000 Subject: change UDPPacketBuffer pools (does waste a bit of memory) --- .../Region/ClientStack/Linden/UDP/LLClientView.cs | 8 - .../Region/ClientStack/Linden/UDP/LLUDPClient.cs | 23 +-- .../Region/ClientStack/Linden/UDP/LLUDPServer.cs | 212 +++++---------------- .../ClientStack/Linden/UDP/LLUDPServerCommands.cs | 37 ---- .../ClientStack/Linden/UDP/OpenSimUDPBase.cs | 197 +++++++++---------- .../Linden/UDP/UnackedPacketCollection.cs | 2 + 6 files changed, 156 insertions(+), 323 deletions(-) (limited to 'OpenSim/Region/ClientStack') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 943be07..3cb9388 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -12555,14 +12555,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// provide your own method. protected void OutPacket(Packet packet, ThrottleOutPacketType throttlePacketType, bool doAutomaticSplitting, UnackedPacketMethod method) { - -/* this is causing packet loss for some reason - if(!m_udpClient.IsConnected) - { - PacketPool.Instance.ReturnPacket(packet); - return; - } -*/ if (m_outPacketsToDrop != null) { if (m_outPacketsToDrop.Contains(packet.Type.ToString())) diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs index 439621a..bc75d82 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs @@ -120,7 +120,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// Circuit code that this client is connected on public readonly uint CircuitCode; /// Sequence numbers of packets we've received (for duplicate checking) - public IncomingPacketHistoryCollection PacketArchive = new IncomingPacketHistoryCollection(200); + public IncomingPacketHistoryCollection PacketArchive = new IncomingPacketHistoryCollection(256); /// Packets we have sent that need to be ACKed by the client public UnackedPacketCollection NeedAcks = new UnackedPacketCollection(); @@ -803,8 +803,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP } } - - /// /// Fires the OnQueueEmpty callback and sets the minimum time that it /// can be called again @@ -843,6 +841,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP return 0; } + public void FreeUDPBuffer(UDPPacketBuffer buf) + { + m_udpServer.FreeUDPBuffer(buf); + } + /// /// Converts a integer to a /// flag value @@ -853,20 +856,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP { ThrottleOutPacketType category = (ThrottleOutPacketType)i; - /* - * Land = 1, - /// Wind data - Wind = 2, - /// Cloud data - Cloud = 3, - /// Any packets that do not fit into the other throttles - Task = 4, - /// Texture assets - Texture = 5, - /// Non-texture assets - Asset = 6, - */ - switch (category) { case ThrottleOutPacketType.Land: diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs index 35d29a5..4739ae8 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs @@ -344,18 +344,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP protected ExpiringCache> m_pendingCache = new ExpiringCache>(); - protected Pool m_incomingPacketPool; - - /// - /// Stat for number of packets in the main pool awaiting use. - /// - protected Stat m_poolCountStat; - - /// - /// Stat for number of packets in the inbound packet pool awaiting use. - /// - protected Stat m_incomingPacketPoolStat; - protected int m_defaultRTO = 0; protected int m_maxRTO = 0; protected int m_ackTimeout = 0; @@ -498,7 +486,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP // if (usePools) // EnablePools(); - base.DisablePools(); } public void Start() @@ -554,83 +541,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP OqrEngine.Stop(); } - public override bool EnablePools() - { - if (!UsePools) - { - base.EnablePools(); - - m_incomingPacketPool = new Pool(() => new IncomingPacket(), 500); - - return true; - } - - return false; - } - - public override bool DisablePools() - { - if (UsePools) - { - base.DisablePools(); - - StatsManager.DeregisterStat(m_incomingPacketPoolStat); - - // We won't null out the pool to avoid a race condition with code that may be in the middle of using it. - - return true; - } - - return false; - } - - /// - /// This is a seperate method so that it can be called once we have an m_scene to distinguish different scene - /// stats. - /// - protected internal void EnablePoolStats() - { - m_poolCountStat - = new Stat( - "UDPPacketBufferPoolCount", - "Objects within the UDPPacketBuffer pool", - "The number of objects currently stored within the UDPPacketBuffer pool", - "", - "clientstack", - Scene.Name, - StatType.Pull, - stat => stat.Value = Pool.Count, - StatVerbosity.Debug); - - StatsManager.RegisterStat(m_poolCountStat); - - m_incomingPacketPoolStat - = new Stat( - "IncomingPacketPoolCount", - "Objects within incoming packet pool", - "The number of objects currently stored within the incoming packet pool", - "", - "clientstack", - Scene.Name, - StatType.Pull, - stat => stat.Value = m_incomingPacketPool.Count, - StatVerbosity.Debug); - - StatsManager.RegisterStat(m_incomingPacketPoolStat); - } - - /// - /// Disables pool stats. - /// - protected internal void DisablePoolStats() - { - StatsManager.DeregisterStat(m_poolCountStat); - m_poolCountStat = null; - - StatsManager.DeregisterStat(m_incomingPacketPoolStat); - m_incomingPacketPoolStat = null; - } - /// /// If the outgoing UDP thread times out, then return client that was being processed to help with debugging. /// @@ -658,8 +568,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP string.Format("Incoming Packet Async Handling Engine ({0})", Scene.Name), "INCOMING PACKET ASYNC HANDLING ENGINE"); */ - OqrEngine - = new JobEngine( + OqrEngine = new JobEngine( string.Format("Outgoing Queue Refill Engine ({0})", Scene.Name), "OUTGOING QUEUE REFILL ENGINE"); @@ -769,15 +678,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP stat => stat.Value = OqrEngine.JobsWaiting, StatVerbosity.Debug)); - // We delay enabling pool stats to AddScene() instead of Initialize() so that we can distinguish pool stats by - // scene name - if (UsePools) - EnablePoolStats(); - + StatsManager.RegisterStat( + new Stat( + "UDPBuffersPoolCount", + "Buffers in the UDP buffers pool", + "The number of buffers currently stored within the UDP buffers pool", + "", + "clientstack", + Scene.Name, + StatType.Pull, + stat => stat.Value = m_udpBuffersPoolPtr, + StatVerbosity.Debug)); LLUDPServerCommands commands = new LLUDPServerCommands(MainConsole.Instance, this); commands.Register(); - } public bool HandlesRegion(Location x) @@ -939,9 +853,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP // The vast majority of packets are less than 200 bytes, although due to asset transfers and packet splitting // there are a decent number of packets in the 1000-1140 byte range. We allocate one of two sizes of data here // to accomodate for both common scenarios and provide ample room for ACK appending in both - int bufferSize = (dataLength > 180) ? LLUDPServer.MTU : 200; + //int bufferSize = (dataLength > 180) ? LLUDPServer.MTU : 200; - UDPPacketBuffer buffer = new UDPPacketBuffer(udpClient.RemoteEndPoint, bufferSize); + //UDPPacketBuffer buffer = new UDPPacketBuffer(udpClient.RemoteEndPoint, bufferSize); + UDPPacketBuffer buffer = GetNewUDPBuffer(udpClient.RemoteEndPoint); // Zerocode if needed if (doZerocode) @@ -971,7 +886,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP // If the packet data wasn't already copied during zerocoding, copy it now if (doCopy) { - if (dataLength <= buffer.Data.Length) + //if (dataLength <= buffer.Data.Length) + if (dataLength <= LLUDPServer.MTU) { Buffer.BlockCopy(data, 0, buffer.Data, 0, dataLength); } @@ -979,7 +895,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP { m_log.Error("[LLUDPSERVER]: Packet exceeded buffer size! This could be an indication of packet assembly not obeying the MTU. Type=" + type + ", DataLength=" + dataLength + ", BufferLength=" + buffer.Data.Length); - buffer = new UDPPacketBuffer(udpClient.RemoteEndPoint, dataLength); + // buffer = new UDPPacketBuffer(udpClient.RemoteEndPoint, dataLength); + buffer = GetNewUDPBuffer(udpClient.RemoteEndPoint); Buffer.BlockCopy(data, 0, buffer.Data, 0, dataLength); } } @@ -1168,22 +1085,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP // Set the appended ACKs flag on this packet buffer.Data[0] = (byte)(buffer.Data[0] | Helpers.MSG_APPENDED_ACKS); } + buffer.DataLength = dataLength; } - buffer.DataLength = dataLength; - if (!isResend) { // Not a resend, assign a new sequence number uint sequenceNumber = (uint)Interlocked.Increment(ref udpClient.CurrentSequence); Utils.UIntToBytesBig(sequenceNumber, buffer.Data, 1); outgoingPacket.SequenceNumber = sequenceNumber; - - if (isReliable) - { - // Add this packet to the list of ACK responses we are waiting on from the server - udpClient.NeedAcks.Add(outgoingPacket); - } } else { @@ -1196,9 +1106,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP PacketsSentCount++; SyncSend(buffer); + // Keep track of when this packet was sent out (right now) outgoingPacket.TickCount = Environment.TickCount & Int32.MaxValue; + if (outgoingPacket.UnackedMethod == null) + FreeUDPBuffer(buffer); + else if(!isResend) + { + // Add this packet to the list of ACK responses we are waiting on from the server + udpClient.NeedAcks.Add(outgoingPacket); + } + if (udpClient.DebugDataOutLevel > 0) m_log.DebugFormat( "[LLUDPSERVER]: Sending packet #{0} (rel: {1}, res: {2}) to {3} from {4}", @@ -1240,7 +1159,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP // buffer.DataLength, buffer.RemoteEndPoint, m_scene.RegionInfo.RegionName); RecordMalformedInboundPacket(endPoint); - + FreeUDPBuffer(buffer); return; // Drop undersized packet } @@ -1260,21 +1179,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP // buffer.RemoteEndPoint, m_scene.RegionInfo.RegionName); RecordMalformedInboundPacket(endPoint); - + FreeUDPBuffer(buffer); return; // Malformed header } try { -// packet = Packet.BuildPacket(buffer.Data, ref packetEnd, -// // Only allocate a buffer for zerodecoding if the packet is zerocoded -// ((buffer.Data[0] & Helpers.MSG_ZEROCODED) != 0) ? new byte[4096] : null); + packet = Packet.BuildPacket(buffer.Data, ref packetEnd, + // Only allocate a buffer for zerodecoding if the packet is zerocoded + ((buffer.Data[0] & Helpers.MSG_ZEROCODED) != 0) ? new byte[4096] : null); // If OpenSimUDPBase.UsePool == true (which is currently separate from the PacketPool) then we // assume that packet construction does not retain a reference to byte[] buffer.Data (instead, all // bytes are copied out). - packet = PacketPool.Instance.GetPacket(buffer.Data, ref packetEnd, +// packet = PacketPool.Instance.GetPacket(buffer.Data, ref packetEnd, // Only allocate a buffer for zerodecoding if the packet is zerocoded - ((buffer.Data[0] & Helpers.MSG_ZEROCODED) != 0) ? new byte[4096] : null); +// ((buffer.Data[0] & Helpers.MSG_ZEROCODED) != 0) ? new byte[4096] : null); } catch (Exception e) { @@ -1292,7 +1211,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP } RecordMalformedInboundPacket(endPoint); - + FreeUDPBuffer(buffer); return; } @@ -1311,17 +1230,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP lock (m_pendingCache) { if (m_pendingCache.Contains(endPoint)) + { + FreeUDPBuffer(buffer); return; + } m_pendingCache.AddOrUpdate(endPoint, new Queue(), 60); } - // We need to copy the endpoint so that it doesn't get changed when another thread reuses the - // buffer. - object[] array = new object[] { new IPEndPoint(endPoint.Address, endPoint.Port), packet }; - - Util.FireAndForget(HandleUseCircuitCode, array); - + Util.FireAndForget(HandleUseCircuitCode, new object[] { endPoint, packet }); + FreeUDPBuffer(buffer); return; } } @@ -1336,24 +1254,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP queue.Enqueue(buffer); return; } - -/* - else if (packet.Type == PacketType.CompleteAgentMovement) - { - // Send ack straight away to let the viewer know that we got it. - SendAckImmediate(endPoint, packet.Header.Sequence); - - // We need to copy the endpoint so that it doesn't get changed when another thread reuses the - // buffer. - object[] array = new object[] { new IPEndPoint(endPoint.Address, endPoint.Port), packet }; - - Util.FireAndForget(HandleCompleteMovementIntoRegion, array); - - return; - } - */ } + FreeUDPBuffer(buffer); + // Determine which agent this packet came from if (client == null || !(client is LLClientView)) { @@ -1471,10 +1375,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP LogPacketHeader(true, udpClient.CircuitCode, 0, packet.Type, (ushort)packet.Length); #endregion BinaryStats - -//AgentUpdate removed from here - - #region Ping Check Handling if (packet.Type == PacketType.StartPingCheck) @@ -1506,17 +1406,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP IncomingPacket incomingPacket; - // Inbox insertion - if (UsePools) - { - incomingPacket = m_incomingPacketPool.GetObject(); - incomingPacket.Client = (LLClientView)client; - incomingPacket.Packet = packet; - } - else - { - incomingPacket = new IncomingPacket((LLClientView)client, packet); - } + incomingPacket = new IncomingPacket((LLClientView)client, packet); // if (incomingPacket.Packet.Type == PacketType.AgentUpdate || // incomingPacket.Packet.Type == PacketType.ChatFromViewer) @@ -1525,7 +1415,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP // else // packetInbox.Enqueue(incomingPacket); packetInbox.Add(incomingPacket); - } #region BinaryStats @@ -1881,13 +1770,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP byte[] packetData = ack.ToBytes(); int length = packetData.Length; - UDPPacketBuffer buffer = new UDPPacketBuffer(remoteEndpoint, length); + UDPPacketBuffer buffer = GetNewUDPBuffer(remoteEndpoint); buffer.DataLength = length; Buffer.BlockCopy(packetData, 0, buffer.Data, 0, length); // AsyncBeginSend(buffer); SyncSend(buffer); + FreeUDPBuffer(buffer); } protected bool IsClientAuthorized(UseCircuitCodePacket useCircuitCode, out AuthenticateResponse sessionInfo) @@ -1982,17 +1872,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP Scene.ThreadAlive(1); try { - packetInbox.TryTake(out incomingPacket, 250); + packetInbox.TryTake(out incomingPacket, 4500); if (incomingPacket != null && IsRunningInbound) { ProcessInPacket(incomingPacket); - - if (UsePools) - { - incomingPacket.Client = null; - m_incomingPacketPool.ReturnObject(incomingPacket); - } incomingPacket = null; } } diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServerCommands.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServerCommands.cs index 012a57d..a4d7eb9 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServerCommands.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServerCommands.cs @@ -777,41 +777,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP m_udpServer.StopOutbound(); } - private void HandlePoolCommand(string module, string[] args) - { - if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_udpServer.Scene) - return; - - if (args.Length != 4) - { - MainConsole.Instance.Output("Usage: debug lludp pool "); - return; - } - - string enabled = args[3]; - - if (enabled == "on") - { - if (m_udpServer.EnablePools()) - { - m_udpServer.EnablePoolStats(); - MainConsole.Instance.OutputFormat("Packet pools enabled on {0}", m_udpServer.Scene.Name); - } - } - else if (enabled == "off") - { - if (m_udpServer.DisablePools()) - { - m_udpServer.DisablePoolStats(); - MainConsole.Instance.OutputFormat("Packet pools disabled on {0}", m_udpServer.Scene.Name); - } - } - else - { - MainConsole.Instance.Output("Usage: debug lludp pool "); - } - } - private void HandleAgentUpdateCommand(string module, string[] args) { if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_udpServer.Scene) @@ -834,8 +799,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP MainConsole.Instance.OutputFormat( "OUT LLUDP packet processing for {0} is {1}", m_udpServer.Scene.Name, m_udpServer.IsRunningOutbound ? "enabled" : "disabled"); - MainConsole.Instance.OutputFormat("LLUDP pools in {0} are {1}", m_udpServer.Scene.Name, m_udpServer.UsePools ? "on" : "off"); - MainConsole.Instance.OutputFormat( "Packet debug level for new clients is {0}", m_udpServer.DefaultClientPacketDebugLevel); } diff --git a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs index f362b06..0bfd86c 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs @@ -26,6 +26,7 @@ */ using System; +using System.Collections.Concurrent; using System.Net; using System.Net.Sockets; using System.Threading; @@ -57,15 +58,9 @@ namespace OpenMetaverse /// UDP socket, used in either client or server mode private Socket m_udpSocket; - /// - /// Are we to use object pool(s) to reduce memory churn when receiving data? - /// - public bool UsePools { get; protected set; } - - /// - /// Pool to use for handling data. May be null if UsePools = false; - /// - protected OpenSim.Framework.Pool Pool { get; private set; } + public static Object m_udpBuffersPoolLock = new Object(); + public static UDPPacketBuffer[] m_udpBuffersPool = new UDPPacketBuffer[1000]; + public static int m_udpBuffersPoolPtr = -1; /// Returns true if the server is currently listening for inbound packets, otherwise false public bool IsRunningInbound { get; private set; } @@ -186,6 +181,52 @@ namespace OpenMetaverse if(m_udpSocket !=null) try { m_udpSocket.Close(); } catch { } } + + public UDPPacketBuffer GetNewUDPBuffer() + { + lock (m_udpBuffersPoolLock) + { + if (m_udpBuffersPoolPtr >= 0) + { + UDPPacketBuffer buf = m_udpBuffersPool[m_udpBuffersPoolPtr]; + m_udpBuffersPool[m_udpBuffersPoolPtr] = null; + m_udpBuffersPoolPtr--; + buf.RemoteEndPoint = new IPEndPoint(IPAddress.Any, 0); + return buf; + } + } + return new UDPPacketBuffer(new IPEndPoint(IPAddress.Any, 0)); + } + + public UDPPacketBuffer GetNewUDPBuffer(IPEndPoint remoteEndpoint) + { + lock (m_udpBuffersPoolLock) + { + if (m_udpBuffersPoolPtr >= 0) + { + UDPPacketBuffer buf = m_udpBuffersPool[m_udpBuffersPoolPtr]; + m_udpBuffersPool[m_udpBuffersPoolPtr] = null; + m_udpBuffersPoolPtr--; + buf.RemoteEndPoint = remoteEndpoint; + return buf; + } + } + return new UDPPacketBuffer(remoteEndpoint); + } + + public void FreeUDPBuffer(UDPPacketBuffer buf) + { + lock (m_udpBuffersPoolLock) + { + if (m_udpBuffersPoolPtr < 999) + { + buf.RemoteEndPoint = null; + m_udpBuffersPoolPtr++; + m_udpBuffersPool[m_udpBuffersPoolPtr] = buf; + } + } + } + /// /// Start inbound UDP packet handling. /// @@ -202,6 +243,7 @@ namespace OpenMetaverse /// manner (not throwing an exception when the remote side resets the /// connection). This call is ignored on Mono where the flag is not /// necessary + public virtual void StartInbound(int recvBufferSize) { if (!IsRunningInbound) @@ -306,101 +348,64 @@ namespace OpenMetaverse IsRunningOutbound = false; } - public virtual bool EnablePools() + private void AsyncBeginReceive() { - if (!UsePools) - { - Pool = new Pool(() => new UDPPacketBuffer(), 500); - - UsePools = true; - - return true; - } - - return false; - } + if (!IsRunningInbound) + return; - public virtual bool DisablePools() - { - if (UsePools) + UDPPacketBuffer buf = GetNewUDPBuffer(); + try { - UsePools = false; - - // We won't null out the pool to avoid a race condition with code that may be in the middle of using it. - - return true; + // kick off an async read + m_udpSocket.BeginReceiveFrom( + //wrappedBuffer.Instance.Data, + buf.Data, + 0, + UDPPacketBuffer.BUFFER_SIZE, + SocketFlags.None, + ref buf.RemoteEndPoint, + AsyncEndReceive, + //wrappedBuffer); + buf); } - - return false; - } - - private void AsyncBeginReceive() - { - UDPPacketBuffer buf; - - // FIXME: Disabled for now as this causes issues with reused packet objects interfering with each other - // on Windows with m_asyncPacketHandling = true, though this has not been seen on Linux. - // Possibly some unexpected issue with fetching UDP data concurrently with multiple threads. Requires more investigation. -// if (UsePools) -// buf = Pool.GetObject(); -// else - buf = new UDPPacketBuffer(); - - if (IsRunningInbound) + catch (SocketException e) { - try + if (e.SocketErrorCode == SocketError.ConnectionReset) { - // kick off an async read - m_udpSocket.BeginReceiveFrom( - //wrappedBuffer.Instance.Data, - buf.Data, - 0, - UDPPacketBuffer.BUFFER_SIZE, - SocketFlags.None, - ref buf.RemoteEndPoint, - AsyncEndReceive, - //wrappedBuffer); - buf); - } - catch (SocketException e) - { - if (e.SocketErrorCode == SocketError.ConnectionReset) + m_log.Warn("[UDPBASE]: SIO_UDP_CONNRESET was ignored, attempting to salvage the UDP listener on port " + m_udpPort); + bool salvaged = false; + while (!salvaged) { - m_log.Warn("[UDPBASE]: SIO_UDP_CONNRESET was ignored, attempting to salvage the UDP listener on port " + m_udpPort); - bool salvaged = false; - while (!salvaged) + try { - try - { - m_udpSocket.BeginReceiveFrom( - //wrappedBuffer.Instance.Data, - buf.Data, - 0, - UDPPacketBuffer.BUFFER_SIZE, - SocketFlags.None, - ref buf.RemoteEndPoint, - AsyncEndReceive, - //wrappedBuffer); - buf); - salvaged = true; - } - catch (SocketException) { } - catch (ObjectDisposedException) { return; } + m_udpSocket.BeginReceiveFrom( + //wrappedBuffer.Instance.Data, + buf.Data, + 0, + UDPPacketBuffer.BUFFER_SIZE, + SocketFlags.None, + ref buf.RemoteEndPoint, + AsyncEndReceive, + //wrappedBuffer); + buf); + salvaged = true; } - - m_log.Warn("[UDPBASE]: Salvaged the UDP listener on port " + m_udpPort); + catch (SocketException) { } + catch (ObjectDisposedException) { return; } } + + m_log.Warn("[UDPBASE]: Salvaged the UDP listener on port " + m_udpPort); } - catch (ObjectDisposedException e) - { - m_log.Error( - string.Format("[UDPBASE]: Error processing UDP begin receive {0}. Exception ", UdpReceives), e); - } - catch (Exception e) - { - m_log.Error( - string.Format("[UDPBASE]: Error processing UDP begin receive {0}. Exception ", UdpReceives), e); - } + } + catch (ObjectDisposedException e) + { + m_log.Error( + string.Format("[UDPBASE]: Error processing UDP begin receive {0}. Exception ", UdpReceives), e); + } + catch (Exception e) + { + m_log.Error( + string.Format("[UDPBASE]: Error processing UDP begin receive {0}. Exception ", UdpReceives), e); } } @@ -465,14 +470,12 @@ namespace OpenMetaverse } finally { -// if (UsePools) -// Pool.ReturnObject(buffer); - AsyncBeginReceive(); } } } +/* not in use public void AsyncBeginSend(UDPPacketBuffer buf) { // if (IsRunningOutbound) @@ -511,7 +514,7 @@ namespace OpenMetaverse catch (SocketException) { } catch (ObjectDisposedException) { } } - +*/ public void SyncSend(UDPPacketBuffer buf) { try diff --git a/OpenSim/Region/ClientStack/Linden/UDP/UnackedPacketCollection.cs b/OpenSim/Region/ClientStack/Linden/UDP/UnackedPacketCollection.cs index 76f4c6f..e0eee53 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/UnackedPacketCollection.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/UnackedPacketCollection.cs @@ -203,6 +203,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP if (ackedPacket != null) { m_packets.Remove(pendingAcknowledgement.SequenceNumber); + ackedPacket.Client.FreeUDPBuffer(ackedPacket.Buffer); // As with other network applications, assume that an acknowledged packet is an // indication that the network can handle a little more load, speed up the transmission @@ -241,6 +242,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP if (removedPacket != null) { m_packets.Remove(pendingRemove); + removedPacket.Client.FreeUDPBuffer(removedPacket.Buffer); // Update stats Interlocked.Add(ref removedPacket.Client.UnackedBytes, -removedPacket.Buffer.DataLength); -- cgit v1.1 From 91fab702361ecaf8a442e7cf3a469aaa6daead44 Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Mon, 25 Feb 2019 23:05:11 +0000 Subject: removed a redundant function; try to make a particular vi coder happy about removed comments --- OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs | 12 ++++++------ .../Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs | 18 +----------------- 2 files changed, 7 insertions(+), 23 deletions(-) (limited to 'OpenSim/Region/ClientStack') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs index bc75d82..e0cca05 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs @@ -859,17 +859,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP switch (category) { case ThrottleOutPacketType.Land: - return ThrottleOutPacketTypeFlags.Land; + return ThrottleOutPacketTypeFlags.Land; // Terrain data case ThrottleOutPacketType.Wind: - return ThrottleOutPacketTypeFlags.Wind; + return ThrottleOutPacketTypeFlags.Wind; // Wind data case ThrottleOutPacketType.Cloud: - return ThrottleOutPacketTypeFlags.Cloud; + return ThrottleOutPacketTypeFlags.Cloud; // Cloud data case ThrottleOutPacketType.Task: - return ThrottleOutPacketTypeFlags.Task; + return ThrottleOutPacketTypeFlags.Task; // Object updates and everything not on the other categories case ThrottleOutPacketType.Texture: - return ThrottleOutPacketTypeFlags.Texture; + return ThrottleOutPacketTypeFlags.Texture; // Textures data (also impacts http texture and mesh by default) case ThrottleOutPacketType.Asset: - return ThrottleOutPacketTypeFlags.Asset; + return ThrottleOutPacketTypeFlags.Asset; // Non-texture Assets data default: return 0; } diff --git a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs index 0bfd86c..7f6a292 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs @@ -182,22 +182,6 @@ namespace OpenMetaverse try { m_udpSocket.Close(); } catch { } } - public UDPPacketBuffer GetNewUDPBuffer() - { - lock (m_udpBuffersPoolLock) - { - if (m_udpBuffersPoolPtr >= 0) - { - UDPPacketBuffer buf = m_udpBuffersPool[m_udpBuffersPoolPtr]; - m_udpBuffersPool[m_udpBuffersPoolPtr] = null; - m_udpBuffersPoolPtr--; - buf.RemoteEndPoint = new IPEndPoint(IPAddress.Any, 0); - return buf; - } - } - return new UDPPacketBuffer(new IPEndPoint(IPAddress.Any, 0)); - } - public UDPPacketBuffer GetNewUDPBuffer(IPEndPoint remoteEndpoint) { lock (m_udpBuffersPoolLock) @@ -353,7 +337,7 @@ namespace OpenMetaverse if (!IsRunningInbound) return; - UDPPacketBuffer buf = GetNewUDPBuffer(); + UDPPacketBuffer buf = GetNewUDPBuffer(new IPEndPoint(IPAddress.Any, 0)); // we need a fresh one here, for now at least try { // kick off an async read -- cgit v1.1 From d5d4dc475461f889194a84aa682fbd555aad303f Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Mon, 25 Feb 2019 23:30:01 +0000 Subject: zero decode using a buffer from the pool --- OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) (limited to 'OpenSim/Region/ClientStack') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs index 4739ae8..e931f3b 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs @@ -1185,15 +1185,23 @@ namespace OpenSim.Region.ClientStack.LindenUDP try { - packet = Packet.BuildPacket(buffer.Data, ref packetEnd, - // Only allocate a buffer for zerodecoding if the packet is zerocoded - ((buffer.Data[0] & Helpers.MSG_ZEROCODED) != 0) ? new byte[4096] : null); + // get a buffer for zero decode using the udp buffers pool + UDPPacketBuffer zerodecodebufferholder = null; + byte[] zerodecodebuffer = null; + // only if needed + if (((buffer.Data[0] & Helpers.MSG_ZEROCODED) != 0)) + { + zerodecodebufferholder = GetNewUDPBuffer(null); + zerodecodebuffer = zerodecodebufferholder.Data; + } + + packet = Packet.BuildPacket(buffer.Data, ref packetEnd, zerodecodebuffer); // If OpenSimUDPBase.UsePool == true (which is currently separate from the PacketPool) then we // assume that packet construction does not retain a reference to byte[] buffer.Data (instead, all // bytes are copied out). -// packet = PacketPool.Instance.GetPacket(buffer.Data, ref packetEnd, - // Only allocate a buffer for zerodecoding if the packet is zerocoded -// ((buffer.Data[0] & Helpers.MSG_ZEROCODED) != 0) ? new byte[4096] : null); + // packet = PacketPool.Instance.GetPacket(buffer.Data, ref packetEnd, zerodecodebuffer); + if(zerodecodebufferholder != null) + FreeUDPBuffer(zerodecodebufferholder); } catch (Exception e) { -- cgit v1.1 From a07951b04471ff4d0c6204f2c13c49248f0b7d19 Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Tue, 26 Feb 2019 00:43:44 +0000 Subject: fix UDPBuffersPoolCount value (readable with stats show clientstack --- OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'OpenSim/Region/ClientStack') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs index e931f3b..ba5a2f3 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs @@ -687,7 +687,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP "clientstack", Scene.Name, StatType.Pull, - stat => stat.Value = m_udpBuffersPoolPtr, + stat => stat.Value = m_udpBuffersPoolPtr + 1, StatVerbosity.Debug)); LLUDPServerCommands commands = new LLUDPServerCommands(MainConsole.Instance, this); @@ -1582,7 +1582,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP { m_log.DebugFormat("[LLUDPSERVER]: Client created but no pending queue present"); return; - } m_pendingCache.Remove(endPoint); } -- cgit v1.1 From 91569e00a0a4f9b9124979b73e00a4e88020c6cd Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Tue, 26 Feb 2019 01:16:30 +0000 Subject: buffers in pool have no data, better mk that clear --- OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs | 1 + 1 file changed, 1 insertion(+) (limited to 'OpenSim/Region/ClientStack') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs index 7f6a292..5fa4637 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs @@ -205,6 +205,7 @@ namespace OpenMetaverse if (m_udpBuffersPoolPtr < 999) { buf.RemoteEndPoint = null; + buf.DataLength = 0; m_udpBuffersPoolPtr++; m_udpBuffersPool[m_udpBuffersPoolPtr] = buf; } -- cgit v1.1 From 4de5e14e542cd9724625e87622f29fecf5652642 Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Tue, 26 Feb 2019 15:02:57 +0000 Subject: issues with udp buffers pool on heavy load --- .../Region/ClientStack/Linden/UDP/LLUDPClient.cs | 30 ++++++++++++++++------ .../Region/ClientStack/Linden/UDP/LLUDPServer.cs | 29 +++++++++++---------- .../ClientStack/Linden/UDP/OpenSimUDPBase.cs | 22 ++++------------ .../Linden/UDP/UnackedPacketCollection.cs | 14 +++++++--- 4 files changed, 53 insertions(+), 42 deletions(-) (limited to 'OpenSim/Region/ClientStack') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs index e0cca05..fca7943 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs @@ -650,6 +650,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP // leaving a dequeued packet still waiting to be sent out. Try to // send it again OutgoingPacket nextPacket = m_nextPackets[i]; + if(nextPacket.Buffer == null) + { + if (m_packetOutboxes[i].Count < 5) + emptyCategories |= CategoryToFlag(i); + continue; + } if (bucket.RemoveTokens(nextPacket.Buffer.DataLength)) { // Send the packet @@ -681,21 +687,29 @@ namespace OpenSim.Region.ClientStack.LindenUDP { // A packet was pulled off the queue. See if we have // enough tokens in the bucket to send it out - if (bucket.RemoveTokens(packet.Buffer.DataLength)) + if(packet.Buffer == null) { - // Send the packet - m_udpServer.SendPacketFinal(packet); - packetSent = true; - + // packet canceled elsewhere (by a ack for example) if (queue.Count < 5) emptyCategories |= CategoryToFlag(i); } else { - // Save the dequeued packet for the next iteration - m_nextPackets[i] = packet; + if (bucket.RemoveTokens(packet.Buffer.DataLength)) + { + // Send the packet + m_udpServer.SendPacketFinal(packet); + packetSent = true; + + if (queue.Count < 5) + emptyCategories |= CategoryToFlag(i); + } + else + { + // Save the dequeued packet for the next iteration + m_nextPackets[i] = packet; + } } - } else { diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs index ba5a2f3..d324623 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs @@ -983,7 +983,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP { LLUDPClient udpClient = client.UDPClient; - if (!udpClient.IsConnected) + if (!client.IsActive || !udpClient.IsConnected) return; // Disconnect an agent if no packets are received for some time @@ -1053,14 +1053,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP internal void SendPacketFinal(OutgoingPacket outgoingPacket) { UDPPacketBuffer buffer = outgoingPacket.Buffer; + if(buffer == null) // canceled packet + return; + LLUDPClient udpClient = outgoingPacket.Client; + if (!udpClient.IsConnected) + return; + byte flags = buffer.Data[0]; bool isResend = (flags & Helpers.MSG_RESENT) != 0; bool isReliable = (flags & Helpers.MSG_RELIABLE) != 0; bool isZerocoded = (flags & Helpers.MSG_ZEROCODED) != 0; - LLUDPClient udpClient = outgoingPacket.Client; - - if (!udpClient.IsConnected) - return; int dataLength = buffer.DataLength; @@ -1916,7 +1918,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP { Scene.ThreadAlive(2); - try { m_packetSent = false; @@ -1971,7 +1972,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP } else if (!m_packetSent) // Thread.Sleep((int)TickCountResolution); outch this is bad on linux - Thread.Sleep(15); // match the 16ms of windows7, dont ask 16 or win may decide to do 32ms. + Thread.Sleep(15); // match the 16ms of windows, dont ask 16 or win may decide to do 32ms. Watchdog.UpdateThread(); } @@ -1995,14 +1996,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP if (udpClient.IsConnected) { - if (m_resendUnacked) + if (client.IsActive && m_resendUnacked) HandleUnacked(llClient); - if (m_sendAcks) - SendAcks(udpClient); + if (client.IsActive) + { + if (m_sendAcks) + SendAcks(udpClient); - if (m_sendPing) - SendPing(udpClient); + if (m_sendPing) + SendPing(udpClient); + } // Dequeue any outgoing packets that are within the throttle limits if (udpClient.DequeueOutgoing()) @@ -2015,7 +2019,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP m_log.Error( string.Format("[LLUDPSERVER]: OutgoingPacketHandler iteration for {0} threw ", client.Name), ex); } - client = null; } #region Emergency Monitoring diff --git a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs index 5fa4637..6f346d3 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs @@ -343,14 +343,12 @@ namespace OpenMetaverse { // kick off an async read m_udpSocket.BeginReceiveFrom( - //wrappedBuffer.Instance.Data, buf.Data, 0, - UDPPacketBuffer.BUFFER_SIZE, + buf.Data.Length, SocketFlags.None, ref buf.RemoteEndPoint, AsyncEndReceive, - //wrappedBuffer); buf); } catch (SocketException e) @@ -364,14 +362,12 @@ namespace OpenMetaverse try { m_udpSocket.BeginReceiveFrom( - //wrappedBuffer.Instance.Data, buf.Data, 0, - UDPPacketBuffer.BUFFER_SIZE, + buf.Data.Length, SocketFlags.None, ref buf.RemoteEndPoint, AsyncEndReceive, - //wrappedBuffer); buf); salvaged = true; } @@ -382,11 +378,6 @@ namespace OpenMetaverse m_log.Warn("[UDPBASE]: Salvaged the UDP listener on port " + m_udpPort); } } - catch (ObjectDisposedException e) - { - m_log.Error( - string.Format("[UDPBASE]: Error processing UDP begin receive {0}. Exception ", UdpReceives), e); - } catch (Exception e) { m_log.Error( @@ -443,11 +434,6 @@ namespace OpenMetaverse UdpReceives, se.ErrorCode), se); } - catch (ObjectDisposedException e) - { - m_log.Error( - string.Format("[UDPBASE]: Error processing UDP end receive {0}. Exception ", UdpReceives), e); - } catch (Exception e) { m_log.Error( @@ -502,6 +488,8 @@ namespace OpenMetaverse */ public void SyncSend(UDPPacketBuffer buf) { + if(buf.RemoteEndPoint == null) + return; // was already expired try { m_udpSocket.SendTo( @@ -515,7 +503,7 @@ namespace OpenMetaverse } catch (SocketException e) { - m_log.Warn("[UDPBASE]: sync send SocketException {0} " + e.Message); + m_log.WarnFormat("[UDPBASE]: sync send SocketException {0} {1}", buf.RemoteEndPoint, e.Message); } catch (ObjectDisposedException) { } } diff --git a/OpenSim/Region/ClientStack/Linden/UDP/UnackedPacketCollection.cs b/OpenSim/Region/ClientStack/Linden/UDP/UnackedPacketCollection.cs index e0eee53..1f978e1 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/UnackedPacketCollection.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/UnackedPacketCollection.cs @@ -189,8 +189,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP // Process all the pending adds OutgoingPacket pendingAdd; while (m_pendingAdds.TryDequeue(out pendingAdd)) + { if (pendingAdd != null) m_packets[pendingAdd.SequenceNumber] = pendingAdd; + } // Process all the pending removes, including updating statistics and round-trip times PendingAck pendingAcknowledgement; @@ -203,15 +205,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP if (ackedPacket != null) { m_packets.Remove(pendingAcknowledgement.SequenceNumber); + + // Update stats + Interlocked.Add(ref ackedPacket.Client.UnackedBytes, -ackedPacket.Buffer.DataLength); + ackedPacket.Client.FreeUDPBuffer(ackedPacket.Buffer); + ackedPacket.Buffer = null; // As with other network applications, assume that an acknowledged packet is an // indication that the network can handle a little more load, speed up the transmission ackedPacket.Client.FlowThrottle.AcknowledgePackets(1); - // Update stats - Interlocked.Add(ref ackedPacket.Client.UnackedBytes, -ackedPacket.Buffer.DataLength); - if (!pendingAcknowledgement.FromResend) { // Calculate the round-trip time for this packet and its ACK @@ -242,10 +246,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP if (removedPacket != null) { m_packets.Remove(pendingRemove); - removedPacket.Client.FreeUDPBuffer(removedPacket.Buffer); // Update stats Interlocked.Add(ref removedPacket.Client.UnackedBytes, -removedPacket.Buffer.DataLength); + + removedPacket.Client.FreeUDPBuffer(removedPacket.Buffer); + removedPacket.Buffer = null; } } } -- cgit v1.1 From fe46f8cd1ddbf3d37e8be4a3771ce5124024d6f8 Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Tue, 26 Feb 2019 15:09:18 +0000 Subject: avoid packet split on terseupdates --- .../Region/ClientStack/Linden/UDP/LLClientView.cs | 106 +++++++++++++++------ 1 file changed, 76 insertions(+), 30 deletions(-) (limited to 'OpenSim/Region/ClientStack') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 3cb9388..f28534b 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -4094,11 +4094,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP return; List objectUpdateBlocks = null; - List compressedUpdateBlocks = null; - List terseUpdateBlocks = null; - List terseAgentUpdateBlocks = null; + // List compressedUpdateBlocks = null; List objectUpdates = null; - List compressedUpdates = null; + // List compressedUpdates = null; List terseUpdates = null; List terseAgentUpdates = null; List ObjectAnimationUpdates = null; @@ -4321,32 +4319,29 @@ namespace OpenSim.Region.ClientStack.LindenUDP if ((updateFlags & canNotUseImprovedMask) == 0) { - ImprovedTerseObjectUpdatePacket.ObjectDataBlock ablock = - CreateImprovedTerseBlock(update.Entity); if (update.Entity is ScenePresence) { // ALL presence updates go into a special list - if (terseAgentUpdateBlocks == null) + if (terseAgentUpdates == null) { - terseAgentUpdateBlocks = new List(); terseAgentUpdates = new List(); + maxUpdatesBytes -= 18; } - terseAgentUpdateBlocks.Add(ablock); terseAgentUpdates.Add(update); + maxUpdatesBytes -= 63; // no texture entry } else { // Everything else goes here - if (terseUpdateBlocks == null) + if (terseUpdates == null) { - terseUpdateBlocks = new List(); terseUpdates = new List(); + maxUpdatesBytes -= 18; } - terseUpdateBlocks.Add(ablock); terseUpdates.Add(update); + maxUpdatesBytes -= 47; // no texture entry } - maxUpdatesBytes -= ablock.Length; } else { @@ -4359,6 +4354,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP { objectUpdateBlocks = new List(); objectUpdates = new List(); + maxUpdatesBytes -= 18; } objectUpdateBlocks.Add(ablock); objectUpdates.Add(update); @@ -4377,16 +4373,42 @@ namespace OpenSim.Region.ClientStack.LindenUDP timeDilation = Utils.FloatToUInt16(m_scene.TimeDilation, 0.0f, 1.0f); - if (terseAgentUpdateBlocks != null) + if (terseAgentUpdates != null) { + const int maxNBlocks = (LLUDPServer.MTU - 18) / 63; // no texture entry + int blocks = terseAgentUpdates.Count; + ImprovedTerseObjectUpdatePacket packet - = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ImprovedTerseObjectUpdate); + = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ImprovedTerseObjectUpdate); packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; packet.RegionData.TimeDilation = timeDilation; - packet.ObjectData = terseAgentUpdateBlocks.ToArray(); - terseAgentUpdateBlocks.Clear(); - OutPacket(packet, ThrottleOutPacketType.Unknown, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(terseAgentUpdates, oPacket); }); + int curNBlocks = blocks > maxNBlocks ? maxNBlocks : blocks; + List tau = new List(curNBlocks); + packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[curNBlocks]; + + int count = 0; + foreach (EntityUpdate eu in terseAgentUpdates) + { + packet.ObjectData[count++] = CreateImprovedTerseBlock(eu.Entity); + tau.Add(eu); + --blocks; + if (count == curNBlocks && blocks > 0) + { + OutPacket(packet, ThrottleOutPacketType.Unknown, false, delegate (OutgoingPacket oPacket) { ResendPrimUpdates(tau, oPacket); }); + packet = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ImprovedTerseObjectUpdate); + packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; + packet.RegionData.TimeDilation = timeDilation; + + curNBlocks = blocks > maxNBlocks ? maxNBlocks : blocks; + tau = new List(curNBlocks); + packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[curNBlocks]; + count = 0; + } + } + + if (tau.Count > 0) + OutPacket(packet, ThrottleOutPacketType.Unknown, false, delegate (OutgoingPacket oPacket) { ResendPrimUpdates(tau, oPacket); }); } if (objectUpdateBlocks != null) @@ -4399,7 +4421,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(objectUpdates, oPacket); }); } - +/* if (compressedUpdateBlocks != null) { ObjectUpdateCompressedPacket packet = (ObjectUpdateCompressedPacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdateCompressed); @@ -4410,20 +4432,46 @@ namespace OpenSim.Region.ClientStack.LindenUDP OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(compressedUpdates, oPacket); }); } - - if (terseUpdateBlocks != null) +*/ + if (terseUpdates != null) { - ImprovedTerseObjectUpdatePacket packet = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket( - PacketType.ImprovedTerseObjectUpdate); + const int maxNBlocks = (LLUDPServer.MTU - 18) / 47; // no texture entry + int blocks = terseUpdates.Count; + + ImprovedTerseObjectUpdatePacket packet = + (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ImprovedTerseObjectUpdate); packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; packet.RegionData.TimeDilation = timeDilation; - packet.ObjectData = terseUpdateBlocks.ToArray(); - terseUpdateBlocks.Clear(); - OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(terseUpdates, oPacket); }); + int curNBlocks = blocks > maxNBlocks ? maxNBlocks : blocks; + List tau = new List(curNBlocks); + packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[curNBlocks]; + + int count = 0; + foreach (EntityUpdate eu in terseUpdates) + { + packet.ObjectData[count++] = CreateImprovedTerseBlock(eu.Entity); + tau.Add(eu); + --blocks; + if (count == curNBlocks && blocks > 0) + { + OutPacket(packet, ThrottleOutPacketType.Task, false, delegate (OutgoingPacket oPacket) { ResendPrimUpdates(tau, oPacket); }); + packet = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ImprovedTerseObjectUpdate); + packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; + packet.RegionData.TimeDilation = timeDilation; + + curNBlocks = blocks > maxNBlocks ? maxNBlocks : blocks; + tau = new List(curNBlocks); + packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[curNBlocks]; + count = 0; + } + } + + if (tau.Count > 0) + OutPacket(packet, ThrottleOutPacketType.Task, false, delegate (OutgoingPacket oPacket) { ResendPrimUpdates(tau, oPacket); }); } - if(ObjectAnimationUpdates != null) + if (ObjectAnimationUpdates != null) { foreach (SceneObjectPart sop in ObjectAnimationUpdates) { @@ -4637,9 +4685,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP // These are used to implement an adaptive backoff in the number // of updates converted to packets. Since we don't want packets // to sit in the queue with old data, only convert enough updates - // to packets that can be sent in 200ms. -// private Int32 m_LastQueueFill = 0; -// private Int32 m_maxUpdates = 0; + // to packets that can be sent in 30ms. void HandleQueueEmpty(ThrottleOutPacketTypeFlags categories) { -- cgit v1.1 From bcf05afd64d3b38c66d6d117a51e336a7e98dfc3 Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Wed, 27 Feb 2019 10:07:25 +0000 Subject: direct encode terseupdates --- .../Region/ClientStack/Linden/UDP/LLClientView.cs | 210 ++++++++++++++++++--- .../Region/ClientStack/Linden/UDP/LLUDPClient.cs | 11 +- .../Region/ClientStack/Linden/UDP/LLUDPServer.cs | 21 +++ .../ClientStack/Linden/UDP/OpenSimUDPBase.cs | 2 +- 4 files changed, 207 insertions(+), 37 deletions(-) (limited to 'OpenSim/Region/ClientStack') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index f28534b..a9edf08 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -4084,6 +4084,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP ResendPrimUpdate(update); } + static private readonly byte[] terseUpdateHeader = new byte[] { + Helpers.MSG_RELIABLE, + 0, 0, 0, 0, // sequence number + 0, // extra + 15 // ID (high frequency) + }; + private void ProcessEntityUpdates(int maxUpdatesBytes) { if (!IsActive) @@ -4377,38 +4384,51 @@ namespace OpenSim.Region.ClientStack.LindenUDP { const int maxNBlocks = (LLUDPServer.MTU - 18) / 63; // no texture entry int blocks = terseAgentUpdates.Count; - - ImprovedTerseObjectUpdatePacket packet - = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ImprovedTerseObjectUpdate); - packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; - packet.RegionData.TimeDilation = timeDilation; - int curNBlocks = blocks > maxNBlocks ? maxNBlocks : blocks; List tau = new List(curNBlocks); - packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[curNBlocks]; + + UDPPacketBuffer buf = m_udpServer.GetNewUDPBuffer(m_udpClient.RemoteEndPoint); + + //setup header and regioninfo block + Array.Copy(terseUpdateHeader, buf.Data, 7); + Utils.UInt64ToBytesSafepos(m_scene.RegionInfo.RegionHandle, buf.Data, 7); + Utils.UInt16ToBytes(timeDilation, buf.Data, 15); + buf.Data[17] = (byte)curNBlocks; + int pos = 18; int count = 0; foreach (EntityUpdate eu in terseAgentUpdates) { - packet.ObjectData[count++] = CreateImprovedTerseBlock(eu.Entity); + CreateImprovedTerseBlock(eu.Entity, buf.Data, ref pos); tau.Add(eu); + ++count; --blocks; if (count == curNBlocks && blocks > 0) { - OutPacket(packet, ThrottleOutPacketType.Unknown, false, delegate (OutgoingPacket oPacket) { ResendPrimUpdates(tau, oPacket); }); - packet = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ImprovedTerseObjectUpdate); - packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; - packet.RegionData.TimeDilation = timeDilation; + // we need more packets + UDPPacketBuffer newbuf = m_udpServer.GetNewUDPBuffer(m_udpClient.RemoteEndPoint); + Array.Copy(buf.Data, newbuf.Data, 17); // start is the same + + buf.DataLength = pos; + m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Unknown, + delegate (OutgoingPacket oPacket) { ResendPrimUpdates(tau, oPacket); }, false); curNBlocks = blocks > maxNBlocks ? maxNBlocks : blocks; tau = new List(curNBlocks); - packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[curNBlocks]; count = 0; + + buf = newbuf; + buf.Data[17] = (byte)curNBlocks; + pos = 18; } } - if (tau.Count > 0) - OutPacket(packet, ThrottleOutPacketType.Unknown, false, delegate (OutgoingPacket oPacket) { ResendPrimUpdates(tau, oPacket); }); + if (count > 0) + { + buf.DataLength = pos; + m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Unknown, + delegate (OutgoingPacket oPacket) { ResendPrimUpdates(tau, oPacket); }, false); + } } if (objectUpdateBlocks != null) @@ -4437,38 +4457,51 @@ namespace OpenSim.Region.ClientStack.LindenUDP { const int maxNBlocks = (LLUDPServer.MTU - 18) / 47; // no texture entry int blocks = terseUpdates.Count; - - ImprovedTerseObjectUpdatePacket packet = - (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ImprovedTerseObjectUpdate); - packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; - packet.RegionData.TimeDilation = timeDilation; - int curNBlocks = blocks > maxNBlocks ? maxNBlocks : blocks; List tau = new List(curNBlocks); - packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[curNBlocks]; + + UDPPacketBuffer buf = m_udpServer.GetNewUDPBuffer(m_udpClient.RemoteEndPoint); + + //setup header and regioninfo block + Array.Copy(terseUpdateHeader, buf.Data, 7); + Utils.UInt64ToBytesSafepos(m_scene.RegionInfo.RegionHandle, buf.Data, 7); + Utils.UInt16ToBytes(timeDilation, buf.Data, 15); + buf.Data[17] = (byte)curNBlocks; + int pos = 18; int count = 0; foreach (EntityUpdate eu in terseUpdates) { - packet.ObjectData[count++] = CreateImprovedTerseBlock(eu.Entity); + CreateImprovedTerseBlock(eu.Entity, buf.Data, ref pos); tau.Add(eu); + ++count; --blocks; if (count == curNBlocks && blocks > 0) { - OutPacket(packet, ThrottleOutPacketType.Task, false, delegate (OutgoingPacket oPacket) { ResendPrimUpdates(tau, oPacket); }); - packet = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ImprovedTerseObjectUpdate); - packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; - packet.RegionData.TimeDilation = timeDilation; + // we need more packets + UDPPacketBuffer newbuf = m_udpServer.GetNewUDPBuffer(m_udpClient.RemoteEndPoint); + Array.Copy(buf.Data, newbuf.Data, 17); // start is the same + + buf.DataLength = pos; + m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task, + delegate (OutgoingPacket oPacket) { ResendPrimUpdates(tau, oPacket); }, false); curNBlocks = blocks > maxNBlocks ? maxNBlocks : blocks; tau = new List(curNBlocks); - packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[curNBlocks]; count = 0; + + buf = newbuf; + buf.Data[17] = (byte)curNBlocks; + pos = 18; } } - if (tau.Count > 0) - OutPacket(packet, ThrottleOutPacketType.Task, false, delegate (OutgoingPacket oPacket) { ResendPrimUpdates(tau, oPacket); }); + if (count > 0) + { + buf.DataLength = pos; + m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task, + delegate (OutgoingPacket oPacket) { ResendPrimUpdates(tau, oPacket); }, false); + } } if (ObjectAnimationUpdates != null) @@ -5686,6 +5719,123 @@ namespace OpenSim.Region.ClientStack.LindenUDP return block; } + + protected void CreateImprovedTerseBlock(ISceneEntity entity, byte[] data, ref int pos) + { + #region ScenePresence/SOP Handling + + bool avatar = (entity is ScenePresence); + uint localID = entity.LocalId; + uint attachPoint; + Vector4 collisionPlane; + Vector3 position, velocity, acceleration, angularVelocity; + Quaternion rotation; + byte datasize; + + if (avatar) + { + ScenePresence presence = (ScenePresence)entity; + + position = presence.OffsetPosition; + velocity = presence.Velocity; + acceleration = Vector3.Zero; + rotation = presence.Rotation; + // tpvs can only see rotations around Z in some cases + if (!presence.Flying && !presence.IsSatOnObject) + { + rotation.X = 0f; + rotation.Y = 0f; + } + rotation.Normalize(); + angularVelocity = presence.AngularVelocity; + + // m_log.DebugFormat( + // "[LLCLIENTVIEW]: Sending terse update to {0} with position {1} in {2}", Name, presence.OffsetPosition, m_scene.Name); + + attachPoint = presence.State; + collisionPlane = presence.CollisionPlane; + + datasize = 60; + } + else + { + SceneObjectPart part = (SceneObjectPart)entity; + + attachPoint = part.ParentGroup.AttachmentPoint; + attachPoint = ((attachPoint % 16) * 16 + (attachPoint / 16)); + // m_log.DebugFormat( + // "[LLCLIENTVIEW]: Sending attachPoint {0} for {1} {2} to {3}", + // attachPoint, part.Name, part.LocalId, Name); + + collisionPlane = Vector4.Zero; + position = part.RelativePosition; + velocity = part.Velocity; + acceleration = part.Acceleration; + angularVelocity = part.AngularVelocity; + rotation = part.RotationOffset; + + datasize = 44; + } + + #endregion ScenePresence/SOP Handling + //object block size + data[pos++] = datasize; + + // LocalID + Utils.UIntToBytes(localID, data, pos); + pos += 4; + + // Avatar/CollisionPlane + data[pos++] = (byte)attachPoint; + if (avatar) + { + data[pos++] = 1; + + if (collisionPlane == Vector4.Zero) + collisionPlane = Vector4.UnitW; + //m_log.DebugFormat("CollisionPlane: {0}",collisionPlane); + collisionPlane.ToBytes(data, pos); + pos += 16; + } + else + { + data[pos++] = 0; + } + + // Position + position.ToBytes(data, pos); + pos += 12; + + // Velocity + ClampVectorForUint(ref velocity, 128f); + Utils.FloatToUInt16Bytes(velocity.X, 128.0f, data, pos); pos += 2; + Utils.FloatToUInt16Bytes(velocity.Y, 128.0f, data, pos); pos += 2; + Utils.FloatToUInt16Bytes(velocity.Z, 128.0f, data, pos); pos += 2; + + // Acceleration + ClampVectorForUint(ref acceleration, 64f); + Utils.FloatToUInt16Bytes(acceleration.X, 64.0f, data, pos); pos += 2; + Utils.FloatToUInt16Bytes(acceleration.Y, 64.0f, data, pos); pos += 2; + Utils.FloatToUInt16Bytes(acceleration.Z, 64.0f, data, pos); pos += 2; + + // Rotation + Utils.FloatToUInt16Bytes(rotation.X, 1.0f, data, pos); pos += 2; + Utils.FloatToUInt16Bytes(rotation.Y, 1.0f, data, pos); pos += 2; + Utils.FloatToUInt16Bytes(rotation.Z, 1.0f, data, pos); pos += 2; + Utils.FloatToUInt16Bytes(rotation.W, 1.0f, data, pos); pos += 2; + + // Angular Velocity + ClampVectorForUint(ref angularVelocity, 64f); + Utils.FloatToUInt16Bytes(angularVelocity.X, 64.0f, data, pos); pos += 2; + Utils.FloatToUInt16Bytes(angularVelocity.Y, 64.0f, data, pos); pos += 2; + Utils.FloatToUInt16Bytes(angularVelocity.Z, 64.0f, data, pos); pos += 2; + + // texture entry block size + data[pos++] = 0; + data[pos++] = 0; + // total size 63 or 47 + } + protected ObjectUpdatePacket.ObjectDataBlock CreateAvatarUpdateBlock(ScenePresence data) { Vector3 offsetPosition = data.OffsetPosition; diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs index fca7943..d0d2152 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs @@ -575,22 +575,22 @@ namespace OpenSim.Region.ClientStack.LindenUDP { DoubleLocklessQueue queue = m_packetOutboxes[category]; - if (m_deliverPackets == false) + if (forceQueue || m_deliverPackets == false) { queue.Enqueue(packet, highPriority); return true; } - TokenBucket bucket = m_throttleCategories[category]; - - // Don't send this packet if queue is not empty + // need to enqueue if queue is not empty if (queue.Count > 0 || m_nextPackets[category] != null) { queue.Enqueue(packet, highPriority); return true; } - if (!forceQueue && bucket.CheckTokens(packet.Buffer.DataLength)) + // check bandwidth + TokenBucket bucket = m_throttleCategories[category]; + if (bucket.CheckTokens(packet.Buffer.DataLength)) { // enough tokens so it can be sent imediatly by caller bucket.RemoveTokens(packet.Buffer.DataLength); @@ -608,7 +608,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP // We don't have a token bucket for this category, so it will not be queued return false; } - } /// diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs index d324623..f12b3b9 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs @@ -934,6 +934,27 @@ namespace OpenSim.Region.ClientStack.LindenUDP #endregion Queue or Send } + public void SendUDPPacket( + LLUDPClient udpClient, UDPPacketBuffer buffer, ThrottleOutPacketType category, UnackedPacketMethod method, bool forcequeue) + { + bool highPriority = false; + + if (category != ThrottleOutPacketType.Unknown && (category & ThrottleOutPacketType.HighPriority) != 0) + { + category = (ThrottleOutPacketType)((int)category & 127); + highPriority = true; + } + + OutgoingPacket outgoingPacket = new OutgoingPacket(udpClient, buffer, category, null); + + // If we were not provided a method for handling unacked, use the UDPServer default method + if ((outgoingPacket.Buffer.Data[0] & Helpers.MSG_RELIABLE) != 0) + outgoingPacket.UnackedMethod = ((method == null) ? delegate (OutgoingPacket oPacket) { ResendUnacked(oPacket); } : method); + + if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket, forcequeue, highPriority)) + SendPacketFinal(outgoingPacket); + } + public void SendAcks(LLUDPClient udpClient) { uint ack; diff --git a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs index 6f346d3..49aca3c 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs @@ -489,7 +489,7 @@ namespace OpenMetaverse public void SyncSend(UDPPacketBuffer buf) { if(buf.RemoteEndPoint == null) - return; // was already expired + return; // already expired try { m_udpSocket.SendTo( -- cgit v1.1 From bd1b992aaf57154fd57403348a1ab63bfd918ad9 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Wed, 27 Feb 2019 07:49:52 -0800 Subject: Add Thread.ResetAbort() to various thread loops to clean up errors on shutdown. Fixes Mantis #8494. Threads are aborted when shutting down and ThreadAbortException is odd in that it is rethrown at the end of the catch unless the abort is reset. No functional changes but fewer error messages on shutdown. --- .../ClientStack/Linden/Caps/GetAssetsModule.cs | 25 ++++++++++++++-------- .../Linden/Caps/WebFetchInvDescModule.cs | 23 ++++++++++++++------ .../Region/ClientStack/Linden/UDP/LLUDPServer.cs | 6 +++++- 3 files changed, 37 insertions(+), 17 deletions(-) mode change 100644 => 100755 OpenSim/Region/ClientStack/Linden/Caps/GetAssetsModule.cs mode change 100644 => 100755 OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs mode change 100644 => 100755 OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs (limited to 'OpenSim/Region/ClientStack') diff --git a/OpenSim/Region/ClientStack/Linden/Caps/GetAssetsModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/GetAssetsModule.cs old mode 100644 new mode 100755 index 9187979..734425b --- a/OpenSim/Region/ClientStack/Linden/Caps/GetAssetsModule.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/GetAssetsModule.cs @@ -204,19 +204,26 @@ namespace OpenSim.Region.ClientStack.Linden private static void DoAssetRequests() { - while (m_NumberScenes > 0) + try { - APollRequest poolreq; - if(m_queue.TryTake(out poolreq, 4500)) + while (m_NumberScenes > 0) { - if (m_NumberScenes <= 0) - break; + APollRequest poolreq; + if (m_queue.TryTake(out poolreq, 4500)) + { + if (m_NumberScenes <= 0) + break; + Watchdog.UpdateThread(); + if (poolreq.reqID != UUID.Zero) + poolreq.thepoll.Process(poolreq); + poolreq = null; + } Watchdog.UpdateThread(); - if (poolreq.reqID != UUID.Zero) - poolreq.thepoll.Process(poolreq); - poolreq = null; } - Watchdog.UpdateThread(); + } + catch (ThreadAbortException) + { + Thread.ResetAbort(); } } diff --git a/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs old mode 100644 new mode 100755 index 41d70a3..9a01567 --- a/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs @@ -395,17 +395,26 @@ namespace OpenSim.Region.ClientStack.Linden private static void DoInventoryRequests() { - while (true) + bool running = true; + while (running) { - APollRequest poolreq; - if (m_queue.TryTake(out poolreq, 4500)) + try { + APollRequest poolreq; + if (m_queue.TryTake(out poolreq, 4500)) + { + Watchdog.UpdateThread(); + if (poolreq.thepoll != null) + poolreq.thepoll.Process(poolreq); + poolreq = null; + } Watchdog.UpdateThread(); - if (poolreq.thepoll != null) - poolreq.thepoll.Process(poolreq); - poolreq = null; } - Watchdog.UpdateThread(); + catch (ThreadAbortException) + { + Thread.ResetAbort(); + running = false; + } } } } diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs old mode 100644 new mode 100755 index f12b3b9..653f648 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs @@ -1910,7 +1910,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP incomingPacket = null; } } - catch(Exception ex) + catch (ThreadAbortException) + { + Thread.ResetAbort(); + } + catch (Exception ex) { m_log.Error("[LLUDPSERVER]: Error in the incoming packet handler loop: " + ex.Message, ex); } -- cgit v1.1 From 8a8ce8b10a4f595ebe25d52e439b1f1708c4262c Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Fri, 1 Mar 2019 11:57:52 +0000 Subject: put back assetViewer cap code, to allow viewers testing. It is disabled at OpenSimDefaults, and should not be enabled until all major viewers do it right on opensim --- OpenSim/Region/ClientStack/Linden/Caps/GetAssetsModule.cs | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) (limited to 'OpenSim/Region/ClientStack') diff --git a/OpenSim/Region/ClientStack/Linden/Caps/GetAssetsModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/GetAssetsModule.cs index 734425b..c071bd1 100755 --- a/OpenSim/Region/ClientStack/Linden/Caps/GetAssetsModule.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/GetAssetsModule.cs @@ -59,7 +59,7 @@ namespace OpenSim.Region.ClientStack.Linden private string m_GetTextureURL; private string m_GetMeshURL; private string m_GetMesh2URL; -// private string m_GetAssetURL; + private string m_GetAssetURL; class APollRequest { @@ -87,7 +87,7 @@ namespace OpenSim.Region.ClientStack.Linden private Dictionary m_capsDictTexture = new Dictionary(); private Dictionary m_capsDictGetMesh = new Dictionary(); private Dictionary m_capsDictGetMesh2 = new Dictionary(); - //private Dictionary m_capsDictGetAsset = new Dictionary(); + private Dictionary m_capsDictGetAsset = new Dictionary(); #region Region Module interfaceBase Members @@ -113,11 +113,11 @@ namespace OpenSim.Region.ClientStack.Linden m_GetMesh2URL = config.GetString("Cap_GetMesh2", string.Empty); if (m_GetMesh2URL != string.Empty) m_Enabled = true; -/* + m_GetAssetURL = config.GetString("Cap_GetAsset", string.Empty); if (m_GetAssetURL != string.Empty) m_Enabled = true; -*/ + } public void AddRegion(Scene pScene) @@ -448,7 +448,6 @@ namespace OpenSim.Region.ClientStack.Linden else if (m_GetMesh2URL != string.Empty) caps.RegisterHandler("GetMesh2", m_GetMesh2URL); -/* we can't support this cap. Current viewers connect to the wrong regions. //ViewerAsset if (m_GetAssetURL == "localhost") { @@ -466,7 +465,7 @@ namespace OpenSim.Region.ClientStack.Linden } else if (m_GetAssetURL != string.Empty) caps.RegisterHandler("ViewerAsset", m_GetMesh2URL); -*/ + } private void DeregisterCaps(UUID agentID, Caps caps) @@ -487,13 +486,12 @@ namespace OpenSim.Region.ClientStack.Linden MainServer.Instance.RemovePollServiceHTTPHandler("", capUrl); m_capsDictGetMesh2.Remove(agentID); } -/* + if (m_capsDictGetAsset.TryGetValue(agentID, out capUrl)) { MainServer.Instance.RemovePollServiceHTTPHandler("", capUrl); m_capsDictGetAsset.Remove(agentID); } -*/ } } } -- cgit v1.1 From ca1993c72d53d5052cea4fef56481c9a54645fca Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Sat, 2 Mar 2019 18:23:29 +0000 Subject: direct encode lludp terse object update, let contain texture entry --- .../Region/ClientStack/Linden/UDP/LLClientView.cs | 93 +++++++++++++++------- 1 file changed, 63 insertions(+), 30 deletions(-) (limited to 'OpenSim/Region/ClientStack') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index a9edf08..da4c1fb 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -4120,10 +4120,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP float cullingrange = 64.0f; Vector3 mypos = Vector3.Zero; - bool orderedDequeue = m_scene.UpdatePrioritizationScheme == UpdatePrioritizationSchemes.SimpleAngularDistance; + //bool orderedDequeue = m_scene.UpdatePrioritizationScheme == UpdatePrioritizationSchemes.SimpleAngularDistance; + bool orderedDequeue = false; // temporary off HashSet GroupsNeedFullUpdate = new HashSet(); + if (doCulling) { cullingrange = mysp.DrawDistance + m_scene.ReprioritizationDistance + 16f; @@ -4304,7 +4306,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP PrimUpdateFlags.Velocity | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity | - PrimUpdateFlags.CollisionPlane + PrimUpdateFlags.CollisionPlane | + PrimUpdateFlags.Textures ); #endregion UpdateFlags to packet type conversion @@ -4347,7 +4350,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP maxUpdatesBytes -= 18; } terseUpdates.Add(update); - maxUpdatesBytes -= 47; // no texture entry + maxUpdatesBytes -= 47; + if ((updateFlags & PrimUpdateFlags.Textures) != 0) + maxUpdatesBytes -= 100; // aprox } } else @@ -4390,7 +4395,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP UDPPacketBuffer buf = m_udpServer.GetNewUDPBuffer(m_udpClient.RemoteEndPoint); //setup header and regioninfo block - Array.Copy(terseUpdateHeader, buf.Data, 7); + Buffer.BlockCopy(terseUpdateHeader, 0, buf.Data, 0, 7); Utils.UInt64ToBytesSafepos(m_scene.RegionInfo.RegionHandle, buf.Data, 7); Utils.UInt16ToBytes(timeDilation, buf.Data, 15); buf.Data[17] = (byte)curNBlocks; @@ -4399,7 +4404,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP int count = 0; foreach (EntityUpdate eu in terseAgentUpdates) { - CreateImprovedTerseBlock(eu.Entity, buf.Data, ref pos); + CreateImprovedTerseBlock(eu.Entity, buf.Data, ref pos, false); tau.Add(eu); ++count; --blocks; @@ -4407,7 +4412,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP { // we need more packets UDPPacketBuffer newbuf = m_udpServer.GetNewUDPBuffer(m_udpClient.RemoteEndPoint); - Array.Copy(buf.Data, newbuf.Data, 17); // start is the same + Buffer.BlockCopy(buf.Data, 0, newbuf.Data, 0, 17); // start is the same buf.DataLength = pos; m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Unknown, @@ -4455,49 +4460,57 @@ namespace OpenSim.Region.ClientStack.LindenUDP */ if (terseUpdates != null) { - const int maxNBlocks = (LLUDPServer.MTU - 18) / 47; // no texture entry int blocks = terseUpdates.Count; - int curNBlocks = blocks > maxNBlocks ? maxNBlocks : blocks; - List tau = new List(curNBlocks); + List tau = new List(30); UDPPacketBuffer buf = m_udpServer.GetNewUDPBuffer(m_udpClient.RemoteEndPoint); //setup header and regioninfo block - Array.Copy(terseUpdateHeader, buf.Data, 7); + Buffer.BlockCopy(terseUpdateHeader, 0, buf.Data, 0, 7); Utils.UInt64ToBytesSafepos(m_scene.RegionInfo.RegionHandle, buf.Data, 7); Utils.UInt16ToBytes(timeDilation, buf.Data, 15); - buf.Data[17] = (byte)curNBlocks; int pos = 18; + int lastpos = 0; int count = 0; foreach (EntityUpdate eu in terseUpdates) { - CreateImprovedTerseBlock(eu.Entity, buf.Data, ref pos); - tau.Add(eu); - ++count; - --blocks; - if (count == curNBlocks && blocks > 0) + lastpos = pos; + CreateImprovedTerseBlock(eu.Entity, buf.Data, ref pos, (eu.Flags & PrimUpdateFlags.Textures) != 0); + if (pos <= LLUDPServer.MTU) + { + tau.Add(eu); + ++count; + --blocks; + } + else if (blocks > 0) { // we need more packets UDPPacketBuffer newbuf = m_udpServer.GetNewUDPBuffer(m_udpClient.RemoteEndPoint); - Array.Copy(buf.Data, newbuf.Data, 17); // start is the same + Buffer.BlockCopy(buf.Data, 0, newbuf.Data, 0, 17); // start is the same + // copy what we done in excess + int extralen = pos - lastpos; + if(extralen > 0) + Buffer.BlockCopy(newbuf.Data, 18, buf.Data, lastpos, extralen); - buf.DataLength = pos; + pos = 18 + extralen; + + buf.Data[17] = (byte)count; + buf.DataLength = lastpos; m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task, delegate (OutgoingPacket oPacket) { ResendPrimUpdates(tau, oPacket); }, false); - curNBlocks = blocks > maxNBlocks ? maxNBlocks : blocks; - tau = new List(curNBlocks); - count = 0; - + tau = new List(30); + tau.Add(eu); + count = 1; + --blocks; buf = newbuf; - buf.Data[17] = (byte)curNBlocks; - pos = 18; } } if (count > 0) { + buf.Data[17] = (byte)count; buf.DataLength = pos; m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task, delegate (OutgoingPacket oPacket) { ResendPrimUpdates(tau, oPacket); }, false); @@ -5720,7 +5733,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP } - protected void CreateImprovedTerseBlock(ISceneEntity entity, byte[] data, ref int pos) + protected void CreateImprovedTerseBlock(ISceneEntity entity, byte[] data, ref int pos, bool includeTexture) { #region ScenePresence/SOP Handling @@ -5731,6 +5744,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP Vector3 position, velocity, acceleration, angularVelocity; Quaternion rotation; byte datasize; + byte[] te = null; if (avatar) { @@ -5775,6 +5789,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP rotation = part.RotationOffset; datasize = 44; + if(includeTexture) + te = part.Shape.TextureEntry; } #endregion ScenePresence/SOP Handling @@ -5785,8 +5801,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP Utils.UIntToBytes(localID, data, pos); pos += 4; - // Avatar/CollisionPlane data[pos++] = (byte)attachPoint; + + // Avatar/CollisionPlane if (avatar) { data[pos++] = 1; @@ -5829,11 +5846,27 @@ namespace OpenSim.Region.ClientStack.LindenUDP Utils.FloatToUInt16Bytes(angularVelocity.X, 64.0f, data, pos); pos += 2; Utils.FloatToUInt16Bytes(angularVelocity.Y, 64.0f, data, pos); pos += 2; Utils.FloatToUInt16Bytes(angularVelocity.Z, 64.0f, data, pos); pos += 2; - + // texture entry block size - data[pos++] = 0; - data[pos++] = 0; - // total size 63 or 47 + if(te == null) + { + data[pos++] = 0; + data[pos++] = 0; + } + else + { + int len = te.Length & 0x7fff; + int totlen = len + 4; + data[pos++] = (byte)totlen; + data[pos++] = (byte)(totlen >> 8); + data[pos++] = (byte)len; // wtf ??? + data[pos++] = (byte)(len >> 8); + data[pos++] = 0; + data[pos++] = 0; + Buffer.BlockCopy(te, 0, data, pos, len); + pos += len; + } + // total size 63 or 47 + (texture size + 4) } protected ObjectUpdatePacket.ObjectDataBlock CreateAvatarUpdateBlock(ScenePresence data) -- cgit v1.1 From 80056abbe71a5946b6f20d33069e12c952af9eeb Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Sun, 3 Mar 2019 12:15:28 +0000 Subject: OOOPPPSSS --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'OpenSim/Region/ClientStack') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index da4c1fb..e039fbf 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -4477,7 +4477,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP { lastpos = pos; CreateImprovedTerseBlock(eu.Entity, buf.Data, ref pos, (eu.Flags & PrimUpdateFlags.Textures) != 0); - if (pos <= LLUDPServer.MTU) + if (pos < LLUDPServer.MTU) { tau.Add(eu); ++count; @@ -4491,7 +4491,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP // copy what we done in excess int extralen = pos - lastpos; if(extralen > 0) - Buffer.BlockCopy(newbuf.Data, 18, buf.Data, lastpos, extralen); + Buffer.BlockCopy(buf.Data, lastpos, newbuf.Data, 18, extralen); pos = 18 + extralen; -- cgit v1.1 From b5ad1b7dcc3592dfa49298636948ea117132e6ff Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Tue, 5 Mar 2019 09:22:34 +0000 Subject: remove lludp throttle texture rate cannibal option. That rate is used by http, and beeing http is still trafic --- OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs | 14 -------------- OpenSim/Region/ClientStack/Linden/UDP/ThrottleRates.cs | 9 --------- 2 files changed, 23 deletions(-) (limited to 'OpenSim/Region/ClientStack') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs index d0d2152..2981337 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs @@ -210,12 +210,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP } } - /// - /// This is the percentage of the udp texture queue to add to the task queue since - /// textures are now generally handled through http. - /// - private double m_cannibalrate = 0.0; - private ClientInfo m_info = new ClientInfo(); /// @@ -257,8 +251,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP // Create an array of token buckets for this clients different throttle categories m_throttleCategories = new TokenBucket[THROTTLE_CATEGORY_COUNT]; - m_cannibalrate = rates.CannibalizeTextureRate; - m_burst = rates.Total * rates.BrustTime; for (int i = 0; i < THROTTLE_CATEGORY_COUNT; i++) @@ -449,12 +441,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP asset = Math.Max(asset, LLUDPServer.MTU); */ - // Since most textures are now delivered through http, make it possible - // to cannibalize some of the bw from the texture throttle to use for - // the task queue (e.g. object updates) - task = task + (int)(m_cannibalrate * texture); - texture = (int)((1 - m_cannibalrate) * texture); - int total = resend + land + wind + cloud + task + texture + asset; float m_burst = total * m_burstTime; diff --git a/OpenSim/Region/ClientStack/Linden/UDP/ThrottleRates.cs b/OpenSim/Region/ClientStack/Linden/UDP/ThrottleRates.cs index f8ec97a..3277638 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/ThrottleRates.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/ThrottleRates.cs @@ -66,9 +66,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// public Int64 MinimumAdaptiveThrottleRate; - /// Amount of the texture throttle to steal for the task throttle - public double CannibalizeTextureRate; - public int ClientMaxRate; public float BrustTime; @@ -104,12 +101,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP // AdaptiveThrottlesEnabled = throttleConfig.GetBoolean("enable_adaptive_throttles", false); AdaptiveThrottlesEnabled = false; MinimumAdaptiveThrottleRate = throttleConfig.GetInt("adaptive_throttle_min_bps", 32000); - - // http textures do use udp bandwidth setting -// CannibalizeTextureRate = (double)throttleConfig.GetFloat("CannibalizeTextureRate", 0.0f); -// CannibalizeTextureRate = Util.Clamp(CannibalizeTextureRate,0.0, 0.9); - CannibalizeTextureRate = 0f; - } catch (Exception) { } } -- cgit v1.1 From 0944a965172668827a3f1cd83c1f99230299cbb7 Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Tue, 5 Mar 2019 16:01:29 +0000 Subject: llupd direct encode object updates for agents; let terse updates be zeroencoded. This is not as spec but does work --- .../Region/ClientStack/Linden/UDP/LLClientView.cs | 251 ++++++++++++--------- .../Region/ClientStack/Linden/UDP/LLUDPServer.cs | 70 +++++- 2 files changed, 212 insertions(+), 109 deletions(-) (limited to 'OpenSim/Region/ClientStack') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index e039fbf..f8ff3c4 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -3891,29 +3891,40 @@ namespace OpenSim.Region.ClientStack.LindenUDP if (ent == null) return; - ObjectUpdatePacket objupdate = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate); - objupdate.Header.Zerocoded = true; - - objupdate.RegionData.TimeDilation = Utils.FloatToUInt16(m_scene.TimeDilation, 0.0f, 1.0f); - objupdate.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[1]; - - if(ent is ScenePresence) + if (ent is ScenePresence) { ScenePresence presence = ent as ScenePresence; - objupdate.RegionData.RegionHandle = presence.RegionHandle; - objupdate.ObjectData[0] = CreateAvatarUpdateBlock(presence); + + UDPPacketBuffer buf = m_udpServer.GetNewUDPBuffer(m_udpClient.RemoteEndPoint); + + //setup header and regioninfo block + Buffer.BlockCopy(objectUpdateHeader, 0, buf.Data, 0, 7); + Utils.UInt64ToBytesSafepos(m_scene.RegionInfo.RegionHandle, buf.Data, 7); + Utils.UInt16ToBytes(Utils.FloatToUInt16(m_scene.TimeDilation, 0.0f, 1.0f), buf.Data, 15); + + buf.Data[17] = 1; + int pos = 18; + CreateAvatarUpdateBlock(presence, buf.Data, ref pos); + + buf.DataLength = pos; + m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task | ThrottleOutPacketType.HighPriority, null, false, true); } + else if(ent is SceneObjectPart) { + ObjectUpdatePacket objupdate = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate); + objupdate.RegionData.TimeDilation = Utils.FloatToUInt16(m_scene.TimeDilation, 0.0f, 1.0f); + objupdate.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[1]; + SceneObjectPart part = ent as SceneObjectPart; objupdate.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; - objupdate.ObjectData[0] = CreatePrimUpdateBlock(part, (ScenePresence)SceneAgent); - } + objupdate.ObjectData[0] = CreatePrimUpdateBlock(part, (ScenePresence)SceneAgent); - OutPacket(objupdate, ThrottleOutPacketType.Task | ThrottleOutPacketType.HighPriority); + OutPacket(objupdate, ThrottleOutPacketType.Task); + } // We need to record the avatar local id since the root prim of an attachment points to this. -// m_attachmentsSent.Add(avatar.LocalId); + // m_attachmentsSent.Add(avatar.LocalId); } public void SendEntityTerseUpdateImmediate(ISceneEntity ent) @@ -4084,8 +4095,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP ResendPrimUpdate(update); } + static private readonly byte[] objectUpdateHeader = new byte[] { + Helpers.MSG_RELIABLE | Helpers.MSG_ZEROCODED, + 0, 0, 0, 0, // sequence number + 0, // extra + 12 // ID (high frequency) + }; + static private readonly byte[] terseUpdateHeader = new byte[] { - Helpers.MSG_RELIABLE, + Helpers.MSG_RELIABLE | Helpers.MSG_ZEROCODED, // zero code is not as spec 0, 0, 0, 0, // sequence number 0, // extra 15 // ID (high frequency) @@ -4105,7 +4123,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP List objectUpdates = null; // List compressedUpdates = null; List terseUpdates = null; - List terseAgentUpdates = null; List ObjectAnimationUpdates = null; // Check to see if this is a flush @@ -4275,7 +4292,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP if(ObjectAnimationUpdates == null) ObjectAnimationUpdates = new List(); ObjectAnimationUpdates.Add(sop); - maxUpdatesBytes -= 32 * sop.Animations.Count + 16; + maxUpdatesBytes -= 20 * sop.Animations.Count + 24; } } } @@ -4329,37 +4346,30 @@ namespace OpenSim.Region.ClientStack.LindenUDP if ((updateFlags & canNotUseImprovedMask) == 0) { + if (terseUpdates == null) + { + terseUpdates = new List(); + maxUpdatesBytes -= 18; + } + terseUpdates.Add(update); if (update.Entity is ScenePresence) - { - // ALL presence updates go into a special list - if (terseAgentUpdates == null) - { - terseAgentUpdates = new List(); - maxUpdatesBytes -= 18; - } - terseAgentUpdates.Add(update); maxUpdatesBytes -= 63; // no texture entry - } else { - // Everything else goes here - if (terseUpdates == null) - { - terseUpdates = new List(); - maxUpdatesBytes -= 18; - } - terseUpdates.Add(update); - maxUpdatesBytes -= 47; - if ((updateFlags & PrimUpdateFlags.Textures) != 0) - maxUpdatesBytes -= 100; // aprox + if ((updateFlags & PrimUpdateFlags.Textures) == 0) + maxUpdatesBytes -= 47; + else + maxUpdatesBytes -= 150; // aprox } } else { ObjectUpdatePacket.ObjectDataBlock ablock; if (update.Entity is ScenePresence) + { ablock = CreateAvatarUpdateBlock((ScenePresence)update.Entity); + } else ablock = CreatePrimUpdateBlock((SceneObjectPart)update.Entity, mysp); if(objectUpdateBlocks == null) @@ -4385,57 +4395,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP timeDilation = Utils.FloatToUInt16(m_scene.TimeDilation, 0.0f, 1.0f); - if (terseAgentUpdates != null) - { - const int maxNBlocks = (LLUDPServer.MTU - 18) / 63; // no texture entry - int blocks = terseAgentUpdates.Count; - int curNBlocks = blocks > maxNBlocks ? maxNBlocks : blocks; - List tau = new List(curNBlocks); - - UDPPacketBuffer buf = m_udpServer.GetNewUDPBuffer(m_udpClient.RemoteEndPoint); - - //setup header and regioninfo block - Buffer.BlockCopy(terseUpdateHeader, 0, buf.Data, 0, 7); - Utils.UInt64ToBytesSafepos(m_scene.RegionInfo.RegionHandle, buf.Data, 7); - Utils.UInt16ToBytes(timeDilation, buf.Data, 15); - buf.Data[17] = (byte)curNBlocks; - int pos = 18; - - int count = 0; - foreach (EntityUpdate eu in terseAgentUpdates) - { - CreateImprovedTerseBlock(eu.Entity, buf.Data, ref pos, false); - tau.Add(eu); - ++count; - --blocks; - if (count == curNBlocks && blocks > 0) - { - // we need more packets - UDPPacketBuffer newbuf = m_udpServer.GetNewUDPBuffer(m_udpClient.RemoteEndPoint); - Buffer.BlockCopy(buf.Data, 0, newbuf.Data, 0, 17); // start is the same - - buf.DataLength = pos; - m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Unknown, - delegate (OutgoingPacket oPacket) { ResendPrimUpdates(tau, oPacket); }, false); - - curNBlocks = blocks > maxNBlocks ? maxNBlocks : blocks; - tau = new List(curNBlocks); - count = 0; - - buf = newbuf; - buf.Data[17] = (byte)curNBlocks; - pos = 18; - } - } - - if (count > 0) - { - buf.DataLength = pos; - m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Unknown, - delegate (OutgoingPacket oPacket) { ResendPrimUpdates(tau, oPacket); }, false); - } - } - if (objectUpdateBlocks != null) { ObjectUpdatePacket packet = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate); @@ -4497,8 +4456,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP buf.Data[17] = (byte)count; buf.DataLength = lastpos; + // zero encode is not as spec m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task, - delegate (OutgoingPacket oPacket) { ResendPrimUpdates(tau, oPacket); }, false); + delegate (OutgoingPacket oPacket) { ResendPrimUpdates(tau, oPacket); }, false, true); tau = new List(30); tau.Add(eu); @@ -4513,7 +4473,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP buf.Data[17] = (byte)count; buf.DataLength = pos; m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task, - delegate (OutgoingPacket oPacket) { ResendPrimUpdates(tau, oPacket); }, false); + delegate (OutgoingPacket oPacket) { ResendPrimUpdates(tau, oPacket); }, false, true); } } @@ -4534,13 +4494,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP UUID[] ids = null; int[] seqs = null; int count = sop.GetAnimations(out ids, out seqs); - if(count < 0) - continue; ObjectAnimationPacket ani = (ObjectAnimationPacket)PacketPool.Instance.GetPacket(PacketType.ObjectAnimation); ani.Sender = new ObjectAnimationPacket.SenderBlock(); ani.Sender.ID = sop.UUID; - ani.AnimationList = new ObjectAnimationPacket.AnimationListBlock[sop.Animations.Count]; + ani.AnimationList = new ObjectAnimationPacket.AnimationListBlock[count]; for(int i = 0; i< count; i++) { @@ -5732,7 +5690,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP return block; } - protected void CreateImprovedTerseBlock(ISceneEntity entity, byte[] data, ref int pos, bool includeTexture) { #region ScenePresence/SOP Handling @@ -5871,7 +5828,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP protected ObjectUpdatePacket.ObjectDataBlock CreateAvatarUpdateBlock(ScenePresence data) { - Vector3 offsetPosition = data.OffsetPosition; Quaternion rotation = data.Rotation; // tpvs can only see rotations around Z in some cases if(!data.Flying && !data.IsSatOnObject) @@ -5881,27 +5837,26 @@ namespace OpenSim.Region.ClientStack.LindenUDP } rotation.Normalize(); - uint parentID = data.ParentID; - // m_log.DebugFormat( // "[LLCLIENTVIEW]: Sending full update to {0} with pos {1}, vel {2} in {3}", Name, data.OffsetPosition, data.Velocity, m_scene.Name); byte[] objectData = new byte[76]; - Vector3 velocity = new Vector3(0, 0, 0); - Vector3 acceleration = new Vector3(0, 0, 0); + //Vector3 velocity = Vector3.Zero; + Vector3 acceleration = Vector3.Zero; + Vector3 angularvelocity = Vector3.Zero; data.CollisionPlane.ToBytes(objectData, 0); - offsetPosition.ToBytes(objectData, 16); - velocity.ToBytes(objectData, 28); + data.OffsetPosition.ToBytes(objectData, 16); + data.Velocity.ToBytes(objectData, 28); acceleration.ToBytes(objectData, 40); rotation.ToBytes(objectData, 52); - data.AngularVelocity.ToBytes(objectData, 64); + angularvelocity.ToBytes(objectData, 64); ObjectUpdatePacket.ObjectDataBlock update = new ObjectUpdatePacket.ObjectDataBlock(); update.Data = Utils.EmptyBytes; - update.ExtraParams = new byte[1]; + update.ExtraParams = Utils.EmptyBytes; update.FullID = data.UUID; update.ID = data.LocalId; update.Material = (byte)Material.Flesh; @@ -5938,7 +5893,99 @@ namespace OpenSim.Region.ClientStack.LindenUDP return update; } -// protected ObjectUpdatePacket.ObjectDataBlock CreatePrimUpdateBlock(SceneObjectPart data, UUID recipientID) + protected void CreateAvatarUpdateBlock(ScenePresence data, byte[] dest, ref int pos) + { + Quaternion rotation = data.Rotation; + // tpvs can only see rotations around Z in some cases + if (!data.Flying && !data.IsSatOnObject) + { + rotation.X = 0f; + rotation.Y = 0f; + } + rotation.Normalize(); + + //Vector3 velocity = Vector3.Zero; + //Vector3 acceleration = Vector3.Zero; + //Vector3 angularvelocity = Vector3.Zero; + + Utils.UIntToBytesSafepos(data.LocalId, dest, pos); pos += 4; + dest[pos++] = 0; // state + data.UUID.ToBytes(dest, pos); pos += 16; + Utils.UIntToBytesSafepos(0 , dest, pos); pos += 4; // crc + dest[pos++] = (byte)PCode.Avatar; + dest[pos++] = (byte)Material.Flesh; + dest[pos++] = 0; // clickaction + data.Appearance.AvatarSize.ToBytes(dest, pos); pos += 12; + + // objectdata block + dest[pos++] = 76; + data.CollisionPlane.ToBytes(dest, pos); pos += 16; + data.OffsetPosition.ToBytes(dest, pos); pos += 12; + data.Velocity.ToBytes(dest, pos); pos += 12; + + //acceleration.ToBytes(dest, pos); pos += 12; + Array.Clear(dest, pos, 12); pos += 12; + + rotation.ToBytes(dest, pos); pos += 12; + + //angularvelocity.ToBytes(dest, pos); pos += 12; + Array.Clear(dest, pos, 12); pos += 12; + + SceneObjectPart parentPart = data.ParentPart; + if (parentPart != null) + { + Utils.UIntToBytesSafepos(parentPart.ParentGroup.LocalId, dest, pos); + pos += 4; + } + else + { +// Utils.UIntToBytesSafepos(0, dest, pos); +// pos += 4; + dest[pos++] = 0; + dest[pos++] = 0; + dest[pos++] = 0; + dest[pos++] = 0; + } + + //Utils.UIntToBytesSafepos(0, dest, pos); pos += 4; //update flags + dest[pos++] = 0; + dest[pos++] = 0; + dest[pos++] = 0; + dest[pos++] = 0; + + //pbs + dest[pos++] = 16; + dest[pos++] = 1; + //Utils.UInt16ToBytes(0, dest, pos); pos += 2; + //Utils.UInt16ToBytes(0, dest, pos); pos += 2; + dest[pos++] = 0; + dest[pos++] = 0; + dest[pos++] = 0; + dest[pos++] = 0; + + dest[pos++] = 100; + dest[pos++] = 100; + + // rest of pbs is 0 (15), texture entry (2) and texture anim (1) + const int pbszeros = 15 + 2 + 1; + Array.Clear(dest, pos, pbszeros); pos += pbszeros; + + //NameValue + byte[] nv = Utils.StringToBytes("FirstName STRING RW SV " + data.Firstname + "\nLastName STRING RW SV " + + data.Lastname + "\nTitle STRING RW SV " + data.Grouptitle); + int len = nv.Length; + dest[pos++] = (byte)len; + dest[pos++] = (byte)(len >> 8); + Buffer.BlockCopy(nv, 0, dest, pos, len); pos += len; + + // data(2), text(1), text color(4), media url(1), PBblock(1), ExtramParams(1), + // sound id(16), sound owner(16) gain (4), flags (1), radius (4) + // jointtype(1) joint pivot(12) joint offset(12) + const int lastzeros = 2 + 1 + 4 + 1 + 1 + 1 + 16 + 16 + 4 + 1 + 4 + 1 + 12 + 12; + Array.Clear(dest, pos, lastzeros); pos += lastzeros; + } + + // protected ObjectUpdatePacket.ObjectDataBlock CreatePrimUpdateBlock(SceneObjectPart data, UUID recipientID) protected ObjectUpdatePacket.ObjectDataBlock CreatePrimUpdateBlock(SceneObjectPart part, ScenePresence sp) { byte[] objectData = new byte[60]; diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs index 653f648..6fd782a 100755 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs @@ -274,10 +274,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// The measured resolution of Environment.TickCount public readonly float TickCountResolution; - /// Number of prim updates to put on the queue each time the - /// OnQueueEmpty event is triggered for updates - public readonly int PrimUpdatesPerCallback; - /// Number of texture packets to put on the queue each time the /// OnQueueEmpty event is triggered for textures public readonly int TextureSendLimit; @@ -440,7 +436,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP m_recvBufferSize = config.GetInt("client_socket_rcvbuf_size", 0); sceneThrottleBps = config.GetInt("scene_throttle_max_bps", 0); - PrimUpdatesPerCallback = config.GetInt("PrimUpdatesPerCallback", 100); TextureSendLimit = config.GetInt("TextureSendLimit", 20); m_defaultRTO = config.GetInt("DefaultRTO", 0); @@ -451,7 +446,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP } else { - PrimUpdatesPerCallback = 100; TextureSendLimit = 20; m_ackTimeout = 1000 * 60; // 1 minute m_pausedAckTimeout = 1000 * 300; // 5 minutes @@ -934,11 +928,73 @@ namespace OpenSim.Region.ClientStack.LindenUDP #endregion Queue or Send } + public unsafe UDPPacketBuffer ZeroEncode(UDPPacketBuffer input) + { + UDPPacketBuffer zb = GetNewUDPBuffer(null); + int srclen = input.DataLength; + byte[] src = input.Data; + byte[] dest = zb.Data; + + int zerolen = 6; + byte zerocount = 0; + + for (int i = zerolen; i < srclen; i++) + { + if (src[i] == 0x00) + { + zerocount++; + if (zerocount == 0) + { + dest[zerolen++] = 0x00; + dest[zerolen++] = 0xff; + zerocount++; + } + } + else + { + if (zerocount != 0) + { + dest[zerolen++] = 0x00; + dest[zerolen++] = zerocount; + zerocount = 0; + } + + dest[zerolen++] = src[i]; + } + } + + if (zerocount != 0) + { + dest[zerolen++] = 0x00; + dest[zerolen++] = zerocount; + } + + if(zerolen >= srclen) + { + FreeUDPBuffer(zb); + + src[0] &= unchecked((byte)~Helpers.MSG_ZEROCODED); + return input; + } + + Buffer.BlockCopy(src, 0, dest, 0, 6); + + zb.RemoteEndPoint = input.RemoteEndPoint; + zb.DataLength = zerolen; + + FreeUDPBuffer(input); + + return zb; + } + public void SendUDPPacket( - LLUDPClient udpClient, UDPPacketBuffer buffer, ThrottleOutPacketType category, UnackedPacketMethod method, bool forcequeue) + LLUDPClient udpClient, UDPPacketBuffer buffer, ThrottleOutPacketType category, UnackedPacketMethod method, bool forcequeue, bool zerocode) { bool highPriority = false; + if(zerocode) + buffer = ZeroEncode(buffer); + if (category != ThrottleOutPacketType.Unknown && (category & ThrottleOutPacketType.HighPriority) != 0) { category = (ThrottleOutPacketType)((int)category & 127); -- cgit v1.1 From cf0f3954a80c480e34c2e5556e2b0581c4c23f88 Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Wed, 6 Mar 2019 20:00:39 +0000 Subject: lludp do inline zeroencode of some(most) agent full updates (runprebuild) --- .../Region/ClientStack/Linden/UDP/LLClientView.cs | 114 ++++++--- .../ClientStack/Linden/UDP/LLUDPZeroEncoder.cs | 279 +++++++++++++++++++++ 2 files changed, 356 insertions(+), 37 deletions(-) create mode 100644 OpenSim/Region/ClientStack/Linden/UDP/LLUDPZeroEncoder.cs (limited to 'OpenSim/Region/ClientStack') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index f8ff3c4..dd06e40 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -3894,22 +3894,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP if (ent is ScenePresence) { ScenePresence presence = ent as ScenePresence; - UDPPacketBuffer buf = m_udpServer.GetNewUDPBuffer(m_udpClient.RemoteEndPoint); - //setup header and regioninfo block Buffer.BlockCopy(objectUpdateHeader, 0, buf.Data, 0, 7); - Utils.UInt64ToBytesSafepos(m_scene.RegionInfo.RegionHandle, buf.Data, 7); - Utils.UInt16ToBytes(Utils.FloatToUInt16(m_scene.TimeDilation, 0.0f, 1.0f), buf.Data, 15); - - buf.Data[17] = 1; - int pos = 18; - CreateAvatarUpdateBlock(presence, buf.Data, ref pos); - buf.DataLength = pos; - m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task | ThrottleOutPacketType.HighPriority, null, false, true); + LLUDPZeroEncoder zc = new LLUDPZeroEncoder(buf.Data); + zc.Position = 7; + zc.AddUInt64(m_scene.RegionInfo.RegionHandle); + zc.AddUInt16(Utils.FloatToUInt16(m_scene.TimeDilation, 0.0f, 1.0f)); + zc.AddByte(1); // block count + CreateAvatarUpdateBlock(presence, zc); + buf.DataLength = zc.Finish(); + m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task | ThrottleOutPacketType.HighPriority, null, false, false); } - else if(ent is SceneObjectPart) { ObjectUpdatePacket objupdate = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate); @@ -5985,6 +5982,75 @@ namespace OpenSim.Region.ClientStack.LindenUDP Array.Clear(dest, pos, lastzeros); pos += lastzeros; } + protected void CreateAvatarUpdateBlock(ScenePresence data, LLUDPZeroEncoder zc) + { + Quaternion rotation = data.Rotation; + // tpvs can only see rotations around Z in some cases + if (!data.Flying && !data.IsSatOnObject) + { + rotation.X = 0f; + rotation.Y = 0f; + } + rotation.Normalize(); + + zc.AddUInt(data.LocalId); + zc.AddByte(0); + zc.AddUUID(data.UUID); + zc.AddZeros(4); // crc unused + zc.AddByte((byte)PCode.Avatar); + zc.AddByte((byte)Material.Flesh); + zc.AddByte(0); // clickaction + zc.AddVector3(data.Appearance.AvatarSize); + + // objectdata block + zc.AddByte(76); // fixed avatar block size + zc.AddVector4(data.CollisionPlane); + zc.AddVector3(data.OffsetPosition); + zc.AddVector3(data.Velocity); + //zc.AddVector3(acceleration); + zc.AddZeros(12); + zc.AddNormQuat(rotation); + //zc.AddVector3(angularvelocity); + zc.AddZeros(12); + + SceneObjectPart parentPart = data.ParentPart; + if (parentPart != null) + zc.AddUInt(parentPart.ParentGroup.LocalId); + else + zc.AddZeros(4); + + zc.AddZeros(4); //update flags + + //pbs + zc.AddByte(16); + zc.AddByte(1); + //Utils.UInt16ToBytes(0, dest, pos); pos += 2; + //Utils.UInt16ToBytes(0, dest, pos); pos += 2; + zc.AddZeros(4); + + zc.AddByte(100); + zc.AddByte(100); + + // rest of pbs is 0 (15), texture entry (2) and texture anim (1) + const int pbszeros = 15 + 2 + 1; + zc.AddZeros(pbszeros); + + //NameValue + byte[] nv = Utils.StringToBytes("FirstName STRING RW SV " + data.Firstname + "\nLastName STRING RW SV " + + data.Lastname + "\nTitle STRING RW SV " + data.Grouptitle); + int len = nv.Length; + zc.AddByte((byte)len); + zc.AddByte((byte)(len >> 8)); + zc.AddBytes(nv, len); + + // data(2), text(1), text color(4), media url(1), PBblock(1), ExtramParams(1), + // sound id(16), sound owner(16) gain (4), flags (1), radius (4) + // jointtype(1) joint pivot(12) joint offset(12) + const int lastzeros = 2 + 1 + 4 + 1 + 1 + 1 + 16 + 16 + 4 + 1 + 4 + 1 + 12 + 12; + zc.AddZeros(lastzeros); + } + + // protected ObjectUpdatePacket.ObjectDataBlock CreatePrimUpdateBlock(SceneObjectPart data, UUID recipientID) protected ObjectUpdatePacket.ObjectDataBlock CreatePrimUpdateBlock(SceneObjectPart part, ScenePresence sp) { @@ -6008,32 +6074,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP //update.JointPivot = Vector3.Zero; //update.JointType = 0; update.Material = part.Material; -/* - if (data.ParentGroup.IsAttachment) - { - update.NameValue - = Util.StringToBytes256( - string.Format("AttachItemID STRING RW SV {0}", data.ParentGroup.FromItemID)); - - update.State = (byte)((data.ParentGroup.AttachmentPoint % 16) * 16 + (data.ParentGroup.AttachmentPoint / 16)); - -// m_log.DebugFormat( -// "[LLCLIENTVIEW]: Sending NameValue {0} for {1} {2} to {3}", -// Util.UTF8.GetString(update.NameValue), data.Name, data.LocalId, Name); -// -// m_log.DebugFormat( -// "[LLCLIENTVIEW]: Sending state {0} for {1} {2} to {3}", -// update.State, data.Name, data.LocalId, Name); - } - else - { - update.NameValue = Utils.EmptyBytes; - - // The root part state is the canonical state for all parts of the object. The other part states in the - // case for attachments may contain conflicting values that can end up crashing the viewer. - update.State = data.ParentGroup.RootPart.Shape.State; - } -*/ if (part.ParentGroup.IsAttachment) { diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPZeroEncoder.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPZeroEncoder.cs new file mode 100644 index 0000000..4841ada --- /dev/null +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPZeroEncoder.cs @@ -0,0 +1,279 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using OpenSim.Framework; +using Nini.Config; +using OpenMetaverse; + +namespace OpenSim.Region.ClientStack.LindenUDP +{ + public sealed class LLUDPZeroEncoder + { + private byte[] m_tmp = new byte[16]; + private byte[] m_dest; + private int zerocount; + private int pos; + + public LLUDPZeroEncoder() + { + } + + public LLUDPZeroEncoder(byte[] data) + { + m_dest = data; + zerocount = 0; + } + + public byte[] Data + { + get + { + return m_dest; + } + set + { + m_dest = value; + } + } + + public int ZeroCount + { + get + { + return zerocount; + } + set + { + zerocount = value; + } + } + + public int Position + { + get + { + return pos; + } + set + { + pos = value; + } + } + + public unsafe void AddZeros(int len) + { + zerocount += len; + while (zerocount > 255) + { + m_dest[pos++] = 0x00; + m_dest[pos++] = 0xff; + zerocount -= 256; + } + } + + public unsafe int Finish() + { + if(zerocount > 0) + { + m_dest[pos++] = 0x00; + m_dest[pos++] = (byte)zerocount; + } + return pos; + } + + public unsafe void AddBytes(byte[] src, int srclen) + { + for (int i = 0; i < srclen; ++i) + { + if (src[i] == 0x00) + { + zerocount++; + if (zerocount == 0) + { + m_dest[pos++] = 0x00; + m_dest[pos++] = 0xff; + zerocount++; + } + } + else + { + if (zerocount != 0) + { + m_dest[pos++] = 0x00; + m_dest[pos++] = (byte)zerocount; + zerocount = 0; + } + + m_dest[pos++] = src[i]; + } + } + } + + public void AddByte(byte v) + { + if (v == 0x00) + { + zerocount++; + if (zerocount == 0) + { + m_dest[pos++] = 0x00; + m_dest[pos++] = 0xff; + zerocount++; + } + } + else + { + if (zerocount != 0) + { + m_dest[pos++] = 0x00; + m_dest[pos++] = (byte)zerocount; + zerocount = 0; + } + + m_dest[pos++] = v; + } + } + + public void AddInt16(short v) + { + if (v == 0) + AddZeros(2); + else + { + Utils.Int16ToBytes(v, m_tmp, 0); + AddBytes(m_tmp, 2); + } + } + + public void AddUInt16(ushort v) + { + if (v == 0) + AddZeros(2); + else + { + Utils.UInt16ToBytes(v, m_tmp, 0); + AddBytes(m_tmp, 2); + } + } + + public void AddInt(int v) + { + if (v == 0) + AddZeros(4); + else + { + Utils.IntToBytesSafepos(v, m_tmp, 0); + AddBytes(m_tmp, 4); + } + } + + public unsafe void AddUInt(uint v) + { + if (v == 0) + AddZeros(4); + else + { + Utils.UIntToBytesSafepos(v, m_tmp, 0); + AddBytes(m_tmp, 4); + } + } + + public void AddFloatToUInt16(float v, float range) + { + Utils.FloatToUInt16Bytes(v, range, m_tmp, 0); + AddBytes(m_tmp, 2); + } + + public void AddFloat(float v) + { + if (v == 0f) + AddZeros(4); + else + { + Utils.FloatToBytesSafepos(v, m_tmp, 0); + AddBytes(m_tmp, 4); + } + } + + public void AddInt64(long v) + { + if (v == 0) + AddZeros(8); + else + { + Utils.Int64ToBytesSafepos(v, m_tmp, 0); + AddBytes(m_tmp, 8); + } + } + + public void AddUInt64(ulong v) + { + if (v == 0) + AddZeros(8); + else + { + Utils.UInt64ToBytesSafepos(v, m_tmp, 0); + AddBytes(m_tmp, 8); + } + } + + public void AddVector3(Vector3 v) + { + if (v == Vector3.Zero) + AddZeros(12); + else + { + v.ToBytes(m_tmp, 0); + AddBytes(m_tmp, 12); + } + } + + public void AddVector4(Vector4 v) + { + if (v == Vector4.Zero) + AddZeros(16); + else + { + v.ToBytes(m_tmp, 0); + AddBytes(m_tmp, 16); + } + } + + public void AddNormQuat(Quaternion v) + { + v.ToBytes(m_tmp, 0); + AddBytes(m_tmp, 12); + } + + public void AddUUID(UUID v) + { + v.ToBytes(m_tmp, 0); + AddBytes(m_tmp, 16); + } + } +} -- cgit v1.1 From 0970dc04e2ed5482de4be589535d9eda522d3e0c Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Wed, 6 Mar 2019 22:42:37 +0000 Subject: llupd add direct encode, with inline zeroencode, of objects update ( code path currently not in use) --- .../Region/ClientStack/Linden/UDP/LLClientView.cs | 259 ++++++++++++++++++--- .../ClientStack/Linden/UDP/LLUDPZeroEncoder.cs | 2 +- 2 files changed, 227 insertions(+), 34 deletions(-) (limited to 'OpenSim/Region/ClientStack') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index dd06e40..4158adc 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -3884,44 +3884,27 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// public void SendEntityFullUpdateImmediate(ISceneEntity ent) { -// m_log.DebugFormat( -// "[LLCLIENTVIEW]: Sending immediate object update for avatar {0} {1} to {2} {3}", -// avatar.Name, avatar.UUID, Name, AgentId); - - if (ent == null) + if (ent == null || (!(ent is ScenePresence) && !(ent is SceneObjectPart))) return; - if (ent is ScenePresence) - { - ScenePresence presence = ent as ScenePresence; - UDPPacketBuffer buf = m_udpServer.GetNewUDPBuffer(m_udpClient.RemoteEndPoint); + UDPPacketBuffer buf = m_udpServer.GetNewUDPBuffer(m_udpClient.RemoteEndPoint); + Buffer.BlockCopy(objectUpdateHeader, 0, buf.Data, 0, 7); - Buffer.BlockCopy(objectUpdateHeader, 0, buf.Data, 0, 7); + LLUDPZeroEncoder zc = new LLUDPZeroEncoder(buf.Data); + zc.Position = 7; - LLUDPZeroEncoder zc = new LLUDPZeroEncoder(buf.Data); - zc.Position = 7; - zc.AddUInt64(m_scene.RegionInfo.RegionHandle); - zc.AddUInt16(Utils.FloatToUInt16(m_scene.TimeDilation, 0.0f, 1.0f)); - zc.AddByte(1); // block count - CreateAvatarUpdateBlock(presence, zc); - buf.DataLength = zc.Finish(); - m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task | ThrottleOutPacketType.HighPriority, null, false, false); - } - else if(ent is SceneObjectPart) - { - ObjectUpdatePacket objupdate = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate); - objupdate.RegionData.TimeDilation = Utils.FloatToUInt16(m_scene.TimeDilation, 0.0f, 1.0f); - objupdate.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[1]; + zc.AddUInt64(m_scene.RegionInfo.RegionHandle); + zc.AddUInt16(Utils.FloatToUInt16(m_scene.TimeDilation, 0.0f, 1.0f)); - SceneObjectPart part = ent as SceneObjectPart; - objupdate.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; - objupdate.ObjectData[0] = CreatePrimUpdateBlock(part, (ScenePresence)SceneAgent); + zc.AddByte(1); // block count - OutPacket(objupdate, ThrottleOutPacketType.Task); - } + if (ent is ScenePresence) + CreateAvatarUpdateBlock(ent as ScenePresence, zc); + else + CreatePrimUpdateBlock(ent as SceneObjectPart, (ScenePresence)SceneAgent, zc); - // We need to record the avatar local id since the root prim of an attachment points to this. - // m_attachmentsSent.Add(avatar.LocalId); + buf.DataLength = zc.Finish(); + m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task | ThrottleOutPacketType.HighPriority, null, false, false); } public void SendEntityTerseUpdateImmediate(ISceneEntity ent) @@ -6050,8 +6033,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP zc.AddZeros(lastzeros); } - - // protected ObjectUpdatePacket.ObjectDataBlock CreatePrimUpdateBlock(SceneObjectPart data, UUID recipientID) protected ObjectUpdatePacket.ObjectDataBlock CreatePrimUpdateBlock(SceneObjectPart part, ScenePresence sp) { byte[] objectData = new byte[60]; @@ -6193,6 +6174,218 @@ namespace OpenSim.Region.ClientStack.LindenUDP return update; } + protected void CreatePrimUpdateBlock(SceneObjectPart part, ScenePresence sp, LLUDPZeroEncoder zc) + { + // prepare data + + //NameValue and state + byte[] nv = null; + byte state; + if (part.ParentGroup.IsAttachment) + { + if (part.IsRoot) + nv = Util.StringToBytes256("AttachItemID STRING RW SV " + part.ParentGroup.FromItemID); + + int st = (int)part.ParentGroup.AttachmentPoint; + state = (byte)(((st & 0xf0) >> 4) + ((st & 0x0f) << 4)); ; + } + else + state = part.Shape.State; // not sure about this + + #region PrimFlags + // prim/update flags + PrimFlags primflags = (PrimFlags)m_scene.Permissions.GenerateClientFlags(part, sp); + // Don't send the CreateSelected flag to everyone + primflags &= ~PrimFlags.CreateSelected; + if (sp.UUID == part.OwnerID) + { + if (part.CreateSelected) + { + // Only send this flag once, then unset it + primflags |= PrimFlags.CreateSelected; + part.CreateSelected = false; + } + } + #endregion PrimFlags + + // filter out mesh faces hack + ushort profileBegin = part.Shape.ProfileBegin; + ushort profileHollow = part.Shape.ProfileHollow; + byte profileCurve = part.Shape.ProfileCurve; + byte pathScaleY = part.Shape.PathScaleY; + + if (part.Shape.SculptType == (byte)SculptType.Mesh) // filter out hack + { + profileCurve = (byte)(part.Shape.ProfileCurve & 0x0f); + // fix old values that confused viewers + if (profileBegin == 1) + profileBegin = 9375; + if (profileHollow == 1) + profileHollow = 27500; + // fix torus hole size Y that also confuse some viewers + if (profileCurve == (byte)ProfileShape.Circle && pathScaleY < 150) + pathScaleY = 150; + } + + // data block + byte[] data = null; + switch ((PCode)part.Shape.PCode) + { + case PCode.Grass: + case PCode.Tree: + case PCode.NewTree: + data = new byte[] { part.Shape.State }; + break; + default: + break; + } + + // do encode the things + zc.AddUInt(part.LocalId); + zc.AddByte(state); // state + zc.AddUUID(part.UUID); + zc.AddZeros(4); // crc unused + zc.AddByte(part.Shape.PCode); + zc.AddByte(part.Material); + zc.AddByte(part.ClickAction); // clickaction + zc.AddVector3(part.Shape.Scale); + + // objectdata block + zc.AddByte(60); // fixed object block size + zc.AddVector3(part.RelativePosition); + zc.AddVector3(part.Velocity); + zc.AddVector3(part.Acceleration); + Quaternion rotation = part.RotationOffset; + rotation.Normalize(); + zc.AddNormQuat(rotation); + zc.AddVector3(part.AngularVelocity); + + zc.AddUInt(part.ParentID); + zc.AddUInt((uint)primflags); //update flags + + //pbs + zc.AddByte(part.Shape.PathCurve); + zc.AddByte(profileCurve); + zc.AddUInt16(part.Shape.PathBegin); + zc.AddUInt16(part.Shape.PathEnd); + zc.AddByte(part.Shape.PathScaleX); + zc.AddByte(pathScaleY); + zc.AddByte(part.Shape.PathShearX); + zc.AddByte(part.Shape.PathShearY); + zc.AddByte((byte)part.Shape.PathTwist); + zc.AddByte((byte)part.Shape.PathTwistBegin); + zc.AddByte((byte)part.Shape.PathRadiusOffset); + zc.AddByte((byte)part.Shape.PathTaperX); + zc.AddByte((byte)part.Shape.PathTaperY); + zc.AddByte(part.Shape.PathRevolutions); + zc.AddByte((byte)part.Shape.PathSkew); + zc.AddUInt16(profileBegin); + zc.AddUInt16(part.Shape.ProfileEnd); + zc.AddUInt16(profileHollow); + + // texture + byte[] tentry = part.Shape.TextureEntry; + if (tentry == null) + zc.AddZeros(2); + else + { + int len = tentry.Length; + zc.AddUInt((ushort)len); + zc.AddBytes(tentry, len); + } + + // texture animation + byte[] tanim = part.TextureAnimation; + if (tanim == null) + zc.AddZeros(1); + else + { + int len = tanim.Length; + zc.AddByte((byte)len); + zc.AddBytes(tanim, len); + } + + //NameValue + if(nv == null) + zc.AddZeros(2); + else + { + int len = nv.Length; + zc.AddByte((byte)len); + zc.AddByte((byte)(len >> 8)); + zc.AddBytes(nv, len); + } + + // data + if (data == null) + zc.AddZeros(2); + else + { + int len = data.Length; + zc.AddByte((byte)len); + zc.AddByte((byte)(len >> 8)); + zc.AddBytes(data, len); + } + + //text + if (part.Text.Length == 0) + zc.AddZeros(1); + else + { + byte[] tbuf = Util.StringToBytes(part.Text, 255); + int len = tbuf.Length; + zc.AddByte((byte)len); + zc.AddBytes(tbuf, len); + } + + //textcolor + byte[] tc = part.GetTextColor().GetBytes(false); + zc.AddBytes(tc, 4); + + //media url + if (part.MediaUrl.Length == 0) + zc.AddZeros(1); + else + { + byte[] tbuf = Util.StringToBytes(part.MediaUrl, 255); + int len = tbuf.Length; + zc.AddByte((byte)len); + zc.AddBytes(tbuf, len); + } + + //particle system + byte[] ps = part.ParticleSystem; + if (ps == null) + zc.AddZeros(1); + else + { + int len = ps.Length; + zc.AddByte((byte)len); + zc.AddBytes(ps, len); + } + + //Extraparams + byte[] ep = part.Shape.ExtraParams; + if (ep == null) + zc.AddZeros(1); + else + { + int len = ep.Length; + zc.AddByte((byte)len); + zc.AddBytes(ep, len); + } + + zc.AddUUID(part.Sound); + zc.AddUUID(part.OwnerID); + zc.AddFloat((float)part.SoundGain); + zc.AddByte(part.SoundFlags); + zc.AddFloat((float)part.SoundRadius); + + // jointtype(1) joint pivot(12) joint offset(12) + const int lastzeros = 1 + 12 + 12; + zc.AddZeros(lastzeros); + } + protected ObjectUpdateCompressedPacket.ObjectDataBlock CreateCompressedUpdateBlock(SceneObjectPart part, PrimUpdateFlags updateFlags) { // TODO: Implement this diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPZeroEncoder.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPZeroEncoder.cs index 4841ada..8ed2cf1 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPZeroEncoder.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPZeroEncoder.cs @@ -134,7 +134,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP } } - public void AddByte(byte v) + public unsafe void AddByte(byte v) { if (v == 0x00) { -- cgit v1.1 From fdb1ce827bc2058b294fadd4cd76f43fd23e8bd7 Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Wed, 6 Mar 2019 22:48:00 +0000 Subject: fix packet type --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'OpenSim/Region/ClientStack') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 4158adc..c049cc8 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -3898,13 +3898,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP zc.AddByte(1); // block count + ThrottleOutPacketType ptype = ThrottleOutPacketType.Task; if (ent is ScenePresence) + { CreateAvatarUpdateBlock(ent as ScenePresence, zc); + ptype |= ThrottleOutPacketType.HighPriority; + } else CreatePrimUpdateBlock(ent as SceneObjectPart, (ScenePresence)SceneAgent, zc); buf.DataLength = zc.Finish(); - m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task | ThrottleOutPacketType.HighPriority, null, false, false); + m_udpServer.SendUDPPacket(m_udpClient, buf, ptype , null, false, false); } public void SendEntityTerseUpdateImmediate(ISceneEntity ent) -- cgit v1.1 From 9487f5cdd37c3d1eae5f183d0952426a4a7eade9 Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Thu, 7 Mar 2019 04:50:05 +0000 Subject: don't send irrelevant data --- .../Region/ClientStack/Linden/UDP/LLClientView.cs | 61 +++++++++++++--------- 1 file changed, 36 insertions(+), 25 deletions(-) (limited to 'OpenSim/Region/ClientStack') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index c049cc8..691b7bb 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -6008,18 +6008,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP zc.AddZeros(4); //update flags - //pbs - zc.AddByte(16); - zc.AddByte(1); - //Utils.UInt16ToBytes(0, dest, pos); pos += 2; - //Utils.UInt16ToBytes(0, dest, pos); pos += 2; - zc.AddZeros(4); - - zc.AddByte(100); - zc.AddByte(100); - - // rest of pbs is 0 (15), texture entry (2) and texture anim (1) - const int pbszeros = 15 + 2 + 1; + //pbs volume data 23 + //texture entry 2 + //texture anim (1) + const int pbszeros = 23 + 2 + 1; zc.AddZeros(pbszeros); //NameValue @@ -6154,15 +6146,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP #endregion PrimFlags - if (part.Sound != UUID.Zero || part.SoundFlags != 0) + bool hassound = part.Sound != UUID.Zero || part.SoundFlags != 0; + if (hassound) { update.Sound = part.Sound; - update.OwnerID = part.OwnerID; update.Gain = (float)part.SoundGain; update.Radius = (float)part.SoundRadius; update.Flags = part.SoundFlags; } + if(hassound || update.PSBlock.Length > 1) + update.OwnerID = part.OwnerID; + switch ((PCode)part.Shape.PCode) { case PCode.Grass: @@ -6333,18 +6328,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP //text if (part.Text.Length == 0) - zc.AddZeros(1); + zc.AddZeros(5); else { - byte[] tbuf = Util.StringToBytes(part.Text, 255); + byte[] tbuf = Util.StringToBytes(part.Text, 254); int len = tbuf.Length; zc.AddByte((byte)len); zc.AddBytes(tbuf, len); - } - //textcolor - byte[] tc = part.GetTextColor().GetBytes(false); - zc.AddBytes(tc, 4); + //textcolor + byte[] tc = part.GetTextColor().GetBytes(false); + zc.AddBytes(tc, 4); + } //media url if (part.MediaUrl.Length == 0) @@ -6357,6 +6352,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP zc.AddBytes(tbuf, len); } + bool hasps = false; //particle system byte[] ps = part.ParticleSystem; if (ps == null) @@ -6366,6 +6362,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP int len = ps.Length; zc.AddByte((byte)len); zc.AddBytes(ps, len); + hasps = len > 1; } //Extraparams @@ -6379,11 +6376,25 @@ namespace OpenSim.Region.ClientStack.LindenUDP zc.AddBytes(ep, len); } - zc.AddUUID(part.Sound); - zc.AddUUID(part.OwnerID); - zc.AddFloat((float)part.SoundGain); - zc.AddByte(part.SoundFlags); - zc.AddFloat((float)part.SoundRadius); + bool hassound = part.Sound != UUID.Zero || part.SoundFlags != 0; + if (hassound) + zc.AddUUID(part.Sound); + else + zc.AddZeros(16); + + if (hassound || hasps) + zc.AddUUID(part.OwnerID); + else + zc.AddZeros(16); + + if (hassound) + { + zc.AddFloat((float)part.SoundGain); + zc.AddByte(part.SoundFlags); + zc.AddFloat((float)part.SoundRadius); + } + else + zc.AddZeros(9); // jointtype(1) joint pivot(12) joint offset(12) const int lastzeros = 1 + 12 + 12; -- cgit v1.1 From 9ccc3ed756fae1626d7d9fe374f131424c52cb21 Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Thu, 7 Mar 2019 14:53:32 +0000 Subject: make use of direct object update encoding --- .../Region/ClientStack/Linden/UDP/LLClientView.cs | 111 ++++++++++++++++----- 1 file changed, 88 insertions(+), 23 deletions(-) (limited to 'OpenSim/Region/ClientStack') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 691b7bb..171f8c6 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -4102,7 +4102,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP if (mysp == null) return; - List objectUpdateBlocks = null; // List compressedUpdateBlocks = null; List objectUpdates = null; // List compressedUpdates = null; @@ -4349,22 +4348,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP } else { - ObjectUpdatePacket.ObjectDataBlock ablock; if (update.Entity is ScenePresence) - { - ablock = CreateAvatarUpdateBlock((ScenePresence)update.Entity); - } + maxUpdatesBytes -= 150; // crude estimation else - ablock = CreatePrimUpdateBlock((SceneObjectPart)update.Entity, mysp); - if(objectUpdateBlocks == null) + maxUpdatesBytes -= 300; + + if(objectUpdates == null) { - objectUpdateBlocks = new List(); objectUpdates = new List(); maxUpdatesBytes -= 18; } - objectUpdateBlocks.Add(ablock); objectUpdates.Add(update); - maxUpdatesBytes -= ablock.Length; } #endregion Block Construction @@ -4379,16 +4373,86 @@ namespace OpenSim.Region.ClientStack.LindenUDP timeDilation = Utils.FloatToUInt16(m_scene.TimeDilation, 0.0f, 1.0f); - if (objectUpdateBlocks != null) + if(objectUpdates != null) { - ObjectUpdatePacket packet = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate); - packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; - packet.RegionData.TimeDilation = timeDilation; - packet.ObjectData = objectUpdateBlocks.ToArray(); - objectUpdateBlocks.Clear(); + int blocks = objectUpdates.Count; + List tau = new List(30); + + UDPPacketBuffer buf = m_udpServer.GetNewUDPBuffer(m_udpClient.RemoteEndPoint); + Buffer.BlockCopy(objectUpdateHeader, 0, buf.Data, 0, 7); + + LLUDPZeroEncoder zc = new LLUDPZeroEncoder(buf.Data); + zc.Position = 7; + + zc.AddUInt64(m_scene.RegionInfo.RegionHandle); + zc.AddUInt16(Utils.FloatToUInt16(m_scene.TimeDilation, 0.0f, 1.0f)); + + zc.AddByte(1); // tmp block count + + int countposition = zc.Position - 1; + + int lastpos = 0; + int lastzc = 0; + + int count = 0; + foreach (EntityUpdate eu in objectUpdates) + { + lastpos = zc.Position; + lastzc = zc.ZeroCount; + if (eu.Entity is ScenePresence) + CreateAvatarUpdateBlock((ScenePresence)eu.Entity, zc); + else + CreatePrimUpdateBlock((SceneObjectPart)eu.Entity, mysp, zc); + if (zc.Position < LLUDPServer.MTU - 5) + { + tau.Add(eu); + ++count; + --blocks; + } + else if (blocks > 0) + { + // we need more packets + UDPPacketBuffer newbuf = m_udpServer.GetNewUDPBuffer(m_udpClient.RemoteEndPoint); + Buffer.BlockCopy(buf.Data, 0, newbuf.Data, 0, countposition); // start is the same + + buf.Data[countposition] = (byte)count; + // get pending zeros at cut point + if(lastzc > 0) + { + buf.Data[lastpos++] = 0; + buf.Data[lastpos++] = (byte)lastzc; + } + buf.DataLength = lastpos; + + m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task, + delegate (OutgoingPacket oPacket) { ResendPrimUpdates(tau, oPacket); }, false, false); + + buf = newbuf; + zc.Data = buf.Data; + zc.ZeroCount = 0; + zc.Position = countposition + 1; + // im lazy now, just do last again + if (eu.Entity is ScenePresence) + CreateAvatarUpdateBlock((ScenePresence)eu.Entity, zc); + else + CreatePrimUpdateBlock((SceneObjectPart)eu.Entity, mysp, zc); + + tau = new List(30); + tau.Add(eu); + count = 1; + --blocks; + } + } - OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(objectUpdates, oPacket); }); + if (count > 0) + { + buf.Data[countposition] = (byte)count; + buf.DataLength = zc.Finish(); + m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task, + delegate (OutgoingPacket oPacket) { ResendPrimUpdates(tau, oPacket); }, false, false); + } } + /* if (compressedUpdateBlocks != null) { @@ -6289,7 +6353,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP else { int len = tentry.Length; - zc.AddUInt((ushort)len); + zc.AddByte((byte)len); + zc.AddByte((byte)(len >> 8)); zc.AddBytes(tentry, len); } @@ -6327,7 +6392,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP } //text - if (part.Text.Length == 0) + if (part.Text == null || part.Text.Length == 0) zc.AddZeros(5); else { @@ -6342,7 +6407,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP } //media url - if (part.MediaUrl.Length == 0) + if (part.MediaUrl == null || part.MediaUrl.Length == 0) zc.AddZeros(1); else { @@ -6355,19 +6420,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP bool hasps = false; //particle system byte[] ps = part.ParticleSystem; - if (ps == null) + if (ps == null || ps.Length < 1) zc.AddZeros(1); else { int len = ps.Length; zc.AddByte((byte)len); zc.AddBytes(ps, len); - hasps = len > 1; + hasps = true; } //Extraparams byte[] ep = part.Shape.ExtraParams; - if (ep == null) + if (ep == null || ep.Length < 2) zc.AddZeros(1); else { -- cgit v1.1 From 4e7cddc6a8a764a76b270dbb7aeb3a16e2bff56c Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Thu, 7 Mar 2019 17:11:52 +0000 Subject: vegetation is special --- .../Region/ClientStack/Linden/UDP/LLClientView.cs | 99 ++++++++++++++++------ 1 file changed, 71 insertions(+), 28 deletions(-) (limited to 'OpenSim/Region/ClientStack') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 171f8c6..f984009 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -6241,20 +6241,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP { // prepare data - //NameValue and state - byte[] nv = null; - byte state; - if (part.ParentGroup.IsAttachment) - { - if (part.IsRoot) - nv = Util.StringToBytes256("AttachItemID STRING RW SV " + part.ParentGroup.FromItemID); - - int st = (int)part.ParentGroup.AttachmentPoint; - state = (byte)(((st & 0xf0) >> 4) + ((st & 0x0f) << 4)); ; - } - else - state = part.Shape.State; // not sure about this - #region PrimFlags // prim/update flags PrimFlags primflags = (PrimFlags)m_scene.Permissions.GenerateClientFlags(part, sp); @@ -6271,6 +6257,76 @@ namespace OpenSim.Region.ClientStack.LindenUDP } #endregion PrimFlags + // data block + byte[] data = null; + byte state = part.Shape.State; + PCode pcode = (PCode)part.Shape.PCode; + + //vegetation is special so just do it inline + if(pcode == PCode.Grass || pcode == PCode.Tree || pcode == PCode.NewTree) + { + zc.AddUInt(part.LocalId); + zc.AddByte(state); // state + zc.AddUUID(part.UUID); + zc.AddZeros(4); // crc unused + zc.AddByte((byte)pcode); + // material 1 + // clickaction 1 + zc.AddZeros(2); + zc.AddVector3(part.Shape.Scale); + + // objectdata block + zc.AddByte(60); // fixed object block size + zc.AddVector3(part.RelativePosition); + zc.AddZeros(24); + Quaternion rot = part.RotationOffset; + rot.Normalize(); + zc.AddNormQuat(rot); + zc.AddZeros(12); + + zc.AddUInt(part.ParentID); + zc.AddUInt((uint)primflags); //update flags + + //pbs volume data 23 + //texture entry 2 + //texture anim 1 + //name value 2 + zc.AddZeros(23 + 2 + 1 + 2); + + //data + zc.AddByte(1); + zc.AddZeros(1); + zc.AddByte(state); + + // text 5 + // media url 1 + // particle system 1 + // Extraparams 1 + // sound id 16 + // ownwer 16 + // sound gain 4 + // sound flags 1 + // sound radius 4 + // jointtype 1 + // joint pivot 12 + // joint offset 12 + zc.AddZeros(5 + 1 + 1 + 1 + 16 + 16 + 4 + 1 + 4 + 1 + 12 + 12); + + return; + } + + //NameValue and state + byte[] nv = null; + + if (part.ParentGroup.IsAttachment) + { + if (part.IsRoot) + nv = Util.StringToBytes256("AttachItemID STRING RW SV " + part.ParentGroup.FromItemID); + + int st = (int)part.ParentGroup.AttachmentPoint; + state = (byte)(((st & 0xf0) >> 4) + ((st & 0x0f) << 4)); ; + } + // filter out mesh faces hack ushort profileBegin = part.Shape.ProfileBegin; ushort profileHollow = part.Shape.ProfileHollow; @@ -6290,25 +6346,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP pathScaleY = 150; } - // data block - byte[] data = null; - switch ((PCode)part.Shape.PCode) - { - case PCode.Grass: - case PCode.Tree: - case PCode.NewTree: - data = new byte[] { part.Shape.State }; - break; - default: - break; - } - // do encode the things zc.AddUInt(part.LocalId); zc.AddByte(state); // state zc.AddUUID(part.UUID); zc.AddZeros(4); // crc unused - zc.AddByte(part.Shape.PCode); + zc.AddByte((byte)pcode); zc.AddByte(part.Material); zc.AddByte(part.ClickAction); // clickaction zc.AddVector3(part.Shape.Scale); -- cgit v1.1 From 95c4de614427ca9d6b376408b0b56b6167bb41ce Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Thu, 7 Mar 2019 18:20:17 +0000 Subject: grass even more --- .../Region/ClientStack/Linden/UDP/LLClientView.cs | 45 ++++++++++++++++++---- 1 file changed, 38 insertions(+), 7 deletions(-) (limited to 'OpenSim/Region/ClientStack') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index f984009..4d62bbe 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -6266,7 +6266,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP if(pcode == PCode.Grass || pcode == PCode.Tree || pcode == PCode.NewTree) { zc.AddUInt(part.LocalId); - zc.AddByte(state); // state + if(pcode == PCode.Grass) + zc.AddByte(state); // state + else + zc.AddZeros(1); zc.AddUUID(part.UUID); zc.AddZeros(4); // crc unused zc.AddByte((byte)pcode); @@ -6278,22 +6281,50 @@ namespace OpenSim.Region.ClientStack.LindenUDP // objectdata block zc.AddByte(60); // fixed object block size zc.AddVector3(part.RelativePosition); - zc.AddZeros(24); - Quaternion rot = part.RotationOffset; - rot.Normalize(); - zc.AddNormQuat(rot); - zc.AddZeros(12); + if (pcode == PCode.Grass) + zc.AddZeros(48); + else + { + zc.AddZeros(24); + Quaternion rot = part.RotationOffset; + rot.Normalize(); + zc.AddNormQuat(rot); + zc.AddZeros(12); + } zc.AddUInt(part.ParentID); zc.AddUInt((uint)primflags); //update flags + if (pcode == PCode.Grass) + { + //pbs volume data 23 + //texture entry 2 + //texture anim 1 + //name value 2 + // data 1 + // text 5 + // media url 1 + // particle system 1 + // Extraparams 1 + // sound id 16 + // ownwer 16 + // sound gain 4 + // sound flags 1 + // sound radius 4 + // jointtype 1 + // joint pivot 12 + // joint offset 12 + zc.AddZeros(23 + 2 + 1 + 2 + 1 + 5 + 1 + 1 + 1 + 16 + 16 + 4 + 1 + 4 + 1 + 12 + 12); + return; + } + //pbs volume data 23 //texture entry 2 //texture anim 1 //name value 2 zc.AddZeros(23 + 2 + 1 + 2); - //data + //data: the tree type zc.AddByte(1); zc.AddZeros(1); zc.AddByte(state); -- cgit v1.1 From 155e4994573a1ad12ce75e8363e0e92c675bc0b6 Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Thu, 7 Mar 2019 18:57:13 +0000 Subject: well let trees have special state and grass data block again. --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'OpenSim/Region/ClientStack') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 4d62bbe..fb876de 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -6266,10 +6266,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP if(pcode == PCode.Grass || pcode == PCode.Tree || pcode == PCode.NewTree) { zc.AddUInt(part.LocalId); - if(pcode == PCode.Grass) - zc.AddByte(state); // state - else - zc.AddZeros(1); + zc.AddByte(state); // state zc.AddUUID(part.UUID); zc.AddZeros(4); // crc unused zc.AddByte((byte)pcode); @@ -6295,6 +6292,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP zc.AddUInt(part.ParentID); zc.AddUInt((uint)primflags); //update flags + /* if (pcode == PCode.Grass) { //pbs volume data 23 @@ -6317,6 +6315,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP zc.AddZeros(23 + 2 + 1 + 2 + 1 + 5 + 1 + 1 + 1 + 16 + 16 + 4 + 1 + 4 + 1 + 12 + 12); return; } + */ //pbs volume data 23 //texture entry 2 -- cgit v1.1 From a32060180fd6e24c7188b24769e294146133d9a0 Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Fri, 8 Mar 2019 19:14:09 +0000 Subject: agent animation object ids are only for self avatar --- .../Region/ClientStack/Linden/UDP/LLClientView.cs | 50 +++++++++++++++++----- 1 file changed, 40 insertions(+), 10 deletions(-) (limited to 'OpenSim/Region/ClientStack') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index fb876de..6ec87ab 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -3833,24 +3833,54 @@ namespace OpenSim.Region.ClientStack.LindenUDP AvatarAnimationPacket ani = (AvatarAnimationPacket)PacketPool.Instance.GetPacket(PacketType.AvatarAnimation); // TODO: don't create new blocks if recycling an old packet - ani.AnimationSourceList = new AvatarAnimationPacket.AnimationSourceListBlock[animations.Length]; ani.Sender = new AvatarAnimationPacket.SenderBlock(); ani.Sender.ID = sourceAgentId; ani.AnimationList = new AvatarAnimationPacket.AnimationListBlock[animations.Length]; ani.PhysicalAvatarEventList = new AvatarAnimationPacket.PhysicalAvatarEventListBlock[0]; - for (int i = 0; i < animations.Length; ++i) + //self animations + if (sourceAgentId == AgentId) { - ani.AnimationList[i] = new AvatarAnimationPacket.AnimationListBlock(); - ani.AnimationList[i].AnimID = animations[i]; - ani.AnimationList[i].AnimSequenceID = seqs[i]; + List withobjects = new List(animations.Length); + List noobjects = new List(animations.Length); + for(int i = 0; i < animations.Length; ++i) + { + if(objectIDs[i] == sourceAgentId || objectIDs[i] == UUID.Zero) + noobjects.Add(i); + else + withobjects.Add(i); + } - ani.AnimationSourceList[i] = new AvatarAnimationPacket.AnimationSourceListBlock(); - if (objectIDs[i].Equals(sourceAgentId)) - ani.AnimationSourceList[i].ObjectID = UUID.Zero; - else - ani.AnimationSourceList[i].ObjectID = objectIDs[i]; + ani.AnimationSourceList = new AvatarAnimationPacket.AnimationSourceListBlock[withobjects.Count]; + int k = 0; + foreach (int i in withobjects) + { + ani.AnimationList[k] = new AvatarAnimationPacket.AnimationListBlock(); + ani.AnimationList[k].AnimID = animations[i]; + ani.AnimationList[k].AnimSequenceID = seqs[i]; + ani.AnimationSourceList[k] = new AvatarAnimationPacket.AnimationSourceListBlock(); + ani.AnimationSourceList[k].ObjectID = objectIDs[i]; + k++; + } + foreach (int i in noobjects) + { + ani.AnimationList[k] = new AvatarAnimationPacket.AnimationListBlock(); + ani.AnimationList[k].AnimID = animations[i]; + ani.AnimationList[k].AnimSequenceID = seqs[i]; + k++; + } + } + else + { + ani.AnimationSourceList = new AvatarAnimationPacket.AnimationSourceListBlock[0]; + for (int i = 0; i < animations.Length; ++i) + { + ani.AnimationList[i] = new AvatarAnimationPacket.AnimationListBlock(); + ani.AnimationList[i].AnimID = animations[i]; + ani.AnimationList[i].AnimSequenceID = seqs[i]; + } } + OutPacket(ani, ThrottleOutPacketType.Task | ThrottleOutPacketType.HighPriority); } -- cgit v1.1 From e9d7ced733e99904de315d71d7b851e8ff7a3a67 Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Fri, 8 Mar 2019 21:14:08 +0000 Subject: just direct encode avatar animation also --- .../Region/ClientStack/Linden/UDP/LLClientView.cs | 74 ++++++++++++++++++++++ 1 file changed, 74 insertions(+) (limited to 'OpenSim/Region/ClientStack') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 6ec87ab..5d42ecd 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -3827,6 +3827,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP OutPacket(avp, ThrottleOutPacketType.Task | ThrottleOutPacketType.HighPriority); } +/* public void SendAnimations(UUID[] animations, int[] seqs, UUID sourceAgentId, UUID[] objectIDs) { // m_log.DebugFormat("[LLCLIENTVIEW]: Sending animations for {0} to {1}", sourceAgentId, Name); @@ -3883,6 +3884,79 @@ namespace OpenSim.Region.ClientStack.LindenUDP OutPacket(ani, ThrottleOutPacketType.Task | ThrottleOutPacketType.HighPriority); } +*/ + + static private readonly byte[] AvatarAnimationHeader = new byte[] { + Helpers.MSG_RELIABLE | Helpers.MSG_ZEROCODED, // zero code is not as spec + 0, 0, 0, 0, // sequence number + 0, // extra + 20 // ID (high frequency) + }; + + public void SendAnimations(UUID[] animations, int[] seqs, UUID sourceAgentId, UUID[] objectIDs) + { + // m_log.DebugFormat("[LLCLIENTVIEW]: Sending animations for {0} to {1}", sourceAgentId, Name); + + UDPPacketBuffer buf = m_udpServer.GetNewUDPBuffer(m_udpClient.RemoteEndPoint); + byte[] data = buf.Data; + //setup header + Buffer.BlockCopy(AvatarAnimationHeader, 0, data, 0, 7); + //agent block + sourceAgentId.ToBytes(data, 7); + + // animations count + data[23] = (byte)animations.Length; + + int pos = 24; + + //self animations + if (sourceAgentId == AgentId) + { + List withobjects = new List(animations.Length); + List noobjects = new List(animations.Length); + for (int i = 0; i < animations.Length; ++i) + { + if (objectIDs[i] == sourceAgentId || objectIDs[i] == UUID.Zero) + noobjects.Add(i); + else + withobjects.Add(i); + } + + // first the ones with corresponding objects + foreach (int i in withobjects) + { + animations[i].ToBytes(data, pos); pos += 16; + Utils.IntToBytesSafepos(seqs[i], data, pos); pos += 4; + } + // then the rest + foreach (int i in noobjects) + { + animations[i].ToBytes(data, pos); pos += 16; + Utils.IntToBytesSafepos(seqs[i], data, pos); pos += 4; + } + // object ids block + data[pos++] = (byte)withobjects.Count; + foreach (int i in withobjects) + { + objectIDs[i].ToBytes(data, pos); pos += 16; + } + } + else + { + for(int i = 0; i < animations.Length; ++i) + { + animations[i].ToBytes(data, pos); pos += 16; + Utils.IntToBytesSafepos(seqs[i], data, pos); pos += 4; + } + data[pos++] = 0; // no object ids + } + + data[pos++] = 0; // no physical avatar events + + buf.DataLength = pos; + m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task | ThrottleOutPacketType.HighPriority, + null, false, false); + } public void SendObjectAnimations(UUID[] animations, int[] seqs, UUID senderId) { -- cgit v1.1 From 6bc37f348e70909bfa91319aefa76e76ffd7b398 Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Fri, 8 Mar 2019 22:28:57 +0000 Subject: ooops bad zeroencode flag --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Region/ClientStack') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 5d42ecd..5353194 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -3887,7 +3887,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP */ static private readonly byte[] AvatarAnimationHeader = new byte[] { - Helpers.MSG_RELIABLE | Helpers.MSG_ZEROCODED, // zero code is not as spec + Helpers.MSG_RELIABLE, 0, 0, 0, 0, // sequence number 0, // extra 20 // ID (high frequency) -- cgit v1.1 From 343239c7c395bf81cd07057bd89a846d81d263a7 Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Sat, 9 Mar 2019 12:04:26 +0000 Subject: do not send animated attachments to viewers that do not support them. --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'OpenSim/Region/ClientStack') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 5353194..ecae8c8 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -4285,7 +4285,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP } if (grp.IsAttachment) - { // Someone else's HUD, why are we getting these? + { + // animated attachments are nasty if not supported by viewer + if(!m_SupportObjectAnimations && grp.RootPart.Shape.MeshFlagEntry) + continue; + + // Someone else's HUD, why are we getting these? if (grp.OwnerID != AgentId && grp.HasPrivateAttachmentPoint) continue; -- cgit v1.1 From 7b55d42b11d899456d8e5a153fb097e8691b92e8 Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Sun, 10 Mar 2019 11:23:38 +0000 Subject: lludp fix max packet size on ack appends --- OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'OpenSim/Region/ClientStack') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs index 6fd782a..2300800 100755 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs @@ -256,6 +256,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// Maximum transmission unit, or UDP packet size, for the LLUDP protocol public const int MTU = 1400; + public const int MAXPAYLOAD = 1250; /// Number of forced client logouts due to no receipt of packets before timeout. public int ClientLogoutsDueToNoReceives { get; protected set; } @@ -1150,7 +1151,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP // no more ACKs to append int ackCount = 0; uint ack; - while (dataLength + 5 < buffer.Data.Length && ackCount < 256 && udpClient.PendingAcks.Dequeue(out ack)) + while (dataLength + 5 < MTU && ackCount < 256 && udpClient.PendingAcks.Dequeue(out ack)) { Utils.UIntToBytesBig(ack, buffer.Data, dataLength); dataLength += 4; -- cgit v1.1 From 32a03a49fc06edb65cb016b8c69f88e3c595be1d Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Sun, 10 Mar 2019 15:56:14 +0000 Subject: lludp: direct encode terrain patchs packets --- .../Region/ClientStack/Linden/UDP/LLClientView.cs | 86 ++++++++++++++++++++-- 1 file changed, 81 insertions(+), 5 deletions(-) (limited to 'OpenSim/Region/ClientStack') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index ecae8c8..ac041f5 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -1257,6 +1257,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP SendLayerTopRight(x1 + 1, y1, x2, y2 - 1); } + static private readonly byte[] TerrainPacketHeader = new byte[] { + Helpers.MSG_RELIABLE, // zero code is not as spec + 0, 0, 0, 0, // sequence number + 0, // extra + 11, // ID (high frequency) + }; + + private const int END_OF_PATCHES = 97; + private const int STRIDE = 264; + public void SendLayerData(int[] map) { if(map == null) @@ -1264,9 +1274,75 @@ namespace OpenSim.Region.ClientStack.LindenUDP try { - List packets = OpenSimTerrainCompressor.CreateLayerDataPackets(m_scene.Heightmap.GetTerrainData(), map); - foreach (LayerDataPacket pkt in packets) - OutPacket(pkt, ThrottleOutPacketType.Land); + TerrainData terrData = m_scene.Heightmap.GetTerrainData(); + byte landPacketType = (terrData.SizeX > Constants.RegionSize || terrData.SizeY > Constants.RegionSize) ? + (byte)TerrainPatch.LayerType.LandExtended : (byte)TerrainPatch.LayerType.Land; + + int numberPatchs = map.Length / 2; + + UDPPacketBuffer buf = m_udpServer.GetNewUDPBuffer(m_udpClient.RemoteEndPoint); + byte[] data = buf.Data; + + Buffer.BlockCopy(TerrainPacketHeader, 0, data, 0, 7); + + data[7] = landPacketType; + //data[8] and data[9] == datablock size to fill later + + data[10] = 0; // BitPack needs this on reused packets + + // start data + BitPack bitpack = new BitPack(data, 10); + bitpack.PackBits(STRIDE, 16); + bitpack.PackBitsFromByte(16); + bitpack.PackBitsFromByte(landPacketType); + + int s; + int datasize = 0; + for (int i = 0; i < numberPatchs; i++) + { + s = 2 * i; + OpenSimTerrainCompressor.CreatePatchFromTerrainData(bitpack, terrData, map[s], map[s + 1]); + if (bitpack.BytePos > 950 && i != numberPatchs - 1) + { + //finish this packet + bitpack.PackBitsFromByte(END_OF_PATCHES); + + // fix the datablock lenght + datasize = bitpack.BytePos - 9; + data[8] = (byte)datasize; + data[9] = (byte)(datasize >> 8); + + buf.DataLength = bitpack.BytePos + 1; + m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Land, null, false, false); + + // start another + buf = m_udpServer.GetNewUDPBuffer(m_udpClient.RemoteEndPoint); + data = buf.Data; + + Buffer.BlockCopy(TerrainPacketHeader, 0, data, 0, 7); + + data[7] = landPacketType; + //data[8] and data[9] == datablock size to fill later + + data[10] = 0; // BitPack needs this + // start data + bitpack = new BitPack(data, 10); + + bitpack.PackBits(STRIDE, 16); + bitpack.PackBitsFromByte(16); + bitpack.PackBitsFromByte(landPacketType); + } + } + + bitpack.PackBitsFromByte(END_OF_PATCHES); + + datasize = bitpack.BytePos - 9; + data[8] = (byte)datasize; + data[9] = (byte)(datasize >> 8); + + buf.DataLength = bitpack.BytePos + 1; + m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Land, null, false, false); + } catch (Exception e) { @@ -4512,7 +4588,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP CreateAvatarUpdateBlock((ScenePresence)eu.Entity, zc); else CreatePrimUpdateBlock((SceneObjectPart)eu.Entity, mysp, zc); - if (zc.Position < LLUDPServer.MTU - 5) + if (zc.Position < LLUDPServer.MAXPAYLOAD) { tau.Add(eu); ++count; @@ -4593,7 +4669,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP { lastpos = pos; CreateImprovedTerseBlock(eu.Entity, buf.Data, ref pos, (eu.Flags & PrimUpdateFlags.Textures) != 0); - if (pos < LLUDPServer.MTU) + if (pos < LLUDPServer.MAXPAYLOAD) { tau.Add(eu); ++count; -- cgit v1.1