From 46dc9ebd4e9fa6deb218b9ebc0d95b63a2f08826 Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Fri, 15 Mar 2019 18:08:05 +0000 Subject: [PATCH] lludp: change zero encode of strings; limit them to what current viewers expect --- .../ClientStack/Linden/UDP/LLClientView.cs | 180 +----------------- .../Linden/UDP/LLUDPZeroEncoder.cs | 82 ++++++++ 2 files changed, 90 insertions(+), 172 deletions(-) diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 181c4e2f1e..cb2d9e2ac8 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -5336,14 +5336,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP zc.AddUUID(sop.LastOwnerID); //name - byte[] tmpbytes = Util.StringToBytes256(sop.Name); - zc.AddByte((byte)tmpbytes.Length); - zc.AddBytes(tmpbytes, tmpbytes.Length); + zc.AddShortString(sop.Name, 64); //Description - tmpbytes = Util.StringToBytes256(sop.Description); - zc.AddByte((byte)tmpbytes.Length); - zc.AddBytes(tmpbytes, tmpbytes.Length); + zc.AddShortString(sop.Description, 128); } private void CreateObjectPropertiesBlock(SceneObjectPart sop, LLUDPZeroEncoder zc) @@ -5387,24 +5383,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP zc.AddUUID(sop.LastOwnerID); //name - byte[] tmpbytes = Util.StringToBytes256(sop.Name); - zc.AddByte((byte)tmpbytes.Length); - zc.AddBytes(tmpbytes, tmpbytes.Length); + zc.AddShortString(sop.Name, 64); //Description - tmpbytes = Util.StringToBytes256(sop.Description); - zc.AddByte((byte)tmpbytes.Length); - zc.AddBytes(tmpbytes, tmpbytes.Length); + zc.AddShortString(sop.Description, 128); // touch name - tmpbytes = Util.StringToBytes256(root.TouchName); - zc.AddByte((byte)tmpbytes.Length); - zc.AddBytes(tmpbytes, tmpbytes.Length); + zc.AddShortString(root.TouchName, 9, 37); // sit name - tmpbytes = Util.StringToBytes256(root.SitName); - zc.AddByte((byte)tmpbytes.Length); - zc.AddBytes(tmpbytes, tmpbytes.Length); + zc.AddShortString(root.SitName, 9, 37); //texture ids block // still not sending, not clear the impact on viewers, if any. @@ -6349,150 +6337,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP zc.AddZeros(lastzeros); } - protected ObjectUpdatePacket.ObjectDataBlock CreatePrimUpdateBlock(SceneObjectPart part, ScenePresence sp) - { - byte[] objectData = new byte[60]; - part.RelativePosition.ToBytes(objectData, 0); - part.Velocity.ToBytes(objectData, 12); - part.Acceleration.ToBytes(objectData, 24); - - Quaternion rotation = part.RotationOffset; - rotation.Normalize(); - rotation.ToBytes(objectData, 36); - part.AngularVelocity.ToBytes(objectData, 48); - - ObjectUpdatePacket.ObjectDataBlock update = new ObjectUpdatePacket.ObjectDataBlock(); - update.ClickAction = (byte)part.ClickAction; - update.CRC = 0; - update.ExtraParams = part.Shape.ExtraParams ?? Utils.EmptyBytes; - update.FullID = part.UUID; - update.ID = part.LocalId; - //update.JointAxisOrAnchor = Vector3.Zero; // These are deprecated - //update.JointPivot = Vector3.Zero; - //update.JointType = 0; - update.Material = part.Material; - - if (part.ParentGroup.IsAttachment) - { - if (part.IsRoot) - { - update.NameValue = Util.StringToBytes256("AttachItemID STRING RW SV " + part.ParentGroup.FromItemID); - } - else - update.NameValue = Utils.EmptyBytes; - - int st = (int)part.ParentGroup.AttachmentPoint; - update.State = (byte)(((st & 0xf0) >> 4) + ((st & 0x0f) << 4)); ; - } - else - { - update.NameValue = Utils.EmptyBytes; - update.State = part.Shape.State; // not sure about this - } - - update.ObjectData = objectData; - update.ParentID = part.ParentID; - update.PathBegin = part.Shape.PathBegin; - update.PathCurve = part.Shape.PathCurve; - update.PathEnd = part.Shape.PathEnd; - update.PathRadiusOffset = part.Shape.PathRadiusOffset; - update.PathRevolutions = part.Shape.PathRevolutions; - update.PathScaleX = part.Shape.PathScaleX; - update.PathScaleY = part.Shape.PathScaleY; - update.PathShearX = part.Shape.PathShearX; - update.PathShearY = part.Shape.PathShearY; - update.PathSkew = part.Shape.PathSkew; - update.PathTaperX = part.Shape.PathTaperX; - update.PathTaperY = part.Shape.PathTaperY; - update.PathTwist = part.Shape.PathTwist; - update.PathTwistBegin = part.Shape.PathTwistBegin; - update.PCode = part.Shape.PCode; - update.ProfileBegin = part.Shape.ProfileBegin; - update.ProfileCurve = part.Shape.ProfileCurve; - - ushort profileBegin = part.Shape.ProfileBegin; - ushort profileHollow = part.Shape.ProfileHollow; - - if(part.Shape.SculptType == (byte)SculptType.Mesh) // filter out hack - { - update.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(update.ProfileCurve == (byte)ProfileShape.Circle && update.PathScaleY < 150) - update.PathScaleY = 150; - } - else - { - update.ProfileCurve = part.Shape.ProfileCurve; - } - - update.ProfileHollow = profileHollow; - update.ProfileBegin = profileBegin; - update.ProfileEnd = part.Shape.ProfileEnd; - update.PSBlock = part.ParticleSystem ?? Utils.EmptyBytes; - update.TextColor = part.GetTextColor().GetBytes(false); - update.TextureAnim = part.TextureAnimation ?? Utils.EmptyBytes; - update.TextureEntry = part.Shape.TextureEntry ?? Utils.EmptyBytes; - update.Scale = part.Shape.Scale; - update.Text = Util.StringToBytes(part.Text, 255); - update.MediaURL = Util.StringToBytes(part.MediaUrl, 255); - - #region PrimFlags - - PrimFlags flags = (PrimFlags)m_scene.Permissions.GenerateClientFlags(part, sp); - - // Don't send the CreateSelected flag to everyone - flags &= ~PrimFlags.CreateSelected; - - if (sp.UUID == part.OwnerID) - { - if (part.CreateSelected) - { - // Only send this flag once, then unset it - flags |= PrimFlags.CreateSelected; - part.CreateSelected = false; - } - } - -// m_log.DebugFormat( -// "[LLCLIENTVIEW]: Constructing client update for part {0} {1} with flags {2}, localId {3}", -// data.Name, update.FullID, flags, update.ID); - - update.UpdateFlags = (uint)flags; - - #endregion PrimFlags - - bool hassound = part.Sound != UUID.Zero || part.SoundFlags != 0; - if (hassound) - { - update.Sound = part.Sound; - 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: - case PCode.Tree: - case PCode.NewTree: - update.Data = new byte[] { part.Shape.State }; - break; - default: - update.Data = Utils.EmptyBytes; - break; - } - - return update; - } - protected void CreatePrimUpdateBlock(SceneObjectPart part, ScenePresence sp, LLUDPZeroEncoder zc) { // prepare data @@ -6725,10 +6569,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP zc.AddZeros(5); else { - byte[] tbuf = Util.StringToBytes(part.Text, 254); - int len = tbuf.Length; - zc.AddByte((byte)len); - zc.AddBytes(tbuf, len); + zc.AddShortString(part.Text, 255); //textcolor byte[] tc = part.GetTextColor().GetBytes(false); @@ -6739,12 +6580,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP if (part.MediaUrl == null || 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); - } + zc.AddShortString(part.MediaUrl, 255); bool hasps = false; //particle system diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPZeroEncoder.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPZeroEncoder.cs index 8ed2cf12cd..0b008a9f85 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPZeroEncoder.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPZeroEncoder.cs @@ -26,6 +26,7 @@ */ using System; +using System.Text; using OpenSim.Framework; using Nini.Config; using OpenMetaverse; @@ -275,5 +276,86 @@ namespace OpenSim.Region.ClientStack.LindenUDP v.ToBytes(m_tmp, 0); AddBytes(m_tmp, 16); } + + // maxlen <= 255 and includes null termination byte + public void AddShortString(string str, int maxlen) + { + if (String.IsNullOrEmpty(str)) + { + AddZeros(1); + return; + } + + --maxlen; // account for null term + bool NullTerm = str.EndsWith("\0"); + + byte[] data = Util.UTF8.GetBytes(str); + int len = data.Length; + if(NullTerm) + --len; + + if(len <= maxlen) + { + AddByte((byte)(len + 1)); + AddBytes(data, len); + AddZeros(1); + return; + } + + if ((data[maxlen] & 0x80) != 0) + { + while (maxlen > 0 && (data[maxlen] & 0xc0) != 0xc0) + maxlen--; + } + AddByte((byte)(maxlen + 1)); + AddBytes(data, maxlen); + AddZeros(1); + } + // maxlen <= 255 and includes null termination byte, maxchars == max len of utf8 source + public void AddShortString(string str, int maxchars, int maxlen) + { + if (String.IsNullOrEmpty(str)) + { + AddZeros(1); + return; + } + + --maxlen; // account for null term + bool NullTerm = false; + byte[] data; + + if (str.Length > maxchars) + { + data = Util.UTF8.GetBytes(str.Substring(0,maxchars)); + } + else + { + NullTerm = str.EndsWith("\0"); + data = Util.UTF8.GetBytes(str); + } + + int len = data.Length; + if (NullTerm) + --len; + + if (len <= maxlen) + { + AddByte((byte)(len + 1)); + AddBytes(data, len); + AddZeros(1); + return; + } + + if ((data[maxlen] & 0x80) != 0) + { + while (maxlen > 0 && (data[maxlen] & 0xc0) != 0xc0) + maxlen--; + } + + AddByte((byte)(maxlen + 1)); + AddBytes(data, maxlen); + AddZeros(1); + } + } }