aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ClientStack
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/ClientStack')
-rwxr-xr-x[-rw-r--r--]OpenSim/Region/ClientStack/Linden/Caps/GetAssetsModule.cs39
-rwxr-xr-x[-rw-r--r--]OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs23
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs1158
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs90
-rwxr-xr-x[-rw-r--r--]OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs350
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLUDPServerCommands.cs37
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLUDPZeroEncoder.cs279
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs182
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/ThrottleRates.cs9
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/UnackedPacketCollection.cs14
10 files changed, 1605 insertions, 576 deletions
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/GetAssetsModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/GetAssetsModule.cs
index 9187979..c071bd1 100644..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
59 private string m_GetTextureURL; 59 private string m_GetTextureURL;
60 private string m_GetMeshURL; 60 private string m_GetMeshURL;
61 private string m_GetMesh2URL; 61 private string m_GetMesh2URL;
62// private string m_GetAssetURL; 62 private string m_GetAssetURL;
63 63
64 class APollRequest 64 class APollRequest
65 { 65 {
@@ -87,7 +87,7 @@ namespace OpenSim.Region.ClientStack.Linden
87 private Dictionary<UUID, string> m_capsDictTexture = new Dictionary<UUID, string>(); 87 private Dictionary<UUID, string> m_capsDictTexture = new Dictionary<UUID, string>();
88 private Dictionary<UUID, string> m_capsDictGetMesh = new Dictionary<UUID, string>(); 88 private Dictionary<UUID, string> m_capsDictGetMesh = new Dictionary<UUID, string>();
89 private Dictionary<UUID, string> m_capsDictGetMesh2 = new Dictionary<UUID, string>(); 89 private Dictionary<UUID, string> m_capsDictGetMesh2 = new Dictionary<UUID, string>();
90 //private Dictionary<UUID, string> m_capsDictGetAsset = new Dictionary<UUID, string>(); 90 private Dictionary<UUID, string> m_capsDictGetAsset = new Dictionary<UUID, string>();
91 91
92 #region Region Module interfaceBase Members 92 #region Region Module interfaceBase Members
93 93
@@ -113,11 +113,11 @@ namespace OpenSim.Region.ClientStack.Linden
113 m_GetMesh2URL = config.GetString("Cap_GetMesh2", string.Empty); 113 m_GetMesh2URL = config.GetString("Cap_GetMesh2", string.Empty);
114 if (m_GetMesh2URL != string.Empty) 114 if (m_GetMesh2URL != string.Empty)
115 m_Enabled = true; 115 m_Enabled = true;
116/* 116
117 m_GetAssetURL = config.GetString("Cap_GetAsset", string.Empty); 117 m_GetAssetURL = config.GetString("Cap_GetAsset", string.Empty);
118 if (m_GetAssetURL != string.Empty) 118 if (m_GetAssetURL != string.Empty)
119 m_Enabled = true; 119 m_Enabled = true;
120*/ 120
121 } 121 }
122 122
123 public void AddRegion(Scene pScene) 123 public void AddRegion(Scene pScene)
@@ -204,19 +204,26 @@ namespace OpenSim.Region.ClientStack.Linden
204 204
205 private static void DoAssetRequests() 205 private static void DoAssetRequests()
206 { 206 {
207 while (m_NumberScenes > 0) 207 try
208 { 208 {
209 APollRequest poolreq; 209 while (m_NumberScenes > 0)
210 if(m_queue.TryTake(out poolreq, 4500))
211 { 210 {
212 if (m_NumberScenes <= 0) 211 APollRequest poolreq;
213 break; 212 if (m_queue.TryTake(out poolreq, 4500))
213 {
214 if (m_NumberScenes <= 0)
215 break;
216 Watchdog.UpdateThread();
217 if (poolreq.reqID != UUID.Zero)
218 poolreq.thepoll.Process(poolreq);
219 poolreq = null;
220 }
214 Watchdog.UpdateThread(); 221 Watchdog.UpdateThread();
215 if (poolreq.reqID != UUID.Zero)
216 poolreq.thepoll.Process(poolreq);
217 poolreq = null;
218 } 222 }
219 Watchdog.UpdateThread(); 223 }
224 catch (ThreadAbortException)
225 {
226 Thread.ResetAbort();
220 } 227 }
221 } 228 }
222 229
@@ -441,7 +448,6 @@ namespace OpenSim.Region.ClientStack.Linden
441 else if (m_GetMesh2URL != string.Empty) 448 else if (m_GetMesh2URL != string.Empty)
442 caps.RegisterHandler("GetMesh2", m_GetMesh2URL); 449 caps.RegisterHandler("GetMesh2", m_GetMesh2URL);
443 450
444/* we can't support this cap. Current viewers connect to the wrong regions.
445 //ViewerAsset 451 //ViewerAsset
446 if (m_GetAssetURL == "localhost") 452 if (m_GetAssetURL == "localhost")
447 { 453 {
@@ -459,7 +465,7 @@ namespace OpenSim.Region.ClientStack.Linden
459 } 465 }
460 else if (m_GetAssetURL != string.Empty) 466 else if (m_GetAssetURL != string.Empty)
461 caps.RegisterHandler("ViewerAsset", m_GetMesh2URL); 467 caps.RegisterHandler("ViewerAsset", m_GetMesh2URL);
462*/ 468
463 } 469 }
464 470
465 private void DeregisterCaps(UUID agentID, Caps caps) 471 private void DeregisterCaps(UUID agentID, Caps caps)
@@ -480,13 +486,12 @@ namespace OpenSim.Region.ClientStack.Linden
480 MainServer.Instance.RemovePollServiceHTTPHandler("", capUrl); 486 MainServer.Instance.RemovePollServiceHTTPHandler("", capUrl);
481 m_capsDictGetMesh2.Remove(agentID); 487 m_capsDictGetMesh2.Remove(agentID);
482 } 488 }
483/* 489
484 if (m_capsDictGetAsset.TryGetValue(agentID, out capUrl)) 490 if (m_capsDictGetAsset.TryGetValue(agentID, out capUrl))
485 { 491 {
486 MainServer.Instance.RemovePollServiceHTTPHandler("", capUrl); 492 MainServer.Instance.RemovePollServiceHTTPHandler("", capUrl);
487 m_capsDictGetAsset.Remove(agentID); 493 m_capsDictGetAsset.Remove(agentID);
488 } 494 }
489*/
490 } 495 }
491 } 496 }
492} 497}
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs
index 41d70a3..9a01567 100644..100755
--- 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
395 395
396 private static void DoInventoryRequests() 396 private static void DoInventoryRequests()
397 { 397 {
398 while (true) 398 bool running = true;
399 while (running)
399 { 400 {
400 APollRequest poolreq; 401 try
401 if (m_queue.TryTake(out poolreq, 4500))
402 { 402 {
403 APollRequest poolreq;
404 if (m_queue.TryTake(out poolreq, 4500))
405 {
406 Watchdog.UpdateThread();
407 if (poolreq.thepoll != null)
408 poolreq.thepoll.Process(poolreq);
409 poolreq = null;
410 }
403 Watchdog.UpdateThread(); 411 Watchdog.UpdateThread();
404 if (poolreq.thepoll != null)
405 poolreq.thepoll.Process(poolreq);
406 poolreq = null;
407 } 412 }
408 Watchdog.UpdateThread(); 413 catch (ThreadAbortException)
414 {
415 Thread.ResetAbort();
416 running = false;
417 }
409 } 418 }
410 } 419 }
411 } 420 }
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
index b7d5a80..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
1257 SendLayerTopRight(x1 + 1, y1, x2, y2 - 1); 1257 SendLayerTopRight(x1 + 1, y1, x2, y2 - 1);
1258 } 1258 }
1259 1259
1260 static private readonly byte[] TerrainPacketHeader = new byte[] {
1261 Helpers.MSG_RELIABLE, // zero code is not as spec
1262 0, 0, 0, 0, // sequence number
1263 0, // extra
1264 11, // ID (high frequency)
1265 };
1266
1267 private const int END_OF_PATCHES = 97;
1268 private const int STRIDE = 264;
1269
1260 public void SendLayerData(int[] map) 1270 public void SendLayerData(int[] map)
1261 { 1271 {
1262 if(map == null) 1272 if(map == null)
@@ -1264,9 +1274,75 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1264 1274
1265 try 1275 try
1266 { 1276 {
1267 List<LayerDataPacket> packets = OpenSimTerrainCompressor.CreateLayerDataPackets(m_scene.Heightmap.GetTerrainData(), map); 1277 TerrainData terrData = m_scene.Heightmap.GetTerrainData();
1268 foreach (LayerDataPacket pkt in packets) 1278 byte landPacketType = (terrData.SizeX > Constants.RegionSize || terrData.SizeY > Constants.RegionSize) ?
1269 OutPacket(pkt, ThrottleOutPacketType.Land); 1279 (byte)TerrainPatch.LayerType.LandExtended : (byte)TerrainPatch.LayerType.Land;
1280
1281 int numberPatchs = map.Length / 2;
1282
1283 UDPPacketBuffer buf = m_udpServer.GetNewUDPBuffer(m_udpClient.RemoteEndPoint);
1284 byte[] data = buf.Data;
1285
1286 Buffer.BlockCopy(TerrainPacketHeader, 0, data, 0, 7);
1287
1288 data[7] = landPacketType;
1289 //data[8] and data[9] == datablock size to fill later
1290
1291 data[10] = 0; // BitPack needs this on reused packets
1292
1293 // start data
1294 BitPack bitpack = new BitPack(data, 10);
1295 bitpack.PackBits(STRIDE, 16);
1296 bitpack.PackBitsFromByte(16);
1297 bitpack.PackBitsFromByte(landPacketType);
1298
1299 int s;
1300 int datasize = 0;
1301 for (int i = 0; i < numberPatchs; i++)
1302 {
1303 s = 2 * i;
1304 OpenSimTerrainCompressor.CreatePatchFromTerrainData(bitpack, terrData, map[s], map[s + 1]);
1305 if (bitpack.BytePos > 950 && i != numberPatchs - 1)
1306 {
1307 //finish this packet
1308 bitpack.PackBitsFromByte(END_OF_PATCHES);
1309
1310 // fix the datablock lenght
1311 datasize = bitpack.BytePos - 9;
1312 data[8] = (byte)datasize;
1313 data[9] = (byte)(datasize >> 8);
1314
1315 buf.DataLength = bitpack.BytePos + 1;
1316 m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Land, null, false, false);
1317
1318 // start another
1319 buf = m_udpServer.GetNewUDPBuffer(m_udpClient.RemoteEndPoint);
1320 data = buf.Data;
1321
1322 Buffer.BlockCopy(TerrainPacketHeader, 0, data, 0, 7);
1323
1324 data[7] = landPacketType;
1325 //data[8] and data[9] == datablock size to fill later
1326
1327 data[10] = 0; // BitPack needs this
1328 // start data
1329 bitpack = new BitPack(data, 10);
1330
1331 bitpack.PackBits(STRIDE, 16);
1332 bitpack.PackBitsFromByte(16);
1333 bitpack.PackBitsFromByte(landPacketType);
1334 }
1335 }
1336
1337 bitpack.PackBitsFromByte(END_OF_PATCHES);
1338
1339 datasize = bitpack.BytePos - 9;
1340 data[8] = (byte)datasize;
1341 data[9] = (byte)(datasize >> 8);
1342
1343 buf.DataLength = bitpack.BytePos + 1;
1344 m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Land, null, false, false);
1345
1270 } 1346 }
1271 catch (Exception e) 1347 catch (Exception e)
1272 { 1348 {
@@ -1677,8 +1753,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1677 1753
1678 public void SendKillObject(List<uint> localIDs) 1754 public void SendKillObject(List<uint> localIDs)
1679 { 1755 {
1680 // foreach (uint id in localIDs) 1756 // foreach (uint id in localIDs)
1681 // m_log.DebugFormat("[CLIENT]: Sending KillObjectPacket to {0} for {1} in {2}", Name, id, regionHandle); 1757 // m_log.DebugFormat("[CLIENT]: Sending KillObjectPacket to {0} for {1} in {2}", Name, id, regionHandle);
1682 1758
1683 // remove pending entities to reduce looping chances. 1759 // remove pending entities to reduce looping chances.
1684 lock (m_entityProps.SyncRoot) 1760 lock (m_entityProps.SyncRoot)
@@ -1702,10 +1778,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1702 1778
1703 if(++nsent >= 200) 1779 if(++nsent >= 200)
1704 { 1780 {
1705 kill.Header.Reliable = true;
1706 kill.Header.Zerocoded = true;
1707 OutPacket(kill, ThrottleOutPacketType.Task); 1781 OutPacket(kill, ThrottleOutPacketType.Task);
1708
1709 perpacket = localIDs.Count - i - 1; 1782 perpacket = localIDs.Count - i - 1;
1710 if(perpacket == 0) 1783 if(perpacket == 0)
1711 break; 1784 break;
@@ -1720,8 +1793,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1720 1793
1721 if(nsent != 0) 1794 if(nsent != 0)
1722 { 1795 {
1723 kill.Header.Reliable = true;
1724 kill.Header.Zerocoded = true;
1725 OutPacket(kill, ThrottleOutPacketType.Task); 1796 OutPacket(kill, ThrottleOutPacketType.Task);
1726 } 1797 }
1727 } 1798 }
@@ -3832,32 +3903,136 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3832 OutPacket(avp, ThrottleOutPacketType.Task | ThrottleOutPacketType.HighPriority); 3903 OutPacket(avp, ThrottleOutPacketType.Task | ThrottleOutPacketType.HighPriority);
3833 } 3904 }
3834 3905
3906/*
3835 public void SendAnimations(UUID[] animations, int[] seqs, UUID sourceAgentId, UUID[] objectIDs) 3907 public void SendAnimations(UUID[] animations, int[] seqs, UUID sourceAgentId, UUID[] objectIDs)
3836 { 3908 {
3837// m_log.DebugFormat("[LLCLIENTVIEW]: Sending animations for {0} to {1}", sourceAgentId, Name); 3909// m_log.DebugFormat("[LLCLIENTVIEW]: Sending animations for {0} to {1}", sourceAgentId, Name);
3838 3910
3839 AvatarAnimationPacket ani = (AvatarAnimationPacket)PacketPool.Instance.GetPacket(PacketType.AvatarAnimation); 3911 AvatarAnimationPacket ani = (AvatarAnimationPacket)PacketPool.Instance.GetPacket(PacketType.AvatarAnimation);
3840 // TODO: don't create new blocks if recycling an old packet 3912 // TODO: don't create new blocks if recycling an old packet
3841 ani.AnimationSourceList = new AvatarAnimationPacket.AnimationSourceListBlock[animations.Length];
3842 ani.Sender = new AvatarAnimationPacket.SenderBlock(); 3913 ani.Sender = new AvatarAnimationPacket.SenderBlock();
3843 ani.Sender.ID = sourceAgentId; 3914 ani.Sender.ID = sourceAgentId;
3844 ani.AnimationList = new AvatarAnimationPacket.AnimationListBlock[animations.Length]; 3915 ani.AnimationList = new AvatarAnimationPacket.AnimationListBlock[animations.Length];
3845 ani.PhysicalAvatarEventList = new AvatarAnimationPacket.PhysicalAvatarEventListBlock[0]; 3916 ani.PhysicalAvatarEventList = new AvatarAnimationPacket.PhysicalAvatarEventListBlock[0];
3846 3917
3847 for (int i = 0; i < animations.Length; ++i) 3918 //self animations
3919 if (sourceAgentId == AgentId)
3848 { 3920 {
3849 ani.AnimationList[i] = new AvatarAnimationPacket.AnimationListBlock(); 3921 List<int> withobjects = new List<int>(animations.Length);
3850 ani.AnimationList[i].AnimID = animations[i]; 3922 List<int> noobjects = new List<int>(animations.Length);
3851 ani.AnimationList[i].AnimSequenceID = seqs[i]; 3923 for(int i = 0; i < animations.Length; ++i)
3924 {
3925 if(objectIDs[i] == sourceAgentId || objectIDs[i] == UUID.Zero)
3926 noobjects.Add(i);
3927 else
3928 withobjects.Add(i);
3929 }
3852 3930
3853 ani.AnimationSourceList[i] = new AvatarAnimationPacket.AnimationSourceListBlock(); 3931 ani.AnimationSourceList = new AvatarAnimationPacket.AnimationSourceListBlock[withobjects.Count];
3854 if (objectIDs[i].Equals(sourceAgentId)) 3932 int k = 0;
3855 ani.AnimationSourceList[i].ObjectID = UUID.Zero; 3933 foreach (int i in withobjects)
3856 else 3934 {
3857 ani.AnimationSourceList[i].ObjectID = objectIDs[i]; 3935 ani.AnimationList[k] = new AvatarAnimationPacket.AnimationListBlock();
3936 ani.AnimationList[k].AnimID = animations[i];
3937 ani.AnimationList[k].AnimSequenceID = seqs[i];
3938 ani.AnimationSourceList[k] = new AvatarAnimationPacket.AnimationSourceListBlock();
3939 ani.AnimationSourceList[k].ObjectID = objectIDs[i];
3940 k++;
3941 }
3942 foreach (int i in noobjects)
3943 {
3944 ani.AnimationList[k] = new AvatarAnimationPacket.AnimationListBlock();
3945 ani.AnimationList[k].AnimID = animations[i];
3946 ani.AnimationList[k].AnimSequenceID = seqs[i];
3947 k++;
3948 }
3949 }
3950 else
3951 {
3952 ani.AnimationSourceList = new AvatarAnimationPacket.AnimationSourceListBlock[0];
3953 for (int i = 0; i < animations.Length; ++i)
3954 {
3955 ani.AnimationList[i] = new AvatarAnimationPacket.AnimationListBlock();
3956 ani.AnimationList[i].AnimID = animations[i];
3957 ani.AnimationList[i].AnimSequenceID = seqs[i];
3958 }
3858 } 3959 }
3960
3859 OutPacket(ani, ThrottleOutPacketType.Task | ThrottleOutPacketType.HighPriority); 3961 OutPacket(ani, ThrottleOutPacketType.Task | ThrottleOutPacketType.HighPriority);
3860 } 3962 }
3963*/
3964
3965 static private readonly byte[] AvatarAnimationHeader = new byte[] {
3966 Helpers.MSG_RELIABLE,
3967 0, 0, 0, 0, // sequence number
3968 0, // extra
3969 20 // ID (high frequency)
3970 };
3971
3972 public void SendAnimations(UUID[] animations, int[] seqs, UUID sourceAgentId, UUID[] objectIDs)
3973 {
3974 // m_log.DebugFormat("[LLCLIENTVIEW]: Sending animations for {0} to {1}", sourceAgentId, Name);
3975
3976 UDPPacketBuffer buf = m_udpServer.GetNewUDPBuffer(m_udpClient.RemoteEndPoint);
3977 byte[] data = buf.Data;
3978 //setup header
3979 Buffer.BlockCopy(AvatarAnimationHeader, 0, data, 0, 7);
3980 //agent block
3981 sourceAgentId.ToBytes(data, 7);
3982
3983 // animations count
3984 data[23] = (byte)animations.Length;
3985
3986 int pos = 24;
3987
3988 //self animations
3989 if (sourceAgentId == AgentId)
3990 {
3991 List<int> withobjects = new List<int>(animations.Length);
3992 List<int> noobjects = new List<int>(animations.Length);
3993 for (int i = 0; i < animations.Length; ++i)
3994 {
3995 if (objectIDs[i] == sourceAgentId || objectIDs[i] == UUID.Zero)
3996 noobjects.Add(i);
3997 else
3998 withobjects.Add(i);
3999 }
4000
4001 // first the ones with corresponding objects
4002 foreach (int i in withobjects)
4003 {
4004 animations[i].ToBytes(data, pos); pos += 16;
4005 Utils.IntToBytesSafepos(seqs[i], data, pos); pos += 4;
4006 }
4007 // then the rest
4008 foreach (int i in noobjects)
4009 {
4010 animations[i].ToBytes(data, pos); pos += 16;
4011 Utils.IntToBytesSafepos(seqs[i], data, pos); pos += 4;
4012 }
4013 // object ids block
4014 data[pos++] = (byte)withobjects.Count;
4015 foreach (int i in withobjects)
4016 {
4017 objectIDs[i].ToBytes(data, pos); pos += 16;
4018 }
4019 }
4020 else
4021 {
4022 for(int i = 0; i < animations.Length; ++i)
4023 {
4024 animations[i].ToBytes(data, pos); pos += 16;
4025 Utils.IntToBytesSafepos(seqs[i], data, pos); pos += 4;
4026 }
4027 data[pos++] = 0; // no object ids
4028 }
4029
4030 data[pos++] = 0; // no physical avatar events
4031
4032 buf.DataLength = pos;
4033 m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task | ThrottleOutPacketType.HighPriority,
4034 null, false, false);
4035 }
3861 4036
3862 public void SendObjectAnimations(UUID[] animations, int[] seqs, UUID senderId) 4037 public void SendObjectAnimations(UUID[] animations, int[] seqs, UUID senderId)
3863 { 4038 {
@@ -3889,36 +4064,31 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3889 /// </summary> 4064 /// </summary>
3890 public void SendEntityFullUpdateImmediate(ISceneEntity ent) 4065 public void SendEntityFullUpdateImmediate(ISceneEntity ent)
3891 { 4066 {
3892// m_log.DebugFormat( 4067 if (ent == null || (!(ent is ScenePresence) && !(ent is SceneObjectPart)))
3893// "[LLCLIENTVIEW]: Sending immediate object update for avatar {0} {1} to {2} {3}",
3894// avatar.Name, avatar.UUID, Name, AgentId);
3895
3896 if (ent == null)
3897 return; 4068 return;
3898 4069
3899 ObjectUpdatePacket objupdate = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate); 4070 UDPPacketBuffer buf = m_udpServer.GetNewUDPBuffer(m_udpClient.RemoteEndPoint);
3900 objupdate.Header.Zerocoded = true; 4071 Buffer.BlockCopy(objectUpdateHeader, 0, buf.Data, 0, 7);
3901 4072
3902 objupdate.RegionData.TimeDilation = Utils.FloatToUInt16(m_scene.TimeDilation, 0.0f, 1.0f); 4073 LLUDPZeroEncoder zc = new LLUDPZeroEncoder(buf.Data);
3903 objupdate.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[1]; 4074 zc.Position = 7;
3904 4075
3905 if(ent is ScenePresence) 4076 zc.AddUInt64(m_scene.RegionInfo.RegionHandle);
3906 { 4077 zc.AddUInt16(Utils.FloatToUInt16(m_scene.TimeDilation, 0.0f, 1.0f));
3907 ScenePresence presence = ent as ScenePresence; 4078
3908 objupdate.RegionData.RegionHandle = presence.RegionHandle; 4079 zc.AddByte(1); // block count
3909 objupdate.ObjectData[0] = CreateAvatarUpdateBlock(presence); 4080
3910 } 4081 ThrottleOutPacketType ptype = ThrottleOutPacketType.Task;
3911 else if(ent is SceneObjectPart) 4082 if (ent is ScenePresence)
3912 { 4083 {
3913 SceneObjectPart part = ent as SceneObjectPart; 4084 CreateAvatarUpdateBlock(ent as ScenePresence, zc);
3914 objupdate.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; 4085 ptype |= ThrottleOutPacketType.HighPriority;
3915 objupdate.ObjectData[0] = CreatePrimUpdateBlock(part, (ScenePresence)SceneAgent);
3916 } 4086 }
4087 else
4088 CreatePrimUpdateBlock(ent as SceneObjectPart, (ScenePresence)SceneAgent, zc);
3917 4089
3918 OutPacket(objupdate, ThrottleOutPacketType.Task | ThrottleOutPacketType.HighPriority); 4090 buf.DataLength = zc.Finish();
3919 4091 m_udpServer.SendUDPPacket(m_udpClient, buf, ptype , null, false, false);
3920 // We need to record the avatar local id since the root prim of an attachment points to this.
3921// m_attachmentsSent.Add(avatar.LocalId);
3922 } 4092 }
3923 4093
3924 public void SendEntityTerseUpdateImmediate(ISceneEntity ent) 4094 public void SendEntityTerseUpdateImmediate(ISceneEntity ent)
@@ -4089,6 +4259,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4089 ResendPrimUpdate(update); 4259 ResendPrimUpdate(update);
4090 } 4260 }
4091 4261
4262 static private readonly byte[] objectUpdateHeader = new byte[] {
4263 Helpers.MSG_RELIABLE | Helpers.MSG_ZEROCODED,
4264 0, 0, 0, 0, // sequence number
4265 0, // extra
4266 12 // ID (high frequency)
4267 };
4268
4269 static private readonly byte[] terseUpdateHeader = new byte[] {
4270 Helpers.MSG_RELIABLE | Helpers.MSG_ZEROCODED, // zero code is not as spec
4271 0, 0, 0, 0, // sequence number
4272 0, // extra
4273 15 // ID (high frequency)
4274 };
4275
4092 private void ProcessEntityUpdates(int maxUpdatesBytes) 4276 private void ProcessEntityUpdates(int maxUpdatesBytes)
4093 { 4277 {
4094 if (!IsActive) 4278 if (!IsActive)
@@ -4098,14 +4282,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4098 if (mysp == null) 4282 if (mysp == null)
4099 return; 4283 return;
4100 4284
4101 List<ObjectUpdatePacket.ObjectDataBlock> objectUpdateBlocks = null; 4285 // List<ObjectUpdateCompressedPacket.ObjectDataBlock> compressedUpdateBlocks = null;
4102 List<ObjectUpdateCompressedPacket.ObjectDataBlock> compressedUpdateBlocks = null;
4103 List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> terseUpdateBlocks = null;
4104 List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> terseAgentUpdateBlocks = null;
4105 List<EntityUpdate> objectUpdates = null; 4286 List<EntityUpdate> objectUpdates = null;
4106 List<EntityUpdate> compressedUpdates = null; 4287 // List<EntityUpdate> compressedUpdates = null;
4107 List<EntityUpdate> terseUpdates = null; 4288 List<EntityUpdate> terseUpdates = null;
4108 List<EntityUpdate> terseAgentUpdates = null;
4109 List<SceneObjectPart> ObjectAnimationUpdates = null; 4289 List<SceneObjectPart> ObjectAnimationUpdates = null;
4110 4290
4111 // Check to see if this is a flush 4291 // Check to see if this is a flush
@@ -4120,10 +4300,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4120 float cullingrange = 64.0f; 4300 float cullingrange = 64.0f;
4121 Vector3 mypos = Vector3.Zero; 4301 Vector3 mypos = Vector3.Zero;
4122 4302
4123 bool orderedDequeue = m_scene.UpdatePrioritizationScheme == UpdatePrioritizationSchemes.SimpleAngularDistance; 4303 //bool orderedDequeue = m_scene.UpdatePrioritizationScheme == UpdatePrioritizationSchemes.SimpleAngularDistance;
4304 bool orderedDequeue = false; // temporary off
4124 4305
4125 HashSet<SceneObjectGroup> GroupsNeedFullUpdate = new HashSet<SceneObjectGroup>(); 4306 HashSet<SceneObjectGroup> GroupsNeedFullUpdate = new HashSet<SceneObjectGroup>();
4126 4307
4308
4127 if (doCulling) 4309 if (doCulling)
4128 { 4310 {
4129 cullingrange = mysp.DrawDistance + m_scene.ReprioritizationDistance + 16f; 4311 cullingrange = mysp.DrawDistance + m_scene.ReprioritizationDistance + 16f;
@@ -4179,7 +4361,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4179 } 4361 }
4180 4362
4181 if (grp.IsAttachment) 4363 if (grp.IsAttachment)
4182 { // Someone else's HUD, why are we getting these? 4364 {
4365 // animated attachments are nasty if not supported by viewer
4366 if(!m_SupportObjectAnimations && grp.RootPart.Shape.MeshFlagEntry)
4367 continue;
4368
4369 // Someone else's HUD, why are we getting these?
4183 if (grp.OwnerID != AgentId && grp.HasPrivateAttachmentPoint) 4370 if (grp.OwnerID != AgentId && grp.HasPrivateAttachmentPoint)
4184 continue; 4371 continue;
4185 4372
@@ -4273,7 +4460,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4273 if(ObjectAnimationUpdates == null) 4460 if(ObjectAnimationUpdates == null)
4274 ObjectAnimationUpdates = new List<SceneObjectPart>(); 4461 ObjectAnimationUpdates = new List<SceneObjectPart>();
4275 ObjectAnimationUpdates.Add(sop); 4462 ObjectAnimationUpdates.Add(sop);
4276 maxUpdatesBytes -= 32 * sop.Animations.Count + 16; 4463 maxUpdatesBytes -= 20 * sop.Animations.Count + 24;
4277 } 4464 }
4278 } 4465 }
4279 } 4466 }
@@ -4304,7 +4491,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4304 PrimUpdateFlags.Velocity | 4491 PrimUpdateFlags.Velocity |
4305 PrimUpdateFlags.Acceleration | 4492 PrimUpdateFlags.Acceleration |
4306 PrimUpdateFlags.AngularVelocity | 4493 PrimUpdateFlags.AngularVelocity |
4307 PrimUpdateFlags.CollisionPlane 4494 PrimUpdateFlags.CollisionPlane |
4495 PrimUpdateFlags.Textures
4308 ); 4496 );
4309 4497
4310 #endregion UpdateFlags to packet type conversion 4498 #endregion UpdateFlags to packet type conversion
@@ -4326,48 +4514,36 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4326 4514
4327 if ((updateFlags & canNotUseImprovedMask) == 0) 4515 if ((updateFlags & canNotUseImprovedMask) == 0)
4328 { 4516 {
4329 ImprovedTerseObjectUpdatePacket.ObjectDataBlock ablock = 4517 if (terseUpdates == null)
4330 CreateImprovedTerseBlock(update.Entity);
4331
4332 if (update.Entity is ScenePresence)
4333 { 4518 {
4334 // ALL presence updates go into a special list 4519 terseUpdates = new List<EntityUpdate>();
4335 if (terseAgentUpdateBlocks == null) 4520 maxUpdatesBytes -= 18;
4336 {
4337 terseAgentUpdateBlocks = new List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>();
4338 terseAgentUpdates = new List<EntityUpdate>();
4339 }
4340 terseAgentUpdateBlocks.Add(ablock);
4341 terseAgentUpdates.Add(update);
4342 } 4521 }
4522 terseUpdates.Add(update);
4523
4524 if (update.Entity is ScenePresence)
4525 maxUpdatesBytes -= 63; // no texture entry
4343 else 4526 else
4344 { 4527 {
4345 // Everything else goes here 4528 if ((updateFlags & PrimUpdateFlags.Textures) == 0)
4346 if (terseUpdateBlocks == null) 4529 maxUpdatesBytes -= 47;
4347 { 4530 else
4348 terseUpdateBlocks = new List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>(); 4531 maxUpdatesBytes -= 150; // aprox
4349 terseUpdates = new List<EntityUpdate>();
4350 }
4351 terseUpdateBlocks.Add(ablock);
4352 terseUpdates.Add(update);
4353 } 4532 }
4354 maxUpdatesBytes -= ablock.Length;
4355 } 4533 }
4356 else 4534 else
4357 { 4535 {
4358 ObjectUpdatePacket.ObjectDataBlock ablock;
4359 if (update.Entity is ScenePresence) 4536 if (update.Entity is ScenePresence)
4360 ablock = CreateAvatarUpdateBlock((ScenePresence)update.Entity); 4537 maxUpdatesBytes -= 150; // crude estimation
4361 else 4538 else
4362 ablock = CreatePrimUpdateBlock((SceneObjectPart)update.Entity, mysp); 4539 maxUpdatesBytes -= 300;
4363 if(objectUpdateBlocks == null) 4540
4541 if(objectUpdates == null)
4364 { 4542 {
4365 objectUpdateBlocks = new List<ObjectUpdatePacket.ObjectDataBlock>();
4366 objectUpdates = new List<EntityUpdate>(); 4543 objectUpdates = new List<EntityUpdate>();
4544 maxUpdatesBytes -= 18;
4367 } 4545 }
4368 objectUpdateBlocks.Add(ablock);
4369 objectUpdates.Add(update); 4546 objectUpdates.Add(update);
4370 maxUpdatesBytes -= ablock.Length;
4371 } 4547 }
4372 4548
4373 #endregion Block Construction 4549 #endregion Block Construction
@@ -4382,29 +4558,87 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4382 4558
4383 timeDilation = Utils.FloatToUInt16(m_scene.TimeDilation, 0.0f, 1.0f); 4559 timeDilation = Utils.FloatToUInt16(m_scene.TimeDilation, 0.0f, 1.0f);
4384 4560
4385 if (terseAgentUpdateBlocks != null) 4561 if(objectUpdates != null)
4386 { 4562 {
4387 ImprovedTerseObjectUpdatePacket packet 4563 int blocks = objectUpdates.Count;
4388 = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ImprovedTerseObjectUpdate); 4564 List<EntityUpdate> tau = new List<EntityUpdate>(30);
4389 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
4390 packet.RegionData.TimeDilation = timeDilation;
4391 packet.ObjectData = terseAgentUpdateBlocks.ToArray();
4392 terseAgentUpdateBlocks.Clear();
4393 4565
4394 OutPacket(packet, ThrottleOutPacketType.Unknown, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(terseAgentUpdates, oPacket); }); 4566 UDPPacketBuffer buf = m_udpServer.GetNewUDPBuffer(m_udpClient.RemoteEndPoint);
4395 } 4567 Buffer.BlockCopy(objectUpdateHeader, 0, buf.Data, 0, 7);
4396 4568
4397 if (objectUpdateBlocks != null) 4569 LLUDPZeroEncoder zc = new LLUDPZeroEncoder(buf.Data);
4398 { 4570 zc.Position = 7;
4399 ObjectUpdatePacket packet = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate); 4571
4400 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; 4572 zc.AddUInt64(m_scene.RegionInfo.RegionHandle);
4401 packet.RegionData.TimeDilation = timeDilation; 4573 zc.AddUInt16(Utils.FloatToUInt16(m_scene.TimeDilation, 0.0f, 1.0f));
4402 packet.ObjectData = objectUpdateBlocks.ToArray(); 4574
4403 objectUpdateBlocks.Clear(); 4575 zc.AddByte(1); // tmp block count
4576
4577 int countposition = zc.Position - 1;
4578
4579 int lastpos = 0;
4580 int lastzc = 0;
4581
4582 int count = 0;
4583 foreach (EntityUpdate eu in objectUpdates)
4584 {
4585 lastpos = zc.Position;
4586 lastzc = zc.ZeroCount;
4587 if (eu.Entity is ScenePresence)
4588 CreateAvatarUpdateBlock((ScenePresence)eu.Entity, zc);
4589 else
4590 CreatePrimUpdateBlock((SceneObjectPart)eu.Entity, mysp, zc);
4591 if (zc.Position < LLUDPServer.MAXPAYLOAD)
4592 {
4593 tau.Add(eu);
4594 ++count;
4595 --blocks;
4596 }
4597 else if (blocks > 0)
4598 {
4599 // we need more packets
4600 UDPPacketBuffer newbuf = m_udpServer.GetNewUDPBuffer(m_udpClient.RemoteEndPoint);
4601 Buffer.BlockCopy(buf.Data, 0, newbuf.Data, 0, countposition); // start is the same
4404 4602
4405 OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(objectUpdates, oPacket); }); 4603 buf.Data[countposition] = (byte)count;
4604 // get pending zeros at cut point
4605 if(lastzc > 0)
4606 {
4607 buf.Data[lastpos++] = 0;
4608 buf.Data[lastpos++] = (byte)lastzc;
4609 }
4610 buf.DataLength = lastpos;
4611
4612 m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task,
4613 delegate (OutgoingPacket oPacket) { ResendPrimUpdates(tau, oPacket); }, false, false);
4614
4615 buf = newbuf;
4616 zc.Data = buf.Data;
4617 zc.ZeroCount = 0;
4618 zc.Position = countposition + 1;
4619 // im lazy now, just do last again
4620 if (eu.Entity is ScenePresence)
4621 CreateAvatarUpdateBlock((ScenePresence)eu.Entity, zc);
4622 else
4623 CreatePrimUpdateBlock((SceneObjectPart)eu.Entity, mysp, zc);
4624
4625 tau = new List<EntityUpdate>(30);
4626 tau.Add(eu);
4627 count = 1;
4628 --blocks;
4629 }
4630 }
4631
4632 if (count > 0)
4633 {
4634 buf.Data[countposition] = (byte)count;
4635 buf.DataLength = zc.Finish();
4636 m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task,
4637 delegate (OutgoingPacket oPacket) { ResendPrimUpdates(tau, oPacket); }, false, false);
4638 }
4406 } 4639 }
4407 4640
4641/*
4408 if (compressedUpdateBlocks != null) 4642 if (compressedUpdateBlocks != null)
4409 { 4643 {
4410 ObjectUpdateCompressedPacket packet = (ObjectUpdateCompressedPacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdateCompressed); 4644 ObjectUpdateCompressedPacket packet = (ObjectUpdateCompressedPacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdateCompressed);
@@ -4415,20 +4649,68 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4415 4649
4416 OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(compressedUpdates, oPacket); }); 4650 OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(compressedUpdates, oPacket); });
4417 } 4651 }
4418 4652*/
4419 if (terseUpdateBlocks != null) 4653 if (terseUpdates != null)
4420 { 4654 {
4421 ImprovedTerseObjectUpdatePacket packet = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket( 4655 int blocks = terseUpdates.Count;
4422 PacketType.ImprovedTerseObjectUpdate); 4656 List<EntityUpdate> tau = new List<EntityUpdate>(30);
4423 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; 4657
4424 packet.RegionData.TimeDilation = timeDilation; 4658 UDPPacketBuffer buf = m_udpServer.GetNewUDPBuffer(m_udpClient.RemoteEndPoint);
4425 packet.ObjectData = terseUpdateBlocks.ToArray(); 4659
4426 terseUpdateBlocks.Clear(); 4660 //setup header and regioninfo block
4661 Buffer.BlockCopy(terseUpdateHeader, 0, buf.Data, 0, 7);
4662 Utils.UInt64ToBytesSafepos(m_scene.RegionInfo.RegionHandle, buf.Data, 7);
4663 Utils.UInt16ToBytes(timeDilation, buf.Data, 15);
4664 int pos = 18;
4665 int lastpos = 0;
4427 4666
4428 OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(terseUpdates, oPacket); }); 4667 int count = 0;
4668 foreach (EntityUpdate eu in terseUpdates)
4669 {
4670 lastpos = pos;
4671 CreateImprovedTerseBlock(eu.Entity, buf.Data, ref pos, (eu.Flags & PrimUpdateFlags.Textures) != 0);
4672 if (pos < LLUDPServer.MAXPAYLOAD)
4673 {
4674 tau.Add(eu);
4675 ++count;
4676 --blocks;
4677 }
4678 else if (blocks > 0)
4679 {
4680 // we need more packets
4681 UDPPacketBuffer newbuf = m_udpServer.GetNewUDPBuffer(m_udpClient.RemoteEndPoint);
4682 Buffer.BlockCopy(buf.Data, 0, newbuf.Data, 0, 17); // start is the same
4683 // copy what we done in excess
4684 int extralen = pos - lastpos;
4685 if(extralen > 0)
4686 Buffer.BlockCopy(buf.Data, lastpos, newbuf.Data, 18, extralen);
4687
4688 pos = 18 + extralen;
4689
4690 buf.Data[17] = (byte)count;
4691 buf.DataLength = lastpos;
4692 // zero encode is not as spec
4693 m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task,
4694 delegate (OutgoingPacket oPacket) { ResendPrimUpdates(tau, oPacket); }, false, true);
4695
4696 tau = new List<EntityUpdate>(30);
4697 tau.Add(eu);
4698 count = 1;
4699 --blocks;
4700 buf = newbuf;
4701 }
4702 }
4703
4704 if (count > 0)
4705 {
4706 buf.Data[17] = (byte)count;
4707 buf.DataLength = pos;
4708 m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task,
4709 delegate (OutgoingPacket oPacket) { ResendPrimUpdates(tau, oPacket); }, false, true);
4710 }
4429 } 4711 }
4430 4712
4431 if(ObjectAnimationUpdates != null) 4713 if (ObjectAnimationUpdates != null)
4432 { 4714 {
4433 foreach (SceneObjectPart sop in ObjectAnimationUpdates) 4715 foreach (SceneObjectPart sop in ObjectAnimationUpdates)
4434 { 4716 {
@@ -4445,13 +4727,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4445 UUID[] ids = null; 4727 UUID[] ids = null;
4446 int[] seqs = null; 4728 int[] seqs = null;
4447 int count = sop.GetAnimations(out ids, out seqs); 4729 int count = sop.GetAnimations(out ids, out seqs);
4448 if(count < 0)
4449 continue;
4450 4730
4451 ObjectAnimationPacket ani = (ObjectAnimationPacket)PacketPool.Instance.GetPacket(PacketType.ObjectAnimation); 4731 ObjectAnimationPacket ani = (ObjectAnimationPacket)PacketPool.Instance.GetPacket(PacketType.ObjectAnimation);
4452 ani.Sender = new ObjectAnimationPacket.SenderBlock(); 4732 ani.Sender = new ObjectAnimationPacket.SenderBlock();
4453 ani.Sender.ID = sop.UUID; 4733 ani.Sender.ID = sop.UUID;
4454 ani.AnimationList = new ObjectAnimationPacket.AnimationListBlock[sop.Animations.Count]; 4734 ani.AnimationList = new ObjectAnimationPacket.AnimationListBlock[count];
4455 4735
4456 for(int i = 0; i< count; i++) 4736 for(int i = 0; i< count; i++)
4457 { 4737 {
@@ -4642,9 +4922,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4642 // These are used to implement an adaptive backoff in the number 4922 // These are used to implement an adaptive backoff in the number
4643 // of updates converted to packets. Since we don't want packets 4923 // of updates converted to packets. Since we don't want packets
4644 // to sit in the queue with old data, only convert enough updates 4924 // to sit in the queue with old data, only convert enough updates
4645 // to packets that can be sent in 200ms. 4925 // to packets that can be sent in 30ms.
4646// private Int32 m_LastQueueFill = 0;
4647// private Int32 m_maxUpdates = 0;
4648 4926
4649 void HandleQueueEmpty(ThrottleOutPacketTypeFlags categories) 4927 void HandleQueueEmpty(ThrottleOutPacketTypeFlags categories)
4650 { 4928 {
@@ -5645,9 +5923,144 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5645 return block; 5923 return block;
5646 } 5924 }
5647 5925
5926 protected void CreateImprovedTerseBlock(ISceneEntity entity, byte[] data, ref int pos, bool includeTexture)
5927 {
5928 #region ScenePresence/SOP Handling
5929
5930 bool avatar = (entity is ScenePresence);
5931 uint localID = entity.LocalId;
5932 uint attachPoint;
5933 Vector4 collisionPlane;
5934 Vector3 position, velocity, acceleration, angularVelocity;
5935 Quaternion rotation;
5936 byte datasize;
5937 byte[] te = null;
5938
5939 if (avatar)
5940 {
5941 ScenePresence presence = (ScenePresence)entity;
5942
5943 position = presence.OffsetPosition;
5944 velocity = presence.Velocity;
5945 acceleration = Vector3.Zero;
5946 rotation = presence.Rotation;
5947 // tpvs can only see rotations around Z in some cases
5948 if (!presence.Flying && !presence.IsSatOnObject)
5949 {
5950 rotation.X = 0f;
5951 rotation.Y = 0f;
5952 }
5953 rotation.Normalize();
5954 angularVelocity = presence.AngularVelocity;
5955
5956 // m_log.DebugFormat(
5957 // "[LLCLIENTVIEW]: Sending terse update to {0} with position {1} in {2}", Name, presence.OffsetPosition, m_scene.Name);
5958
5959 attachPoint = presence.State;
5960 collisionPlane = presence.CollisionPlane;
5961
5962 datasize = 60;
5963 }
5964 else
5965 {
5966 SceneObjectPart part = (SceneObjectPart)entity;
5967
5968 attachPoint = part.ParentGroup.AttachmentPoint;
5969 attachPoint = ((attachPoint % 16) * 16 + (attachPoint / 16));
5970 // m_log.DebugFormat(
5971 // "[LLCLIENTVIEW]: Sending attachPoint {0} for {1} {2} to {3}",
5972 // attachPoint, part.Name, part.LocalId, Name);
5973
5974 collisionPlane = Vector4.Zero;
5975 position = part.RelativePosition;
5976 velocity = part.Velocity;
5977 acceleration = part.Acceleration;
5978 angularVelocity = part.AngularVelocity;
5979 rotation = part.RotationOffset;
5980
5981 datasize = 44;
5982 if(includeTexture)
5983 te = part.Shape.TextureEntry;
5984 }
5985
5986 #endregion ScenePresence/SOP Handling
5987 //object block size
5988 data[pos++] = datasize;
5989
5990 // LocalID
5991 Utils.UIntToBytes(localID, data, pos);
5992 pos += 4;
5993
5994 data[pos++] = (byte)attachPoint;
5995
5996 // Avatar/CollisionPlane
5997 if (avatar)
5998 {
5999 data[pos++] = 1;
6000
6001 if (collisionPlane == Vector4.Zero)
6002 collisionPlane = Vector4.UnitW;
6003 //m_log.DebugFormat("CollisionPlane: {0}",collisionPlane);
6004 collisionPlane.ToBytes(data, pos);
6005 pos += 16;
6006 }
6007 else
6008 {
6009 data[pos++] = 0;
6010 }
6011
6012 // Position
6013 position.ToBytes(data, pos);
6014 pos += 12;
6015
6016 // Velocity
6017 ClampVectorForUint(ref velocity, 128f);
6018 Utils.FloatToUInt16Bytes(velocity.X, 128.0f, data, pos); pos += 2;
6019 Utils.FloatToUInt16Bytes(velocity.Y, 128.0f, data, pos); pos += 2;
6020 Utils.FloatToUInt16Bytes(velocity.Z, 128.0f, data, pos); pos += 2;
6021
6022 // Acceleration
6023 ClampVectorForUint(ref acceleration, 64f);
6024 Utils.FloatToUInt16Bytes(acceleration.X, 64.0f, data, pos); pos += 2;
6025 Utils.FloatToUInt16Bytes(acceleration.Y, 64.0f, data, pos); pos += 2;
6026 Utils.FloatToUInt16Bytes(acceleration.Z, 64.0f, data, pos); pos += 2;
6027
6028 // Rotation
6029 Utils.FloatToUInt16Bytes(rotation.X, 1.0f, data, pos); pos += 2;
6030 Utils.FloatToUInt16Bytes(rotation.Y, 1.0f, data, pos); pos += 2;
6031 Utils.FloatToUInt16Bytes(rotation.Z, 1.0f, data, pos); pos += 2;
6032 Utils.FloatToUInt16Bytes(rotation.W, 1.0f, data, pos); pos += 2;
6033
6034 // Angular Velocity
6035 ClampVectorForUint(ref angularVelocity, 64f);
6036 Utils.FloatToUInt16Bytes(angularVelocity.X, 64.0f, data, pos); pos += 2;
6037 Utils.FloatToUInt16Bytes(angularVelocity.Y, 64.0f, data, pos); pos += 2;
6038 Utils.FloatToUInt16Bytes(angularVelocity.Z, 64.0f, data, pos); pos += 2;
6039
6040 // texture entry block size
6041 if(te == null)
6042 {
6043 data[pos++] = 0;
6044 data[pos++] = 0;
6045 }
6046 else
6047 {
6048 int len = te.Length & 0x7fff;
6049 int totlen = len + 4;
6050 data[pos++] = (byte)totlen;
6051 data[pos++] = (byte)(totlen >> 8);
6052 data[pos++] = (byte)len; // wtf ???
6053 data[pos++] = (byte)(len >> 8);
6054 data[pos++] = 0;
6055 data[pos++] = 0;
6056 Buffer.BlockCopy(te, 0, data, pos, len);
6057 pos += len;
6058 }
6059 // total size 63 or 47 + (texture size + 4)
6060 }
6061
5648 protected ObjectUpdatePacket.ObjectDataBlock CreateAvatarUpdateBlock(ScenePresence data) 6062 protected ObjectUpdatePacket.ObjectDataBlock CreateAvatarUpdateBlock(ScenePresence data)
5649 { 6063 {
5650 Vector3 offsetPosition = data.OffsetPosition;
5651 Quaternion rotation = data.Rotation; 6064 Quaternion rotation = data.Rotation;
5652 // tpvs can only see rotations around Z in some cases 6065 // tpvs can only see rotations around Z in some cases
5653 if(!data.Flying && !data.IsSatOnObject) 6066 if(!data.Flying && !data.IsSatOnObject)
@@ -5657,27 +6070,26 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5657 } 6070 }
5658 rotation.Normalize(); 6071 rotation.Normalize();
5659 6072
5660 uint parentID = data.ParentID;
5661
5662// m_log.DebugFormat( 6073// m_log.DebugFormat(
5663// "[LLCLIENTVIEW]: Sending full update to {0} with pos {1}, vel {2} in {3}", Name, data.OffsetPosition, data.Velocity, m_scene.Name); 6074// "[LLCLIENTVIEW]: Sending full update to {0} with pos {1}, vel {2} in {3}", Name, data.OffsetPosition, data.Velocity, m_scene.Name);
5664 6075
5665 byte[] objectData = new byte[76]; 6076 byte[] objectData = new byte[76];
5666 6077
5667 Vector3 velocity = new Vector3(0, 0, 0); 6078 //Vector3 velocity = Vector3.Zero;
5668 Vector3 acceleration = new Vector3(0, 0, 0); 6079 Vector3 acceleration = Vector3.Zero;
6080 Vector3 angularvelocity = Vector3.Zero;
5669 6081
5670 data.CollisionPlane.ToBytes(objectData, 0); 6082 data.CollisionPlane.ToBytes(objectData, 0);
5671 offsetPosition.ToBytes(objectData, 16); 6083 data.OffsetPosition.ToBytes(objectData, 16);
5672 velocity.ToBytes(objectData, 28); 6084 data.Velocity.ToBytes(objectData, 28);
5673 acceleration.ToBytes(objectData, 40); 6085 acceleration.ToBytes(objectData, 40);
5674 rotation.ToBytes(objectData, 52); 6086 rotation.ToBytes(objectData, 52);
5675 data.AngularVelocity.ToBytes(objectData, 64); 6087 angularvelocity.ToBytes(objectData, 64);
5676 6088
5677 ObjectUpdatePacket.ObjectDataBlock update = new ObjectUpdatePacket.ObjectDataBlock(); 6089 ObjectUpdatePacket.ObjectDataBlock update = new ObjectUpdatePacket.ObjectDataBlock();
5678 6090
5679 update.Data = Utils.EmptyBytes; 6091 update.Data = Utils.EmptyBytes;
5680 update.ExtraParams = new byte[1]; 6092 update.ExtraParams = Utils.EmptyBytes;
5681 update.FullID = data.UUID; 6093 update.FullID = data.UUID;
5682 update.ID = data.LocalId; 6094 update.ID = data.LocalId;
5683 update.Material = (byte)Material.Flesh; 6095 update.Material = (byte)Material.Flesh;
@@ -5714,7 +6126,158 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5714 return update; 6126 return update;
5715 } 6127 }
5716 6128
5717// protected ObjectUpdatePacket.ObjectDataBlock CreatePrimUpdateBlock(SceneObjectPart data, UUID recipientID) 6129 protected void CreateAvatarUpdateBlock(ScenePresence data, byte[] dest, ref int pos)
6130 {
6131 Quaternion rotation = data.Rotation;
6132 // tpvs can only see rotations around Z in some cases
6133 if (!data.Flying && !data.IsSatOnObject)
6134 {
6135 rotation.X = 0f;
6136 rotation.Y = 0f;
6137 }
6138 rotation.Normalize();
6139
6140 //Vector3 velocity = Vector3.Zero;
6141 //Vector3 acceleration = Vector3.Zero;
6142 //Vector3 angularvelocity = Vector3.Zero;
6143
6144 Utils.UIntToBytesSafepos(data.LocalId, dest, pos); pos += 4;
6145 dest[pos++] = 0; // state
6146 data.UUID.ToBytes(dest, pos); pos += 16;
6147 Utils.UIntToBytesSafepos(0 , dest, pos); pos += 4; // crc
6148 dest[pos++] = (byte)PCode.Avatar;
6149 dest[pos++] = (byte)Material.Flesh;
6150 dest[pos++] = 0; // clickaction
6151 data.Appearance.AvatarSize.ToBytes(dest, pos); pos += 12;
6152
6153 // objectdata block
6154 dest[pos++] = 76;
6155 data.CollisionPlane.ToBytes(dest, pos); pos += 16;
6156 data.OffsetPosition.ToBytes(dest, pos); pos += 12;
6157 data.Velocity.ToBytes(dest, pos); pos += 12;
6158
6159 //acceleration.ToBytes(dest, pos); pos += 12;
6160 Array.Clear(dest, pos, 12); pos += 12;
6161
6162 rotation.ToBytes(dest, pos); pos += 12;
6163
6164 //angularvelocity.ToBytes(dest, pos); pos += 12;
6165 Array.Clear(dest, pos, 12); pos += 12;
6166
6167 SceneObjectPart parentPart = data.ParentPart;
6168 if (parentPart != null)
6169 {
6170 Utils.UIntToBytesSafepos(parentPart.ParentGroup.LocalId, dest, pos);
6171 pos += 4;
6172 }
6173 else
6174 {
6175// Utils.UIntToBytesSafepos(0, dest, pos);
6176// pos += 4;
6177 dest[pos++] = 0;
6178 dest[pos++] = 0;
6179 dest[pos++] = 0;
6180 dest[pos++] = 0;
6181 }
6182
6183 //Utils.UIntToBytesSafepos(0, dest, pos); pos += 4; //update flags
6184 dest[pos++] = 0;
6185 dest[pos++] = 0;
6186 dest[pos++] = 0;
6187 dest[pos++] = 0;
6188
6189 //pbs
6190 dest[pos++] = 16;
6191 dest[pos++] = 1;
6192 //Utils.UInt16ToBytes(0, dest, pos); pos += 2;
6193 //Utils.UInt16ToBytes(0, dest, pos); pos += 2;
6194 dest[pos++] = 0;
6195 dest[pos++] = 0;
6196 dest[pos++] = 0;
6197 dest[pos++] = 0;
6198
6199 dest[pos++] = 100;
6200 dest[pos++] = 100;
6201
6202 // rest of pbs is 0 (15), texture entry (2) and texture anim (1)
6203 const int pbszeros = 15 + 2 + 1;
6204 Array.Clear(dest, pos, pbszeros); pos += pbszeros;
6205
6206 //NameValue
6207 byte[] nv = Utils.StringToBytes("FirstName STRING RW SV " + data.Firstname + "\nLastName STRING RW SV " +
6208 data.Lastname + "\nTitle STRING RW SV " + data.Grouptitle);
6209 int len = nv.Length;
6210 dest[pos++] = (byte)len;
6211 dest[pos++] = (byte)(len >> 8);
6212 Buffer.BlockCopy(nv, 0, dest, pos, len); pos += len;
6213
6214 // data(2), text(1), text color(4), media url(1), PBblock(1), ExtramParams(1),
6215 // sound id(16), sound owner(16) gain (4), flags (1), radius (4)
6216 // jointtype(1) joint pivot(12) joint offset(12)
6217 const int lastzeros = 2 + 1 + 4 + 1 + 1 + 1 + 16 + 16 + 4 + 1 + 4 + 1 + 12 + 12;
6218 Array.Clear(dest, pos, lastzeros); pos += lastzeros;
6219 }
6220
6221 protected void CreateAvatarUpdateBlock(ScenePresence data, LLUDPZeroEncoder zc)
6222 {
6223 Quaternion rotation = data.Rotation;
6224 // tpvs can only see rotations around Z in some cases
6225 if (!data.Flying && !data.IsSatOnObject)
6226 {
6227 rotation.X = 0f;
6228 rotation.Y = 0f;
6229 }
6230 rotation.Normalize();
6231
6232 zc.AddUInt(data.LocalId);
6233 zc.AddByte(0);
6234 zc.AddUUID(data.UUID);
6235 zc.AddZeros(4); // crc unused
6236 zc.AddByte((byte)PCode.Avatar);
6237 zc.AddByte((byte)Material.Flesh);
6238 zc.AddByte(0); // clickaction
6239 zc.AddVector3(data.Appearance.AvatarSize);
6240
6241 // objectdata block
6242 zc.AddByte(76); // fixed avatar block size
6243 zc.AddVector4(data.CollisionPlane);
6244 zc.AddVector3(data.OffsetPosition);
6245 zc.AddVector3(data.Velocity);
6246 //zc.AddVector3(acceleration);
6247 zc.AddZeros(12);
6248 zc.AddNormQuat(rotation);
6249 //zc.AddVector3(angularvelocity);
6250 zc.AddZeros(12);
6251
6252 SceneObjectPart parentPart = data.ParentPart;
6253 if (parentPart != null)
6254 zc.AddUInt(parentPart.ParentGroup.LocalId);
6255 else
6256 zc.AddZeros(4);
6257
6258 zc.AddZeros(4); //update flags
6259
6260 //pbs volume data 23
6261 //texture entry 2
6262 //texture anim (1)
6263 const int pbszeros = 23 + 2 + 1;
6264 zc.AddZeros(pbszeros);
6265
6266 //NameValue
6267 byte[] nv = Utils.StringToBytes("FirstName STRING RW SV " + data.Firstname + "\nLastName STRING RW SV " +
6268 data.Lastname + "\nTitle STRING RW SV " + data.Grouptitle);
6269 int len = nv.Length;
6270 zc.AddByte((byte)len);
6271 zc.AddByte((byte)(len >> 8));
6272 zc.AddBytes(nv, len);
6273
6274 // data(2), text(1), text color(4), media url(1), PBblock(1), ExtramParams(1),
6275 // sound id(16), sound owner(16) gain (4), flags (1), radius (4)
6276 // jointtype(1) joint pivot(12) joint offset(12)
6277 const int lastzeros = 2 + 1 + 4 + 1 + 1 + 1 + 16 + 16 + 4 + 1 + 4 + 1 + 12 + 12;
6278 zc.AddZeros(lastzeros);
6279 }
6280
5718 protected ObjectUpdatePacket.ObjectDataBlock CreatePrimUpdateBlock(SceneObjectPart part, ScenePresence sp) 6281 protected ObjectUpdatePacket.ObjectDataBlock CreatePrimUpdateBlock(SceneObjectPart part, ScenePresence sp)
5719 { 6282 {
5720 byte[] objectData = new byte[60]; 6283 byte[] objectData = new byte[60];
@@ -5737,32 +6300,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5737 //update.JointPivot = Vector3.Zero; 6300 //update.JointPivot = Vector3.Zero;
5738 //update.JointType = 0; 6301 //update.JointType = 0;
5739 update.Material = part.Material; 6302 update.Material = part.Material;
5740/*
5741 if (data.ParentGroup.IsAttachment)
5742 {
5743 update.NameValue
5744 = Util.StringToBytes256(
5745 string.Format("AttachItemID STRING RW SV {0}", data.ParentGroup.FromItemID));
5746
5747 update.State = (byte)((data.ParentGroup.AttachmentPoint % 16) * 16 + (data.ParentGroup.AttachmentPoint / 16));
5748
5749// m_log.DebugFormat(
5750// "[LLCLIENTVIEW]: Sending NameValue {0} for {1} {2} to {3}",
5751// Util.UTF8.GetString(update.NameValue), data.Name, data.LocalId, Name);
5752//
5753// m_log.DebugFormat(
5754// "[LLCLIENTVIEW]: Sending state {0} for {1} {2} to {3}",
5755// update.State, data.Name, data.LocalId, Name);
5756 }
5757 else
5758 {
5759 update.NameValue = Utils.EmptyBytes;
5760
5761 // The root part state is the canonical state for all parts of the object. The other part states in the
5762 // case for attachments may contain conflicting values that can end up crashing the viewer.
5763 update.State = data.ParentGroup.RootPart.Shape.State;
5764 }
5765*/
5766 6303
5767 if (part.ParentGroup.IsAttachment) 6304 if (part.ParentGroup.IsAttachment)
5768 { 6305 {
@@ -5858,15 +6395,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5858 6395
5859 #endregion PrimFlags 6396 #endregion PrimFlags
5860 6397
5861 if (part.Sound != UUID.Zero || part.SoundFlags != 0) 6398 bool hassound = part.Sound != UUID.Zero || part.SoundFlags != 0;
6399 if (hassound)
5862 { 6400 {
5863 update.Sound = part.Sound; 6401 update.Sound = part.Sound;
5864 update.OwnerID = part.OwnerID;
5865 update.Gain = (float)part.SoundGain; 6402 update.Gain = (float)part.SoundGain;
5866 update.Radius = (float)part.SoundRadius; 6403 update.Radius = (float)part.SoundRadius;
5867 update.Flags = part.SoundFlags; 6404 update.Flags = part.SoundFlags;
5868 } 6405 }
5869 6406
6407 if(hassound || update.PSBlock.Length > 1)
6408 update.OwnerID = part.OwnerID;
6409
5870 switch ((PCode)part.Shape.PCode) 6410 switch ((PCode)part.Shape.PCode)
5871 { 6411 {
5872 case PCode.Grass: 6412 case PCode.Grass:
@@ -5882,6 +6422,308 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5882 return update; 6422 return update;
5883 } 6423 }
5884 6424
6425 protected void CreatePrimUpdateBlock(SceneObjectPart part, ScenePresence sp, LLUDPZeroEncoder zc)
6426 {
6427 // prepare data
6428
6429 #region PrimFlags
6430 // prim/update flags
6431 PrimFlags primflags = (PrimFlags)m_scene.Permissions.GenerateClientFlags(part, sp);
6432 // Don't send the CreateSelected flag to everyone
6433 primflags &= ~PrimFlags.CreateSelected;
6434 if (sp.UUID == part.OwnerID)
6435 {
6436 if (part.CreateSelected)
6437 {
6438 // Only send this flag once, then unset it
6439 primflags |= PrimFlags.CreateSelected;
6440 part.CreateSelected = false;
6441 }
6442 }
6443 #endregion PrimFlags
6444
6445 // data block
6446 byte[] data = null;
6447 byte state = part.Shape.State;
6448 PCode pcode = (PCode)part.Shape.PCode;
6449
6450 //vegetation is special so just do it inline
6451 if(pcode == PCode.Grass || pcode == PCode.Tree || pcode == PCode.NewTree)
6452 {
6453 zc.AddUInt(part.LocalId);
6454 zc.AddByte(state); // state
6455 zc.AddUUID(part.UUID);
6456 zc.AddZeros(4); // crc unused
6457 zc.AddByte((byte)pcode);
6458 // material 1
6459 // clickaction 1
6460 zc.AddZeros(2);
6461 zc.AddVector3(part.Shape.Scale);
6462
6463 // objectdata block
6464 zc.AddByte(60); // fixed object block size
6465 zc.AddVector3(part.RelativePosition);
6466 if (pcode == PCode.Grass)
6467 zc.AddZeros(48);
6468 else
6469 {
6470 zc.AddZeros(24);
6471 Quaternion rot = part.RotationOffset;
6472 rot.Normalize();
6473 zc.AddNormQuat(rot);
6474 zc.AddZeros(12);
6475 }
6476
6477 zc.AddUInt(part.ParentID);
6478 zc.AddUInt((uint)primflags); //update flags
6479
6480 /*
6481 if (pcode == PCode.Grass)
6482 {
6483 //pbs volume data 23
6484 //texture entry 2
6485 //texture anim 1
6486 //name value 2
6487 // data 1
6488 // text 5
6489 // media url 1
6490 // particle system 1
6491 // Extraparams 1
6492 // sound id 16
6493 // ownwer 16
6494 // sound gain 4
6495 // sound flags 1
6496 // sound radius 4
6497 // jointtype 1
6498 // joint pivot 12
6499 // joint offset 12
6500 zc.AddZeros(23 + 2 + 1 + 2 + 1 + 5 + 1 + 1 + 1 + 16 + 16 + 4 + 1 + 4 + 1 + 12 + 12);
6501 return;
6502 }
6503 */
6504
6505 //pbs volume data 23
6506 //texture entry 2
6507 //texture anim 1
6508 //name value 2
6509 zc.AddZeros(23 + 2 + 1 + 2);
6510
6511 //data: the tree type
6512 zc.AddByte(1);
6513 zc.AddZeros(1);
6514 zc.AddByte(state);
6515
6516 // text 5
6517 // media url 1
6518 // particle system 1
6519 // Extraparams 1
6520 // sound id 16
6521 // ownwer 16
6522 // sound gain 4
6523 // sound flags 1
6524 // sound radius 4
6525 // jointtype 1
6526 // joint pivot 12
6527 // joint offset 12
6528 zc.AddZeros(5 + 1 + 1 + 1 + 16 + 16 + 4 + 1 + 4 + 1 + 12 + 12);
6529
6530 return;
6531 }
6532
6533 //NameValue and state
6534 byte[] nv = null;
6535
6536 if (part.ParentGroup.IsAttachment)
6537 {
6538 if (part.IsRoot)
6539 nv = Util.StringToBytes256("AttachItemID STRING RW SV " + part.ParentGroup.FromItemID);
6540
6541 int st = (int)part.ParentGroup.AttachmentPoint;
6542 state = (byte)(((st & 0xf0) >> 4) + ((st & 0x0f) << 4)); ;
6543 }
6544
6545 // filter out mesh faces hack
6546 ushort profileBegin = part.Shape.ProfileBegin;
6547 ushort profileHollow = part.Shape.ProfileHollow;
6548 byte profileCurve = part.Shape.ProfileCurve;
6549 byte pathScaleY = part.Shape.PathScaleY;
6550
6551 if (part.Shape.SculptType == (byte)SculptType.Mesh) // filter out hack
6552 {
6553 profileCurve = (byte)(part.Shape.ProfileCurve & 0x0f);
6554 // fix old values that confused viewers
6555 if (profileBegin == 1)
6556 profileBegin = 9375;
6557 if (profileHollow == 1)
6558 profileHollow = 27500;
6559 // fix torus hole size Y that also confuse some viewers
6560 if (profileCurve == (byte)ProfileShape.Circle && pathScaleY < 150)
6561 pathScaleY = 150;
6562 }
6563
6564 // do encode the things
6565 zc.AddUInt(part.LocalId);
6566 zc.AddByte(state); // state
6567 zc.AddUUID(part.UUID);
6568 zc.AddZeros(4); // crc unused
6569 zc.AddByte((byte)pcode);
6570 zc.AddByte(part.Material);
6571 zc.AddByte(part.ClickAction); // clickaction
6572 zc.AddVector3(part.Shape.Scale);
6573
6574 // objectdata block
6575 zc.AddByte(60); // fixed object block size
6576 zc.AddVector3(part.RelativePosition);
6577 zc.AddVector3(part.Velocity);
6578 zc.AddVector3(part.Acceleration);
6579 Quaternion rotation = part.RotationOffset;
6580 rotation.Normalize();
6581 zc.AddNormQuat(rotation);
6582 zc.AddVector3(part.AngularVelocity);
6583
6584 zc.AddUInt(part.ParentID);
6585 zc.AddUInt((uint)primflags); //update flags
6586
6587 //pbs
6588 zc.AddByte(part.Shape.PathCurve);
6589 zc.AddByte(profileCurve);
6590 zc.AddUInt16(part.Shape.PathBegin);
6591 zc.AddUInt16(part.Shape.PathEnd);
6592 zc.AddByte(part.Shape.PathScaleX);
6593 zc.AddByte(pathScaleY);
6594 zc.AddByte(part.Shape.PathShearX);
6595 zc.AddByte(part.Shape.PathShearY);
6596 zc.AddByte((byte)part.Shape.PathTwist);
6597 zc.AddByte((byte)part.Shape.PathTwistBegin);
6598 zc.AddByte((byte)part.Shape.PathRadiusOffset);
6599 zc.AddByte((byte)part.Shape.PathTaperX);
6600 zc.AddByte((byte)part.Shape.PathTaperY);
6601 zc.AddByte(part.Shape.PathRevolutions);
6602 zc.AddByte((byte)part.Shape.PathSkew);
6603 zc.AddUInt16(profileBegin);
6604 zc.AddUInt16(part.Shape.ProfileEnd);
6605 zc.AddUInt16(profileHollow);
6606
6607 // texture
6608 byte[] tentry = part.Shape.TextureEntry;
6609 if (tentry == null)
6610 zc.AddZeros(2);
6611 else
6612 {
6613 int len = tentry.Length;
6614 zc.AddByte((byte)len);
6615 zc.AddByte((byte)(len >> 8));
6616 zc.AddBytes(tentry, len);
6617 }
6618
6619 // texture animation
6620 byte[] tanim = part.TextureAnimation;
6621 if (tanim == null)
6622 zc.AddZeros(1);
6623 else
6624 {
6625 int len = tanim.Length;
6626 zc.AddByte((byte)len);
6627 zc.AddBytes(tanim, len);
6628 }
6629
6630 //NameValue
6631 if(nv == null)
6632 zc.AddZeros(2);
6633 else
6634 {
6635 int len = nv.Length;
6636 zc.AddByte((byte)len);
6637 zc.AddByte((byte)(len >> 8));
6638 zc.AddBytes(nv, len);
6639 }
6640
6641 // data
6642 if (data == null)
6643 zc.AddZeros(2);
6644 else
6645 {
6646 int len = data.Length;
6647 zc.AddByte((byte)len);
6648 zc.AddByte((byte)(len >> 8));
6649 zc.AddBytes(data, len);
6650 }
6651
6652 //text
6653 if (part.Text == null || part.Text.Length == 0)
6654 zc.AddZeros(5);
6655 else
6656 {
6657 byte[] tbuf = Util.StringToBytes(part.Text, 254);
6658 int len = tbuf.Length;
6659 zc.AddByte((byte)len);
6660 zc.AddBytes(tbuf, len);
6661
6662 //textcolor
6663 byte[] tc = part.GetTextColor().GetBytes(false);
6664 zc.AddBytes(tc, 4);
6665 }
6666
6667 //media url
6668 if (part.MediaUrl == null || part.MediaUrl.Length == 0)
6669 zc.AddZeros(1);
6670 else
6671 {
6672 byte[] tbuf = Util.StringToBytes(part.MediaUrl, 255);
6673 int len = tbuf.Length;
6674 zc.AddByte((byte)len);
6675 zc.AddBytes(tbuf, len);
6676 }
6677
6678 bool hasps = false;
6679 //particle system
6680 byte[] ps = part.ParticleSystem;
6681 if (ps == null || ps.Length < 1)
6682 zc.AddZeros(1);
6683 else
6684 {
6685 int len = ps.Length;
6686 zc.AddByte((byte)len);
6687 zc.AddBytes(ps, len);
6688 hasps = true;
6689 }
6690
6691 //Extraparams
6692 byte[] ep = part.Shape.ExtraParams;
6693 if (ep == null || ep.Length < 2)
6694 zc.AddZeros(1);
6695 else
6696 {
6697 int len = ep.Length;
6698 zc.AddByte((byte)len);
6699 zc.AddBytes(ep, len);
6700 }
6701
6702 bool hassound = part.Sound != UUID.Zero || part.SoundFlags != 0;
6703 if (hassound)
6704 zc.AddUUID(part.Sound);
6705 else
6706 zc.AddZeros(16);
6707
6708 if (hassound || hasps)
6709 zc.AddUUID(part.OwnerID);
6710 else
6711 zc.AddZeros(16);
6712
6713 if (hassound)
6714 {
6715 zc.AddFloat((float)part.SoundGain);
6716 zc.AddByte(part.SoundFlags);
6717 zc.AddFloat((float)part.SoundRadius);
6718 }
6719 else
6720 zc.AddZeros(9);
6721
6722 // jointtype(1) joint pivot(12) joint offset(12)
6723 const int lastzeros = 1 + 12 + 12;
6724 zc.AddZeros(lastzeros);
6725 }
6726
5885 protected ObjectUpdateCompressedPacket.ObjectDataBlock CreateCompressedUpdateBlock(SceneObjectPart part, PrimUpdateFlags updateFlags) 6727 protected ObjectUpdateCompressedPacket.ObjectDataBlock CreateCompressedUpdateBlock(SceneObjectPart part, PrimUpdateFlags updateFlags)
5886 { 6728 {
5887 // TODO: Implement this 6729 // TODO: Implement this
@@ -10047,7 +10889,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
10047 10889
10048 UUID.TryParse(Utils.BytesToString(messagePacket.ParamList[1].Parameter), out Prey); 10890 UUID.TryParse(Utils.BytesToString(messagePacket.ParamList[1].Parameter), out Prey);
10049 10891
10050 OnEstateTeleportOneUserHomeRequest(this, invoice, SenderID, Prey); 10892 OnEstateTeleportOneUserHomeRequest(this, invoice, SenderID, Prey, false);
10051 } 10893 }
10052 return true; 10894 return true;
10053 case "teleporthomeallusers": 10895 case "teleporthomeallusers":
@@ -10195,7 +11037,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
10195 11037
10196 UUID.TryParse(Utils.BytesToString(messagePacket.ParamList[0].Parameter), out Prey); 11038 UUID.TryParse(Utils.BytesToString(messagePacket.ParamList[0].Parameter), out Prey);
10197 11039
10198 OnEstateTeleportOneUserHomeRequest(this, invoice, SenderID, Prey); 11040 OnEstateTeleportOneUserHomeRequest(this, invoice, SenderID, Prey, true);
10199 } 11041 }
10200 return true; 11042 return true;
10201 11043
@@ -12560,14 +13402,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
12560 /// provide your own method.</param> 13402 /// provide your own method.</param>
12561 protected void OutPacket(Packet packet, ThrottleOutPacketType throttlePacketType, bool doAutomaticSplitting, UnackedPacketMethod method) 13403 protected void OutPacket(Packet packet, ThrottleOutPacketType throttlePacketType, bool doAutomaticSplitting, UnackedPacketMethod method)
12562 { 13404 {
12563
12564/* this is causing packet loss for some reason
12565 if(!m_udpClient.IsConnected)
12566 {
12567 PacketPool.Instance.ReturnPacket(packet);
12568 return;
12569 }
12570*/
12571 if (m_outPacketsToDrop != null) 13405 if (m_outPacketsToDrop != null)
12572 { 13406 {
12573 if (m_outPacketsToDrop.Contains(packet.Type.ToString())) 13407 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..2981337 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
120 /// <summary>Circuit code that this client is connected on</summary> 120 /// <summary>Circuit code that this client is connected on</summary>
121 public readonly uint CircuitCode; 121 public readonly uint CircuitCode;
122 /// <summary>Sequence numbers of packets we've received (for duplicate checking)</summary> 122 /// <summary>Sequence numbers of packets we've received (for duplicate checking)</summary>
123 public IncomingPacketHistoryCollection PacketArchive = new IncomingPacketHistoryCollection(200); 123 public IncomingPacketHistoryCollection PacketArchive = new IncomingPacketHistoryCollection(256);
124 124
125 /// <summary>Packets we have sent that need to be ACKed by the client</summary> 125 /// <summary>Packets we have sent that need to be ACKed by the client</summary>
126 public UnackedPacketCollection NeedAcks = new UnackedPacketCollection(); 126 public UnackedPacketCollection NeedAcks = new UnackedPacketCollection();
@@ -210,12 +210,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
210 } 210 }
211 } 211 }
212 212
213 /// <summary>
214 /// This is the percentage of the udp texture queue to add to the task queue since
215 /// textures are now generally handled through http.
216 /// </summary>
217 private double m_cannibalrate = 0.0;
218
219 private ClientInfo m_info = new ClientInfo(); 213 private ClientInfo m_info = new ClientInfo();
220 214
221 /// <summary> 215 /// <summary>
@@ -257,8 +251,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
257 // Create an array of token buckets for this clients different throttle categories 251 // Create an array of token buckets for this clients different throttle categories
258 m_throttleCategories = new TokenBucket[THROTTLE_CATEGORY_COUNT]; 252 m_throttleCategories = new TokenBucket[THROTTLE_CATEGORY_COUNT];
259 253
260 m_cannibalrate = rates.CannibalizeTextureRate;
261
262 m_burst = rates.Total * rates.BrustTime; 254 m_burst = rates.Total * rates.BrustTime;
263 255
264 for (int i = 0; i < THROTTLE_CATEGORY_COUNT; i++) 256 for (int i = 0; i < THROTTLE_CATEGORY_COUNT; i++)
@@ -449,12 +441,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
449 asset = Math.Max(asset, LLUDPServer.MTU); 441 asset = Math.Max(asset, LLUDPServer.MTU);
450*/ 442*/
451 443
452 // Since most textures are now delivered through http, make it possible
453 // to cannibalize some of the bw from the texture throttle to use for
454 // the task queue (e.g. object updates)
455 task = task + (int)(m_cannibalrate * texture);
456 texture = (int)((1 - m_cannibalrate) * texture);
457
458 int total = resend + land + wind + cloud + task + texture + asset; 444 int total = resend + land + wind + cloud + task + texture + asset;
459 445
460 float m_burst = total * m_burstTime; 446 float m_burst = total * m_burstTime;
@@ -575,22 +561,22 @@ namespace OpenSim.Region.ClientStack.LindenUDP
575 { 561 {
576 DoubleLocklessQueue<OutgoingPacket> queue = m_packetOutboxes[category]; 562 DoubleLocklessQueue<OutgoingPacket> queue = m_packetOutboxes[category];
577 563
578 if (m_deliverPackets == false) 564 if (forceQueue || m_deliverPackets == false)
579 { 565 {
580 queue.Enqueue(packet, highPriority); 566 queue.Enqueue(packet, highPriority);
581 return true; 567 return true;
582 } 568 }
583 569
584 TokenBucket bucket = m_throttleCategories[category]; 570 // need to enqueue if queue is not empty
585
586 // Don't send this packet if queue is not empty
587 if (queue.Count > 0 || m_nextPackets[category] != null) 571 if (queue.Count > 0 || m_nextPackets[category] != null)
588 { 572 {
589 queue.Enqueue(packet, highPriority); 573 queue.Enqueue(packet, highPriority);
590 return true; 574 return true;
591 } 575 }
592 576
593 if (!forceQueue && bucket.CheckTokens(packet.Buffer.DataLength)) 577 // check bandwidth
578 TokenBucket bucket = m_throttleCategories[category];
579 if (bucket.CheckTokens(packet.Buffer.DataLength))
594 { 580 {
595 // enough tokens so it can be sent imediatly by caller 581 // enough tokens so it can be sent imediatly by caller
596 bucket.RemoveTokens(packet.Buffer.DataLength); 582 bucket.RemoveTokens(packet.Buffer.DataLength);
@@ -608,7 +594,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
608 // We don't have a token bucket for this category, so it will not be queued 594 // We don't have a token bucket for this category, so it will not be queued
609 return false; 595 return false;
610 } 596 }
611
612 } 597 }
613 598
614 /// <summary> 599 /// <summary>
@@ -650,6 +635,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
650 // leaving a dequeued packet still waiting to be sent out. Try to 635 // leaving a dequeued packet still waiting to be sent out. Try to
651 // send it again 636 // send it again
652 OutgoingPacket nextPacket = m_nextPackets[i]; 637 OutgoingPacket nextPacket = m_nextPackets[i];
638 if(nextPacket.Buffer == null)
639 {
640 if (m_packetOutboxes[i].Count < 5)
641 emptyCategories |= CategoryToFlag(i);
642 continue;
643 }
653 if (bucket.RemoveTokens(nextPacket.Buffer.DataLength)) 644 if (bucket.RemoveTokens(nextPacket.Buffer.DataLength))
654 { 645 {
655 // Send the packet 646 // Send the packet
@@ -681,21 +672,29 @@ namespace OpenSim.Region.ClientStack.LindenUDP
681 { 672 {
682 // A packet was pulled off the queue. See if we have 673 // A packet was pulled off the queue. See if we have
683 // enough tokens in the bucket to send it out 674 // enough tokens in the bucket to send it out
684 if (bucket.RemoveTokens(packet.Buffer.DataLength)) 675 if(packet.Buffer == null)
685 { 676 {
686 // Send the packet 677 // packet canceled elsewhere (by a ack for example)
687 m_udpServer.SendPacketFinal(packet);
688 packetSent = true;
689
690 if (queue.Count < 5) 678 if (queue.Count < 5)
691 emptyCategories |= CategoryToFlag(i); 679 emptyCategories |= CategoryToFlag(i);
692 } 680 }
693 else 681 else
694 { 682 {
695 // Save the dequeued packet for the next iteration 683 if (bucket.RemoveTokens(packet.Buffer.DataLength))
696 m_nextPackets[i] = packet; 684 {
685 // Send the packet
686 m_udpServer.SendPacketFinal(packet);
687 packetSent = true;
688
689 if (queue.Count < 5)
690 emptyCategories |= CategoryToFlag(i);
691 }
692 else
693 {
694 // Save the dequeued packet for the next iteration
695 m_nextPackets[i] = packet;
696 }
697 } 697 }
698
699 } 698 }
700 else 699 else
701 { 700 {
@@ -803,8 +802,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
803 } 802 }
804 } 803 }
805 804
806
807
808 /// <summary> 805 /// <summary>
809 /// Fires the OnQueueEmpty callback and sets the minimum time that it 806 /// Fires the OnQueueEmpty callback and sets the minimum time that it
810 /// can be called again 807 /// can be called again
@@ -843,6 +840,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
843 return 0; 840 return 0;
844 } 841 }
845 842
843 public void FreeUDPBuffer(UDPPacketBuffer buf)
844 {
845 m_udpServer.FreeUDPBuffer(buf);
846 }
847
846 /// <summary> 848 /// <summary>
847 /// Converts a <seealso cref="ThrottleOutPacketType"/> integer to a 849 /// Converts a <seealso cref="ThrottleOutPacketType"/> integer to a
848 /// flag value 850 /// flag value
@@ -853,34 +855,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP
853 { 855 {
854 ThrottleOutPacketType category = (ThrottleOutPacketType)i; 856 ThrottleOutPacketType category = (ThrottleOutPacketType)i;
855 857
856 /*
857 * Land = 1,
858 /// <summary>Wind data</summary>
859 Wind = 2,
860 /// <summary>Cloud data</summary>
861 Cloud = 3,
862 /// <summary>Any packets that do not fit into the other throttles</summary>
863 Task = 4,
864 /// <summary>Texture assets</summary>
865 Texture = 5,
866 /// <summary>Non-texture assets</summary>
867 Asset = 6,
868 */
869
870 switch (category) 858 switch (category)
871 { 859 {
872 case ThrottleOutPacketType.Land: 860 case ThrottleOutPacketType.Land:
873 return ThrottleOutPacketTypeFlags.Land; 861 return ThrottleOutPacketTypeFlags.Land; // Terrain data
874 case ThrottleOutPacketType.Wind: 862 case ThrottleOutPacketType.Wind:
875 return ThrottleOutPacketTypeFlags.Wind; 863 return ThrottleOutPacketTypeFlags.Wind; // Wind data
876 case ThrottleOutPacketType.Cloud: 864 case ThrottleOutPacketType.Cloud:
877 return ThrottleOutPacketTypeFlags.Cloud; 865 return ThrottleOutPacketTypeFlags.Cloud; // Cloud data
878 case ThrottleOutPacketType.Task: 866 case ThrottleOutPacketType.Task:
879 return ThrottleOutPacketTypeFlags.Task; 867 return ThrottleOutPacketTypeFlags.Task; // Object updates and everything not on the other categories
880 case ThrottleOutPacketType.Texture: 868 case ThrottleOutPacketType.Texture:
881 return ThrottleOutPacketTypeFlags.Texture; 869 return ThrottleOutPacketTypeFlags.Texture; // Textures data (also impacts http texture and mesh by default)
882 case ThrottleOutPacketType.Asset: 870 case ThrottleOutPacketType.Asset:
883 return ThrottleOutPacketTypeFlags.Asset; 871 return ThrottleOutPacketTypeFlags.Asset; // Non-texture Assets data
884 default: 872 default:
885 return 0; 873 return 0;
886 } 874 }
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
index 35d29a5..2300800 100644..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
256 256
257 /// <summary>Maximum transmission unit, or UDP packet size, for the LLUDP protocol</summary> 257 /// <summary>Maximum transmission unit, or UDP packet size, for the LLUDP protocol</summary>
258 public const int MTU = 1400; 258 public const int MTU = 1400;
259 public const int MAXPAYLOAD = 1250;
259 260
260 /// <summary>Number of forced client logouts due to no receipt of packets before timeout.</summary> 261 /// <summary>Number of forced client logouts due to no receipt of packets before timeout.</summary>
261 public int ClientLogoutsDueToNoReceives { get; protected set; } 262 public int ClientLogoutsDueToNoReceives { get; protected set; }
@@ -274,10 +275,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
274 /// <summary>The measured resolution of Environment.TickCount</summary> 275 /// <summary>The measured resolution of Environment.TickCount</summary>
275 public readonly float TickCountResolution; 276 public readonly float TickCountResolution;
276 277
277 /// <summary>Number of prim updates to put on the queue each time the
278 /// OnQueueEmpty event is triggered for updates</summary>
279 public readonly int PrimUpdatesPerCallback;
280
281 /// <summary>Number of texture packets to put on the queue each time the 278 /// <summary>Number of texture packets to put on the queue each time the
282 /// OnQueueEmpty event is triggered for textures</summary> 279 /// OnQueueEmpty event is triggered for textures</summary>
283 public readonly int TextureSendLimit; 280 public readonly int TextureSendLimit;
@@ -344,18 +341,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
344 341
345 protected ExpiringCache<IPEndPoint, Queue<UDPPacketBuffer>> m_pendingCache = new ExpiringCache<IPEndPoint, Queue<UDPPacketBuffer>>(); 342 protected ExpiringCache<IPEndPoint, Queue<UDPPacketBuffer>> m_pendingCache = new ExpiringCache<IPEndPoint, Queue<UDPPacketBuffer>>();
346 343
347 protected Pool<IncomingPacket> m_incomingPacketPool;
348
349 /// <summary>
350 /// Stat for number of packets in the main pool awaiting use.
351 /// </summary>
352 protected Stat m_poolCountStat;
353
354 /// <summary>
355 /// Stat for number of packets in the inbound packet pool awaiting use.
356 /// </summary>
357 protected Stat m_incomingPacketPoolStat;
358
359 protected int m_defaultRTO = 0; 344 protected int m_defaultRTO = 0;
360 protected int m_maxRTO = 0; 345 protected int m_maxRTO = 0;
361 protected int m_ackTimeout = 0; 346 protected int m_ackTimeout = 0;
@@ -452,7 +437,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
452 m_recvBufferSize = config.GetInt("client_socket_rcvbuf_size", 0); 437 m_recvBufferSize = config.GetInt("client_socket_rcvbuf_size", 0);
453 sceneThrottleBps = config.GetInt("scene_throttle_max_bps", 0); 438 sceneThrottleBps = config.GetInt("scene_throttle_max_bps", 0);
454 439
455 PrimUpdatesPerCallback = config.GetInt("PrimUpdatesPerCallback", 100);
456 TextureSendLimit = config.GetInt("TextureSendLimit", 20); 440 TextureSendLimit = config.GetInt("TextureSendLimit", 20);
457 441
458 m_defaultRTO = config.GetInt("DefaultRTO", 0); 442 m_defaultRTO = config.GetInt("DefaultRTO", 0);
@@ -463,7 +447,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
463 } 447 }
464 else 448 else
465 { 449 {
466 PrimUpdatesPerCallback = 100;
467 TextureSendLimit = 20; 450 TextureSendLimit = 20;
468 m_ackTimeout = 1000 * 60; // 1 minute 451 m_ackTimeout = 1000 * 60; // 1 minute
469 m_pausedAckTimeout = 1000 * 300; // 5 minutes 452 m_pausedAckTimeout = 1000 * 300; // 5 minutes
@@ -498,7 +481,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
498 481
499// if (usePools) 482// if (usePools)
500// EnablePools(); 483// EnablePools();
501 base.DisablePools();
502 } 484 }
503 485
504 public void Start() 486 public void Start()
@@ -554,83 +536,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
554 OqrEngine.Stop(); 536 OqrEngine.Stop();
555 } 537 }
556 538
557 public override bool EnablePools()
558 {
559 if (!UsePools)
560 {
561 base.EnablePools();
562
563 m_incomingPacketPool = new Pool<IncomingPacket>(() => new IncomingPacket(), 500);
564
565 return true;
566 }
567
568 return false;
569 }
570
571 public override bool DisablePools()
572 {
573 if (UsePools)
574 {
575 base.DisablePools();
576
577 StatsManager.DeregisterStat(m_incomingPacketPoolStat);
578
579 // We won't null out the pool to avoid a race condition with code that may be in the middle of using it.
580
581 return true;
582 }
583
584 return false;
585 }
586
587 /// <summary>
588 /// This is a seperate method so that it can be called once we have an m_scene to distinguish different scene
589 /// stats.
590 /// </summary>
591 protected internal void EnablePoolStats()
592 {
593 m_poolCountStat
594 = new Stat(
595 "UDPPacketBufferPoolCount",
596 "Objects within the UDPPacketBuffer pool",
597 "The number of objects currently stored within the UDPPacketBuffer pool",
598 "",
599 "clientstack",
600 Scene.Name,
601 StatType.Pull,
602 stat => stat.Value = Pool.Count,
603 StatVerbosity.Debug);
604
605 StatsManager.RegisterStat(m_poolCountStat);
606
607 m_incomingPacketPoolStat
608 = new Stat(
609 "IncomingPacketPoolCount",
610 "Objects within incoming packet pool",
611 "The number of objects currently stored within the incoming packet pool",
612 "",
613 "clientstack",
614 Scene.Name,
615 StatType.Pull,
616 stat => stat.Value = m_incomingPacketPool.Count,
617 StatVerbosity.Debug);
618
619 StatsManager.RegisterStat(m_incomingPacketPoolStat);
620 }
621
622 /// <summary>
623 /// Disables pool stats.
624 /// </summary>
625 protected internal void DisablePoolStats()
626 {
627 StatsManager.DeregisterStat(m_poolCountStat);
628 m_poolCountStat = null;
629
630 StatsManager.DeregisterStat(m_incomingPacketPoolStat);
631 m_incomingPacketPoolStat = null;
632 }
633
634 /// <summary> 539 /// <summary>
635 /// If the outgoing UDP thread times out, then return client that was being processed to help with debugging. 540 /// If the outgoing UDP thread times out, then return client that was being processed to help with debugging.
636 /// </summary> 541 /// </summary>
@@ -658,8 +563,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
658 string.Format("Incoming Packet Async Handling Engine ({0})", Scene.Name), 563 string.Format("Incoming Packet Async Handling Engine ({0})", Scene.Name),
659 "INCOMING PACKET ASYNC HANDLING ENGINE"); 564 "INCOMING PACKET ASYNC HANDLING ENGINE");
660*/ 565*/
661 OqrEngine 566 OqrEngine = new JobEngine(
662 = new JobEngine(
663 string.Format("Outgoing Queue Refill Engine ({0})", Scene.Name), 567 string.Format("Outgoing Queue Refill Engine ({0})", Scene.Name),
664 "OUTGOING QUEUE REFILL ENGINE"); 568 "OUTGOING QUEUE REFILL ENGINE");
665 569
@@ -769,15 +673,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP
769 stat => stat.Value = OqrEngine.JobsWaiting, 673 stat => stat.Value = OqrEngine.JobsWaiting,
770 StatVerbosity.Debug)); 674 StatVerbosity.Debug));
771 675
772 // We delay enabling pool stats to AddScene() instead of Initialize() so that we can distinguish pool stats by 676 StatsManager.RegisterStat(
773 // scene name 677 new Stat(
774 if (UsePools) 678 "UDPBuffersPoolCount",
775 EnablePoolStats(); 679 "Buffers in the UDP buffers pool",
776 680 "The number of buffers currently stored within the UDP buffers pool",
681 "",
682 "clientstack",
683 Scene.Name,
684 StatType.Pull,
685 stat => stat.Value = m_udpBuffersPoolPtr + 1,
686 StatVerbosity.Debug));
777 687
778 LLUDPServerCommands commands = new LLUDPServerCommands(MainConsole.Instance, this); 688 LLUDPServerCommands commands = new LLUDPServerCommands(MainConsole.Instance, this);
779 commands.Register(); 689 commands.Register();
780
781 } 690 }
782 691
783 public bool HandlesRegion(Location x) 692 public bool HandlesRegion(Location x)
@@ -939,9 +848,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
939 // The vast majority of packets are less than 200 bytes, although due to asset transfers and packet splitting 848 // The vast majority of packets are less than 200 bytes, although due to asset transfers and packet splitting
940 // there are a decent number of packets in the 1000-1140 byte range. We allocate one of two sizes of data here 849 // there are a decent number of packets in the 1000-1140 byte range. We allocate one of two sizes of data here
941 // to accomodate for both common scenarios and provide ample room for ACK appending in both 850 // to accomodate for both common scenarios and provide ample room for ACK appending in both
942 int bufferSize = (dataLength > 180) ? LLUDPServer.MTU : 200; 851 //int bufferSize = (dataLength > 180) ? LLUDPServer.MTU : 200;
943 852
944 UDPPacketBuffer buffer = new UDPPacketBuffer(udpClient.RemoteEndPoint, bufferSize); 853 //UDPPacketBuffer buffer = new UDPPacketBuffer(udpClient.RemoteEndPoint, bufferSize);
854 UDPPacketBuffer buffer = GetNewUDPBuffer(udpClient.RemoteEndPoint);
945 855
946 // Zerocode if needed 856 // Zerocode if needed
947 if (doZerocode) 857 if (doZerocode)
@@ -971,7 +881,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
971 // If the packet data wasn't already copied during zerocoding, copy it now 881 // If the packet data wasn't already copied during zerocoding, copy it now
972 if (doCopy) 882 if (doCopy)
973 { 883 {
974 if (dataLength <= buffer.Data.Length) 884 //if (dataLength <= buffer.Data.Length)
885 if (dataLength <= LLUDPServer.MTU)
975 { 886 {
976 Buffer.BlockCopy(data, 0, buffer.Data, 0, dataLength); 887 Buffer.BlockCopy(data, 0, buffer.Data, 0, dataLength);
977 } 888 }
@@ -979,7 +890,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
979 { 890 {
980 m_log.Error("[LLUDPSERVER]: Packet exceeded buffer size! This could be an indication of packet assembly not obeying the MTU. Type=" + 891 m_log.Error("[LLUDPSERVER]: Packet exceeded buffer size! This could be an indication of packet assembly not obeying the MTU. Type=" +
981 type + ", DataLength=" + dataLength + ", BufferLength=" + buffer.Data.Length); 892 type + ", DataLength=" + dataLength + ", BufferLength=" + buffer.Data.Length);
982 buffer = new UDPPacketBuffer(udpClient.RemoteEndPoint, dataLength); 893 // buffer = new UDPPacketBuffer(udpClient.RemoteEndPoint, dataLength);
894 buffer = GetNewUDPBuffer(udpClient.RemoteEndPoint);
983 Buffer.BlockCopy(data, 0, buffer.Data, 0, dataLength); 895 Buffer.BlockCopy(data, 0, buffer.Data, 0, dataLength);
984 } 896 }
985 } 897 }
@@ -1017,6 +929,89 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1017 #endregion Queue or Send 929 #endregion Queue or Send
1018 } 930 }
1019 931
932 public unsafe UDPPacketBuffer ZeroEncode(UDPPacketBuffer input)
933 {
934 UDPPacketBuffer zb = GetNewUDPBuffer(null);
935 int srclen = input.DataLength;
936 byte[] src = input.Data;
937 byte[] dest = zb.Data;
938
939 int zerolen = 6;
940 byte zerocount = 0;
941
942 for (int i = zerolen; i < srclen; i++)
943 {
944 if (src[i] == 0x00)
945 {
946 zerocount++;
947 if (zerocount == 0)
948 {
949 dest[zerolen++] = 0x00;
950 dest[zerolen++] = 0xff;
951 zerocount++;
952 }
953 }
954 else
955 {
956 if (zerocount != 0)
957 {
958 dest[zerolen++] = 0x00;
959 dest[zerolen++] = zerocount;
960 zerocount = 0;
961 }
962
963 dest[zerolen++] = src[i];
964 }
965 }
966
967 if (zerocount != 0)
968 {
969 dest[zerolen++] = 0x00;
970 dest[zerolen++] = zerocount;
971 }
972
973 if(zerolen >= srclen)
974 {
975 FreeUDPBuffer(zb);
976
977 src[0] &= unchecked((byte)~Helpers.MSG_ZEROCODED);
978 return input;
979 }
980
981 Buffer.BlockCopy(src, 0, dest, 0, 6);
982
983 zb.RemoteEndPoint = input.RemoteEndPoint;
984 zb.DataLength = zerolen;
985
986 FreeUDPBuffer(input);
987
988 return zb;
989 }
990
991 public void SendUDPPacket(
992 LLUDPClient udpClient, UDPPacketBuffer buffer, ThrottleOutPacketType category, UnackedPacketMethod method, bool forcequeue, bool zerocode)
993 {
994 bool highPriority = false;
995
996 if(zerocode)
997 buffer = ZeroEncode(buffer);
998
999 if (category != ThrottleOutPacketType.Unknown && (category & ThrottleOutPacketType.HighPriority) != 0)
1000 {
1001 category = (ThrottleOutPacketType)((int)category & 127);
1002 highPriority = true;
1003 }
1004
1005 OutgoingPacket outgoingPacket = new OutgoingPacket(udpClient, buffer, category, null);
1006
1007 // If we were not provided a method for handling unacked, use the UDPServer default method
1008 if ((outgoingPacket.Buffer.Data[0] & Helpers.MSG_RELIABLE) != 0)
1009 outgoingPacket.UnackedMethod = ((method == null) ? delegate (OutgoingPacket oPacket) { ResendUnacked(oPacket); } : method);
1010
1011 if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket, forcequeue, highPriority))
1012 SendPacketFinal(outgoingPacket);
1013 }
1014
1020 public void SendAcks(LLUDPClient udpClient) 1015 public void SendAcks(LLUDPClient udpClient)
1021 { 1016 {
1022 uint ack; 1017 uint ack;
@@ -1066,7 +1061,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1066 { 1061 {
1067 LLUDPClient udpClient = client.UDPClient; 1062 LLUDPClient udpClient = client.UDPClient;
1068 1063
1069 if (!udpClient.IsConnected) 1064 if (!client.IsActive || !udpClient.IsConnected)
1070 return; 1065 return;
1071 1066
1072 // Disconnect an agent if no packets are received for some time 1067 // Disconnect an agent if no packets are received for some time
@@ -1136,14 +1131,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1136 internal void SendPacketFinal(OutgoingPacket outgoingPacket) 1131 internal void SendPacketFinal(OutgoingPacket outgoingPacket)
1137 { 1132 {
1138 UDPPacketBuffer buffer = outgoingPacket.Buffer; 1133 UDPPacketBuffer buffer = outgoingPacket.Buffer;
1134 if(buffer == null) // canceled packet
1135 return;
1136 LLUDPClient udpClient = outgoingPacket.Client;
1137 if (!udpClient.IsConnected)
1138 return;
1139
1139 byte flags = buffer.Data[0]; 1140 byte flags = buffer.Data[0];
1140 bool isResend = (flags & Helpers.MSG_RESENT) != 0; 1141 bool isResend = (flags & Helpers.MSG_RESENT) != 0;
1141 bool isReliable = (flags & Helpers.MSG_RELIABLE) != 0; 1142 bool isReliable = (flags & Helpers.MSG_RELIABLE) != 0;
1142 bool isZerocoded = (flags & Helpers.MSG_ZEROCODED) != 0; 1143 bool isZerocoded = (flags & Helpers.MSG_ZEROCODED) != 0;
1143 LLUDPClient udpClient = outgoingPacket.Client;
1144
1145 if (!udpClient.IsConnected)
1146 return;
1147 1144
1148 int dataLength = buffer.DataLength; 1145 int dataLength = buffer.DataLength;
1149 1146
@@ -1154,7 +1151,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1154 // no more ACKs to append 1151 // no more ACKs to append
1155 int ackCount = 0; 1152 int ackCount = 0;
1156 uint ack; 1153 uint ack;
1157 while (dataLength + 5 < buffer.Data.Length && ackCount < 256 && udpClient.PendingAcks.Dequeue(out ack)) 1154 while (dataLength + 5 < MTU && ackCount < 256 && udpClient.PendingAcks.Dequeue(out ack))
1158 { 1155 {
1159 Utils.UIntToBytesBig(ack, buffer.Data, dataLength); 1156 Utils.UIntToBytesBig(ack, buffer.Data, dataLength);
1160 dataLength += 4; 1157 dataLength += 4;
@@ -1168,22 +1165,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1168 // Set the appended ACKs flag on this packet 1165 // Set the appended ACKs flag on this packet
1169 buffer.Data[0] = (byte)(buffer.Data[0] | Helpers.MSG_APPENDED_ACKS); 1166 buffer.Data[0] = (byte)(buffer.Data[0] | Helpers.MSG_APPENDED_ACKS);
1170 } 1167 }
1168 buffer.DataLength = dataLength;
1171 } 1169 }
1172 1170
1173 buffer.DataLength = dataLength;
1174
1175 if (!isResend) 1171 if (!isResend)
1176 { 1172 {
1177 // Not a resend, assign a new sequence number 1173 // Not a resend, assign a new sequence number
1178 uint sequenceNumber = (uint)Interlocked.Increment(ref udpClient.CurrentSequence); 1174 uint sequenceNumber = (uint)Interlocked.Increment(ref udpClient.CurrentSequence);
1179 Utils.UIntToBytesBig(sequenceNumber, buffer.Data, 1); 1175 Utils.UIntToBytesBig(sequenceNumber, buffer.Data, 1);
1180 outgoingPacket.SequenceNumber = sequenceNumber; 1176 outgoingPacket.SequenceNumber = sequenceNumber;
1181
1182 if (isReliable)
1183 {
1184 // Add this packet to the list of ACK responses we are waiting on from the server
1185 udpClient.NeedAcks.Add(outgoingPacket);
1186 }
1187 } 1177 }
1188 else 1178 else
1189 { 1179 {
@@ -1196,9 +1186,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1196 PacketsSentCount++; 1186 PacketsSentCount++;
1197 1187
1198 SyncSend(buffer); 1188 SyncSend(buffer);
1189
1199 // Keep track of when this packet was sent out (right now) 1190 // Keep track of when this packet was sent out (right now)
1200 outgoingPacket.TickCount = Environment.TickCount & Int32.MaxValue; 1191 outgoingPacket.TickCount = Environment.TickCount & Int32.MaxValue;
1201 1192
1193 if (outgoingPacket.UnackedMethod == null)
1194 FreeUDPBuffer(buffer);
1195 else if(!isResend)
1196 {
1197 // Add this packet to the list of ACK responses we are waiting on from the server
1198 udpClient.NeedAcks.Add(outgoingPacket);
1199 }
1200
1202 if (udpClient.DebugDataOutLevel > 0) 1201 if (udpClient.DebugDataOutLevel > 0)
1203 m_log.DebugFormat( 1202 m_log.DebugFormat(
1204 "[LLUDPSERVER]: Sending packet #{0} (rel: {1}, res: {2}) to {3} from {4}", 1203 "[LLUDPSERVER]: Sending packet #{0} (rel: {1}, res: {2}) to {3} from {4}",
@@ -1240,7 +1239,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1240// buffer.DataLength, buffer.RemoteEndPoint, m_scene.RegionInfo.RegionName); 1239// buffer.DataLength, buffer.RemoteEndPoint, m_scene.RegionInfo.RegionName);
1241 1240
1242 RecordMalformedInboundPacket(endPoint); 1241 RecordMalformedInboundPacket(endPoint);
1243 1242 FreeUDPBuffer(buffer);
1244 return; // Drop undersized packet 1243 return; // Drop undersized packet
1245 } 1244 }
1246 1245
@@ -1260,21 +1259,29 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1260// buffer.RemoteEndPoint, m_scene.RegionInfo.RegionName); 1259// buffer.RemoteEndPoint, m_scene.RegionInfo.RegionName);
1261 1260
1262 RecordMalformedInboundPacket(endPoint); 1261 RecordMalformedInboundPacket(endPoint);
1263 1262 FreeUDPBuffer(buffer);
1264 return; // Malformed header 1263 return; // Malformed header
1265 } 1264 }
1266 1265
1267 try 1266 try
1268 { 1267 {
1269// packet = Packet.BuildPacket(buffer.Data, ref packetEnd, 1268 // get a buffer for zero decode using the udp buffers pool
1270// // Only allocate a buffer for zerodecoding if the packet is zerocoded 1269 UDPPacketBuffer zerodecodebufferholder = null;
1271// ((buffer.Data[0] & Helpers.MSG_ZEROCODED) != 0) ? new byte[4096] : null); 1270 byte[] zerodecodebuffer = null;
1271 // only if needed
1272 if (((buffer.Data[0] & Helpers.MSG_ZEROCODED) != 0))
1273 {
1274 zerodecodebufferholder = GetNewUDPBuffer(null);
1275 zerodecodebuffer = zerodecodebufferholder.Data;
1276 }
1277
1278 packet = Packet.BuildPacket(buffer.Data, ref packetEnd, zerodecodebuffer);
1272 // If OpenSimUDPBase.UsePool == true (which is currently separate from the PacketPool) then we 1279 // If OpenSimUDPBase.UsePool == true (which is currently separate from the PacketPool) then we
1273 // assume that packet construction does not retain a reference to byte[] buffer.Data (instead, all 1280 // assume that packet construction does not retain a reference to byte[] buffer.Data (instead, all
1274 // bytes are copied out). 1281 // bytes are copied out).
1275 packet = PacketPool.Instance.GetPacket(buffer.Data, ref packetEnd, 1282 // packet = PacketPool.Instance.GetPacket(buffer.Data, ref packetEnd, zerodecodebuffer);
1276 // Only allocate a buffer for zerodecoding if the packet is zerocoded 1283 if(zerodecodebufferholder != null)
1277 ((buffer.Data[0] & Helpers.MSG_ZEROCODED) != 0) ? new byte[4096] : null); 1284 FreeUDPBuffer(zerodecodebufferholder);
1278 } 1285 }
1279 catch (Exception e) 1286 catch (Exception e)
1280 { 1287 {
@@ -1292,7 +1299,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1292 } 1299 }
1293 1300
1294 RecordMalformedInboundPacket(endPoint); 1301 RecordMalformedInboundPacket(endPoint);
1295 1302 FreeUDPBuffer(buffer);
1296 return; 1303 return;
1297 } 1304 }
1298 1305
@@ -1311,17 +1318,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1311 lock (m_pendingCache) 1318 lock (m_pendingCache)
1312 { 1319 {
1313 if (m_pendingCache.Contains(endPoint)) 1320 if (m_pendingCache.Contains(endPoint))
1321 {
1322 FreeUDPBuffer(buffer);
1314 return; 1323 return;
1324 }
1315 1325
1316 m_pendingCache.AddOrUpdate(endPoint, new Queue<UDPPacketBuffer>(), 60); 1326 m_pendingCache.AddOrUpdate(endPoint, new Queue<UDPPacketBuffer>(), 60);
1317 } 1327 }
1318 1328
1319 // We need to copy the endpoint so that it doesn't get changed when another thread reuses the 1329 Util.FireAndForget(HandleUseCircuitCode, new object[] { endPoint, packet });
1320 // buffer. 1330 FreeUDPBuffer(buffer);
1321 object[] array = new object[] { new IPEndPoint(endPoint.Address, endPoint.Port), packet };
1322
1323 Util.FireAndForget(HandleUseCircuitCode, array);
1324
1325 return; 1331 return;
1326 } 1332 }
1327 } 1333 }
@@ -1336,24 +1342,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1336 queue.Enqueue(buffer); 1342 queue.Enqueue(buffer);
1337 return; 1343 return;
1338 } 1344 }
1339
1340/*
1341 else if (packet.Type == PacketType.CompleteAgentMovement)
1342 {
1343 // Send ack straight away to let the viewer know that we got it.
1344 SendAckImmediate(endPoint, packet.Header.Sequence);
1345
1346 // We need to copy the endpoint so that it doesn't get changed when another thread reuses the
1347 // buffer.
1348 object[] array = new object[] { new IPEndPoint(endPoint.Address, endPoint.Port), packet };
1349
1350 Util.FireAndForget(HandleCompleteMovementIntoRegion, array);
1351
1352 return;
1353 }
1354 */
1355 } 1345 }
1356 1346
1347 FreeUDPBuffer(buffer);
1348
1357 // Determine which agent this packet came from 1349 // Determine which agent this packet came from
1358 if (client == null || !(client is LLClientView)) 1350 if (client == null || !(client is LLClientView))
1359 { 1351 {
@@ -1471,10 +1463,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1471 LogPacketHeader(true, udpClient.CircuitCode, 0, packet.Type, (ushort)packet.Length); 1463 LogPacketHeader(true, udpClient.CircuitCode, 0, packet.Type, (ushort)packet.Length);
1472 #endregion BinaryStats 1464 #endregion BinaryStats
1473 1465
1474
1475//AgentUpdate removed from here
1476
1477
1478 #region Ping Check Handling 1466 #region Ping Check Handling
1479 1467
1480 if (packet.Type == PacketType.StartPingCheck) 1468 if (packet.Type == PacketType.StartPingCheck)
@@ -1506,17 +1494,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1506 1494
1507 IncomingPacket incomingPacket; 1495 IncomingPacket incomingPacket;
1508 1496
1509 // Inbox insertion 1497 incomingPacket = new IncomingPacket((LLClientView)client, packet);
1510 if (UsePools)
1511 {
1512 incomingPacket = m_incomingPacketPool.GetObject();
1513 incomingPacket.Client = (LLClientView)client;
1514 incomingPacket.Packet = packet;
1515 }
1516 else
1517 {
1518 incomingPacket = new IncomingPacket((LLClientView)client, packet);
1519 }
1520 1498
1521// if (incomingPacket.Packet.Type == PacketType.AgentUpdate || 1499// if (incomingPacket.Packet.Type == PacketType.AgentUpdate ||
1522// incomingPacket.Packet.Type == PacketType.ChatFromViewer) 1500// incomingPacket.Packet.Type == PacketType.ChatFromViewer)
@@ -1525,7 +1503,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1525// else 1503// else
1526// packetInbox.Enqueue(incomingPacket); 1504// packetInbox.Enqueue(incomingPacket);
1527 packetInbox.Add(incomingPacket); 1505 packetInbox.Add(incomingPacket);
1528
1529 } 1506 }
1530 1507
1531 #region BinaryStats 1508 #region BinaryStats
@@ -1685,7 +1662,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1685 { 1662 {
1686 m_log.DebugFormat("[LLUDPSERVER]: Client created but no pending queue present"); 1663 m_log.DebugFormat("[LLUDPSERVER]: Client created but no pending queue present");
1687 return; 1664 return;
1688
1689 } 1665 }
1690 m_pendingCache.Remove(endPoint); 1666 m_pendingCache.Remove(endPoint);
1691 } 1667 }
@@ -1881,13 +1857,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1881 byte[] packetData = ack.ToBytes(); 1857 byte[] packetData = ack.ToBytes();
1882 int length = packetData.Length; 1858 int length = packetData.Length;
1883 1859
1884 UDPPacketBuffer buffer = new UDPPacketBuffer(remoteEndpoint, length); 1860 UDPPacketBuffer buffer = GetNewUDPBuffer(remoteEndpoint);
1885 buffer.DataLength = length; 1861 buffer.DataLength = length;
1886 1862
1887 Buffer.BlockCopy(packetData, 0, buffer.Data, 0, length); 1863 Buffer.BlockCopy(packetData, 0, buffer.Data, 0, length);
1888 1864
1889// AsyncBeginSend(buffer); 1865// AsyncBeginSend(buffer);
1890 SyncSend(buffer); 1866 SyncSend(buffer);
1867 FreeUDPBuffer(buffer);
1891 } 1868 }
1892 1869
1893 protected bool IsClientAuthorized(UseCircuitCodePacket useCircuitCode, out AuthenticateResponse sessionInfo) 1870 protected bool IsClientAuthorized(UseCircuitCodePacket useCircuitCode, out AuthenticateResponse sessionInfo)
@@ -1982,21 +1959,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1982 Scene.ThreadAlive(1); 1959 Scene.ThreadAlive(1);
1983 try 1960 try
1984 { 1961 {
1985 packetInbox.TryTake(out incomingPacket, 250); 1962 packetInbox.TryTake(out incomingPacket, 4500);
1986 1963
1987 if (incomingPacket != null && IsRunningInbound) 1964 if (incomingPacket != null && IsRunningInbound)
1988 { 1965 {
1989 ProcessInPacket(incomingPacket); 1966 ProcessInPacket(incomingPacket);
1990
1991 if (UsePools)
1992 {
1993 incomingPacket.Client = null;
1994 m_incomingPacketPool.ReturnObject(incomingPacket);
1995 }
1996 incomingPacket = null; 1967 incomingPacket = null;
1997 } 1968 }
1998 } 1969 }
1999 catch(Exception ex) 1970 catch (ThreadAbortException)
1971 {
1972 Thread.ResetAbort();
1973 }
1974 catch (Exception ex)
2000 { 1975 {
2001 m_log.Error("[LLUDPSERVER]: Error in the incoming packet handler loop: " + ex.Message, ex); 1976 m_log.Error("[LLUDPSERVER]: Error in the incoming packet handler loop: " + ex.Message, ex);
2002 } 1977 }
@@ -2025,7 +2000,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2025 { 2000 {
2026 Scene.ThreadAlive(2); 2001 Scene.ThreadAlive(2);
2027 2002
2028
2029 try 2003 try
2030 { 2004 {
2031 m_packetSent = false; 2005 m_packetSent = false;
@@ -2080,7 +2054,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2080 } 2054 }
2081 else if (!m_packetSent) 2055 else if (!m_packetSent)
2082// Thread.Sleep((int)TickCountResolution); outch this is bad on linux 2056// Thread.Sleep((int)TickCountResolution); outch this is bad on linux
2083 Thread.Sleep(15); // match the 16ms of windows7, dont ask 16 or win may decide to do 32ms. 2057 Thread.Sleep(15); // match the 16ms of windows, dont ask 16 or win may decide to do 32ms.
2084 2058
2085 Watchdog.UpdateThread(); 2059 Watchdog.UpdateThread();
2086 } 2060 }
@@ -2104,14 +2078,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2104 2078
2105 if (udpClient.IsConnected) 2079 if (udpClient.IsConnected)
2106 { 2080 {
2107 if (m_resendUnacked) 2081 if (client.IsActive && m_resendUnacked)
2108 HandleUnacked(llClient); 2082 HandleUnacked(llClient);
2109 2083
2110 if (m_sendAcks) 2084 if (client.IsActive)
2111 SendAcks(udpClient); 2085 {
2086 if (m_sendAcks)
2087 SendAcks(udpClient);
2112 2088
2113 if (m_sendPing) 2089 if (m_sendPing)
2114 SendPing(udpClient); 2090 SendPing(udpClient);
2091 }
2115 2092
2116 // Dequeue any outgoing packets that are within the throttle limits 2093 // Dequeue any outgoing packets that are within the throttle limits
2117 if (udpClient.DequeueOutgoing()) 2094 if (udpClient.DequeueOutgoing())
@@ -2124,7 +2101,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2124 m_log.Error( 2101 m_log.Error(
2125 string.Format("[LLUDPSERVER]: OutgoingPacketHandler iteration for {0} threw ", client.Name), ex); 2102 string.Format("[LLUDPSERVER]: OutgoingPacketHandler iteration for {0} threw ", client.Name), ex);
2126 } 2103 }
2127 client = null;
2128 } 2104 }
2129 2105
2130 #region Emergency Monitoring 2106 #region Emergency Monitoring
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
777 m_udpServer.StopOutbound(); 777 m_udpServer.StopOutbound();
778 } 778 }
779 779
780 private void HandlePoolCommand(string module, string[] args)
781 {
782 if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_udpServer.Scene)
783 return;
784
785 if (args.Length != 4)
786 {
787 MainConsole.Instance.Output("Usage: debug lludp pool <on|off>");
788 return;
789 }
790
791 string enabled = args[3];
792
793 if (enabled == "on")
794 {
795 if (m_udpServer.EnablePools())
796 {
797 m_udpServer.EnablePoolStats();
798 MainConsole.Instance.OutputFormat("Packet pools enabled on {0}", m_udpServer.Scene.Name);
799 }
800 }
801 else if (enabled == "off")
802 {
803 if (m_udpServer.DisablePools())
804 {
805 m_udpServer.DisablePoolStats();
806 MainConsole.Instance.OutputFormat("Packet pools disabled on {0}", m_udpServer.Scene.Name);
807 }
808 }
809 else
810 {
811 MainConsole.Instance.Output("Usage: debug lludp pool <on|off>");
812 }
813 }
814
815 private void HandleAgentUpdateCommand(string module, string[] args) 780 private void HandleAgentUpdateCommand(string module, string[] args)
816 { 781 {
817 if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_udpServer.Scene) 782 if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_udpServer.Scene)
@@ -834,8 +799,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
834 MainConsole.Instance.OutputFormat( 799 MainConsole.Instance.OutputFormat(
835 "OUT LLUDP packet processing for {0} is {1}", m_udpServer.Scene.Name, m_udpServer.IsRunningOutbound ? "enabled" : "disabled"); 800 "OUT LLUDP packet processing for {0} is {1}", m_udpServer.Scene.Name, m_udpServer.IsRunningOutbound ? "enabled" : "disabled");
836 801
837 MainConsole.Instance.OutputFormat("LLUDP pools in {0} are {1}", m_udpServer.Scene.Name, m_udpServer.UsePools ? "on" : "off");
838
839 MainConsole.Instance.OutputFormat( 802 MainConsole.Instance.OutputFormat(
840 "Packet debug level for new clients is {0}", m_udpServer.DefaultClientPacketDebugLevel); 803 "Packet debug level for new clients is {0}", m_udpServer.DefaultClientPacketDebugLevel);
841 } 804 }
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPZeroEncoder.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPZeroEncoder.cs
new file mode 100644
index 0000000..8ed2cf1
--- /dev/null
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPZeroEncoder.cs
@@ -0,0 +1,279 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using OpenSim.Framework;
30using Nini.Config;
31using OpenMetaverse;
32
33namespace OpenSim.Region.ClientStack.LindenUDP
34{
35 public sealed class LLUDPZeroEncoder
36 {
37 private byte[] m_tmp = new byte[16];
38 private byte[] m_dest;
39 private int zerocount;
40 private int pos;
41
42 public LLUDPZeroEncoder()
43 {
44 }
45
46 public LLUDPZeroEncoder(byte[] data)
47 {
48 m_dest = data;
49 zerocount = 0;
50 }
51
52 public byte[] Data
53 {
54 get
55 {
56 return m_dest;
57 }
58 set
59 {
60 m_dest = value;
61 }
62 }
63
64 public int ZeroCount
65 {
66 get
67 {
68 return zerocount;
69 }
70 set
71 {
72 zerocount = value;
73 }
74 }
75
76 public int Position
77 {
78 get
79 {
80 return pos;
81 }
82 set
83 {
84 pos = value;
85 }
86 }
87
88 public unsafe void AddZeros(int len)
89 {
90 zerocount += len;
91 while (zerocount > 255)
92 {
93 m_dest[pos++] = 0x00;
94 m_dest[pos++] = 0xff;
95 zerocount -= 256;
96 }
97 }
98
99 public unsafe int Finish()
100 {
101 if(zerocount > 0)
102 {
103 m_dest[pos++] = 0x00;
104 m_dest[pos++] = (byte)zerocount;
105 }
106 return pos;
107 }
108
109 public unsafe void AddBytes(byte[] src, int srclen)
110 {
111 for (int i = 0; i < srclen; ++i)
112 {
113 if (src[i] == 0x00)
114 {
115 zerocount++;
116 if (zerocount == 0)
117 {
118 m_dest[pos++] = 0x00;
119 m_dest[pos++] = 0xff;
120 zerocount++;
121 }
122 }
123 else
124 {
125 if (zerocount != 0)
126 {
127 m_dest[pos++] = 0x00;
128 m_dest[pos++] = (byte)zerocount;
129 zerocount = 0;
130 }
131
132 m_dest[pos++] = src[i];
133 }
134 }
135 }
136
137 public unsafe void AddByte(byte v)
138 {
139 if (v == 0x00)
140 {
141 zerocount++;
142 if (zerocount == 0)
143 {
144 m_dest[pos++] = 0x00;
145 m_dest[pos++] = 0xff;
146 zerocount++;
147 }
148 }
149 else
150 {
151 if (zerocount != 0)
152 {
153 m_dest[pos++] = 0x00;
154 m_dest[pos++] = (byte)zerocount;
155 zerocount = 0;
156 }
157
158 m_dest[pos++] = v;
159 }
160 }
161
162 public void AddInt16(short v)
163 {
164 if (v == 0)
165 AddZeros(2);
166 else
167 {
168 Utils.Int16ToBytes(v, m_tmp, 0);
169 AddBytes(m_tmp, 2);
170 }
171 }
172
173 public void AddUInt16(ushort v)
174 {
175 if (v == 0)
176 AddZeros(2);
177 else
178 {
179 Utils.UInt16ToBytes(v, m_tmp, 0);
180 AddBytes(m_tmp, 2);
181 }
182 }
183
184 public void AddInt(int v)
185 {
186 if (v == 0)
187 AddZeros(4);
188 else
189 {
190 Utils.IntToBytesSafepos(v, m_tmp, 0);
191 AddBytes(m_tmp, 4);
192 }
193 }
194
195 public unsafe void AddUInt(uint v)
196 {
197 if (v == 0)
198 AddZeros(4);
199 else
200 {
201 Utils.UIntToBytesSafepos(v, m_tmp, 0);
202 AddBytes(m_tmp, 4);
203 }
204 }
205
206 public void AddFloatToUInt16(float v, float range)
207 {
208 Utils.FloatToUInt16Bytes(v, range, m_tmp, 0);
209 AddBytes(m_tmp, 2);
210 }
211
212 public void AddFloat(float v)
213 {
214 if (v == 0f)
215 AddZeros(4);
216 else
217 {
218 Utils.FloatToBytesSafepos(v, m_tmp, 0);
219 AddBytes(m_tmp, 4);
220 }
221 }
222
223 public void AddInt64(long v)
224 {
225 if (v == 0)
226 AddZeros(8);
227 else
228 {
229 Utils.Int64ToBytesSafepos(v, m_tmp, 0);
230 AddBytes(m_tmp, 8);
231 }
232 }
233
234 public void AddUInt64(ulong v)
235 {
236 if (v == 0)
237 AddZeros(8);
238 else
239 {
240 Utils.UInt64ToBytesSafepos(v, m_tmp, 0);
241 AddBytes(m_tmp, 8);
242 }
243 }
244
245 public void AddVector3(Vector3 v)
246 {
247 if (v == Vector3.Zero)
248 AddZeros(12);
249 else
250 {
251 v.ToBytes(m_tmp, 0);
252 AddBytes(m_tmp, 12);
253 }
254 }
255
256 public void AddVector4(Vector4 v)
257 {
258 if (v == Vector4.Zero)
259 AddZeros(16);
260 else
261 {
262 v.ToBytes(m_tmp, 0);
263 AddBytes(m_tmp, 16);
264 }
265 }
266
267 public void AddNormQuat(Quaternion v)
268 {
269 v.ToBytes(m_tmp, 0);
270 AddBytes(m_tmp, 12);
271 }
272
273 public void AddUUID(UUID v)
274 {
275 v.ToBytes(m_tmp, 0);
276 AddBytes(m_tmp, 16);
277 }
278 }
279}
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs
index f362b06..49aca3c 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs
@@ -26,6 +26,7 @@
26 */ 26 */
27 27
28using System; 28using System;
29using System.Collections.Concurrent;
29using System.Net; 30using System.Net;
30using System.Net.Sockets; 31using System.Net.Sockets;
31using System.Threading; 32using System.Threading;
@@ -57,15 +58,9 @@ namespace OpenMetaverse
57 /// <summary>UDP socket, used in either client or server mode</summary> 58 /// <summary>UDP socket, used in either client or server mode</summary>
58 private Socket m_udpSocket; 59 private Socket m_udpSocket;
59 60
60 /// <summary> 61 public static Object m_udpBuffersPoolLock = new Object();
61 /// Are we to use object pool(s) to reduce memory churn when receiving data? 62 public static UDPPacketBuffer[] m_udpBuffersPool = new UDPPacketBuffer[1000];
62 /// </summary> 63 public static int m_udpBuffersPoolPtr = -1;
63 public bool UsePools { get; protected set; }
64
65 /// <summary>
66 /// Pool to use for handling data. May be null if UsePools = false;
67 /// </summary>
68 protected OpenSim.Framework.Pool<UDPPacketBuffer> Pool { get; private set; }
69 64
70 /// <summary>Returns true if the server is currently listening for inbound packets, otherwise false</summary> 65 /// <summary>Returns true if the server is currently listening for inbound packets, otherwise false</summary>
71 public bool IsRunningInbound { get; private set; } 66 public bool IsRunningInbound { get; private set; }
@@ -186,6 +181,37 @@ namespace OpenMetaverse
186 if(m_udpSocket !=null) 181 if(m_udpSocket !=null)
187 try { m_udpSocket.Close(); } catch { } 182 try { m_udpSocket.Close(); } catch { }
188 } 183 }
184
185 public UDPPacketBuffer GetNewUDPBuffer(IPEndPoint remoteEndpoint)
186 {
187 lock (m_udpBuffersPoolLock)
188 {
189 if (m_udpBuffersPoolPtr >= 0)
190 {
191 UDPPacketBuffer buf = m_udpBuffersPool[m_udpBuffersPoolPtr];
192 m_udpBuffersPool[m_udpBuffersPoolPtr] = null;
193 m_udpBuffersPoolPtr--;
194 buf.RemoteEndPoint = remoteEndpoint;
195 return buf;
196 }
197 }
198 return new UDPPacketBuffer(remoteEndpoint);
199 }
200
201 public void FreeUDPBuffer(UDPPacketBuffer buf)
202 {
203 lock (m_udpBuffersPoolLock)
204 {
205 if (m_udpBuffersPoolPtr < 999)
206 {
207 buf.RemoteEndPoint = null;
208 buf.DataLength = 0;
209 m_udpBuffersPoolPtr++;
210 m_udpBuffersPool[m_udpBuffersPoolPtr] = buf;
211 }
212 }
213 }
214
189 /// <summary> 215 /// <summary>
190 /// Start inbound UDP packet handling. 216 /// Start inbound UDP packet handling.
191 /// </summary> 217 /// </summary>
@@ -202,6 +228,7 @@ namespace OpenMetaverse
202 /// manner (not throwing an exception when the remote side resets the 228 /// manner (not throwing an exception when the remote side resets the
203 /// connection). This call is ignored on Mono where the flag is not 229 /// connection). This call is ignored on Mono where the flag is not
204 /// necessary</remarks> 230 /// necessary</remarks>
231
205 public virtual void StartInbound(int recvBufferSize) 232 public virtual void StartInbound(int recvBufferSize)
206 { 233 {
207 if (!IsRunningInbound) 234 if (!IsRunningInbound)
@@ -306,102 +333,56 @@ namespace OpenMetaverse
306 IsRunningOutbound = false; 333 IsRunningOutbound = false;
307 } 334 }
308 335
309 public virtual bool EnablePools() 336 private void AsyncBeginReceive()
310 { 337 {
311 if (!UsePools) 338 if (!IsRunningInbound)
312 { 339 return;
313 Pool = new Pool<UDPPacketBuffer>(() => new UDPPacketBuffer(), 500);
314
315 UsePools = true;
316
317 return true;
318 }
319
320 return false;
321 }
322 340
323 public virtual bool DisablePools() 341 UDPPacketBuffer buf = GetNewUDPBuffer(new IPEndPoint(IPAddress.Any, 0)); // we need a fresh one here, for now at least
324 { 342 try
325 if (UsePools)
326 { 343 {
327 UsePools = false; 344 // kick off an async read
328 345 m_udpSocket.BeginReceiveFrom(
329 // We won't null out the pool to avoid a race condition with code that may be in the middle of using it. 346 buf.Data,
330 347 0,
331 return true; 348 buf.Data.Length,
349 SocketFlags.None,
350 ref buf.RemoteEndPoint,
351 AsyncEndReceive,
352 buf);
332 } 353 }
333 354 catch (SocketException e)
334 return false;
335 }
336
337 private void AsyncBeginReceive()
338 {
339 UDPPacketBuffer buf;
340
341 // FIXME: Disabled for now as this causes issues with reused packet objects interfering with each other
342 // on Windows with m_asyncPacketHandling = true, though this has not been seen on Linux.
343 // Possibly some unexpected issue with fetching UDP data concurrently with multiple threads. Requires more investigation.
344// if (UsePools)
345// buf = Pool.GetObject();
346// else
347 buf = new UDPPacketBuffer();
348
349 if (IsRunningInbound)
350 { 355 {
351 try 356 if (e.SocketErrorCode == SocketError.ConnectionReset)
352 {
353 // kick off an async read
354 m_udpSocket.BeginReceiveFrom(
355 //wrappedBuffer.Instance.Data,
356 buf.Data,
357 0,
358 UDPPacketBuffer.BUFFER_SIZE,
359 SocketFlags.None,
360 ref buf.RemoteEndPoint,
361 AsyncEndReceive,
362 //wrappedBuffer);
363 buf);
364 }
365 catch (SocketException e)
366 { 357 {
367 if (e.SocketErrorCode == SocketError.ConnectionReset) 358 m_log.Warn("[UDPBASE]: SIO_UDP_CONNRESET was ignored, attempting to salvage the UDP listener on port " + m_udpPort);
359 bool salvaged = false;
360 while (!salvaged)
368 { 361 {
369 m_log.Warn("[UDPBASE]: SIO_UDP_CONNRESET was ignored, attempting to salvage the UDP listener on port " + m_udpPort); 362 try
370 bool salvaged = false;
371 while (!salvaged)
372 { 363 {
373 try 364 m_udpSocket.BeginReceiveFrom(
374 { 365 buf.Data,
375 m_udpSocket.BeginReceiveFrom( 366 0,
376 //wrappedBuffer.Instance.Data, 367 buf.Data.Length,
377 buf.Data, 368 SocketFlags.None,
378 0, 369 ref buf.RemoteEndPoint,
379 UDPPacketBuffer.BUFFER_SIZE, 370 AsyncEndReceive,
380 SocketFlags.None, 371 buf);
381 ref buf.RemoteEndPoint, 372 salvaged = true;
382 AsyncEndReceive,
383 //wrappedBuffer);
384 buf);
385 salvaged = true;
386 }
387 catch (SocketException) { }
388 catch (ObjectDisposedException) { return; }
389 } 373 }
390 374 catch (SocketException) { }
391 m_log.Warn("[UDPBASE]: Salvaged the UDP listener on port " + m_udpPort); 375 catch (ObjectDisposedException) { return; }
392 } 376 }
393 } 377
394 catch (ObjectDisposedException e) 378 m_log.Warn("[UDPBASE]: Salvaged the UDP listener on port " + m_udpPort);
395 {
396 m_log.Error(
397 string.Format("[UDPBASE]: Error processing UDP begin receive {0}. Exception ", UdpReceives), e);
398 }
399 catch (Exception e)
400 {
401 m_log.Error(
402 string.Format("[UDPBASE]: Error processing UDP begin receive {0}. Exception ", UdpReceives), e);
403 } 379 }
404 } 380 }
381 catch (Exception e)
382 {
383 m_log.Error(
384 string.Format("[UDPBASE]: Error processing UDP begin receive {0}. Exception ", UdpReceives), e);
385 }
405 } 386 }
406 387
407 private void AsyncEndReceive(IAsyncResult iar) 388 private void AsyncEndReceive(IAsyncResult iar)
@@ -453,11 +434,6 @@ namespace OpenMetaverse
453 UdpReceives, se.ErrorCode), 434 UdpReceives, se.ErrorCode),
454 se); 435 se);
455 } 436 }
456 catch (ObjectDisposedException e)
457 {
458 m_log.Error(
459 string.Format("[UDPBASE]: Error processing UDP end receive {0}. Exception ", UdpReceives), e);
460 }
461 catch (Exception e) 437 catch (Exception e)
462 { 438 {
463 m_log.Error( 439 m_log.Error(
@@ -465,14 +441,12 @@ namespace OpenMetaverse
465 } 441 }
466 finally 442 finally
467 { 443 {
468// if (UsePools)
469// Pool.ReturnObject(buffer);
470
471 AsyncBeginReceive(); 444 AsyncBeginReceive();
472 } 445 }
473 } 446 }
474 } 447 }
475 448
449/* not in use
476 public void AsyncBeginSend(UDPPacketBuffer buf) 450 public void AsyncBeginSend(UDPPacketBuffer buf)
477 { 451 {
478// if (IsRunningOutbound) 452// if (IsRunningOutbound)
@@ -511,9 +485,11 @@ namespace OpenMetaverse
511 catch (SocketException) { } 485 catch (SocketException) { }
512 catch (ObjectDisposedException) { } 486 catch (ObjectDisposedException) { }
513 } 487 }
514 488*/
515 public void SyncSend(UDPPacketBuffer buf) 489 public void SyncSend(UDPPacketBuffer buf)
516 { 490 {
491 if(buf.RemoteEndPoint == null)
492 return; // already expired
517 try 493 try
518 { 494 {
519 m_udpSocket.SendTo( 495 m_udpSocket.SendTo(
@@ -527,7 +503,7 @@ namespace OpenMetaverse
527 } 503 }
528 catch (SocketException e) 504 catch (SocketException e)
529 { 505 {
530 m_log.Warn("[UDPBASE]: sync send SocketException {0} " + e.Message); 506 m_log.WarnFormat("[UDPBASE]: sync send SocketException {0} {1}", buf.RemoteEndPoint, e.Message);
531 } 507 }
532 catch (ObjectDisposedException) { } 508 catch (ObjectDisposedException) { }
533 } 509 }
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
66 /// </summary> 66 /// </summary>
67 public Int64 MinimumAdaptiveThrottleRate; 67 public Int64 MinimumAdaptiveThrottleRate;
68 68
69 /// <summary>Amount of the texture throttle to steal for the task throttle</summary>
70 public double CannibalizeTextureRate;
71
72 public int ClientMaxRate; 69 public int ClientMaxRate;
73 public float BrustTime; 70 public float BrustTime;
74 71
@@ -104,12 +101,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
104// AdaptiveThrottlesEnabled = throttleConfig.GetBoolean("enable_adaptive_throttles", false); 101// AdaptiveThrottlesEnabled = throttleConfig.GetBoolean("enable_adaptive_throttles", false);
105 AdaptiveThrottlesEnabled = false; 102 AdaptiveThrottlesEnabled = false;
106 MinimumAdaptiveThrottleRate = throttleConfig.GetInt("adaptive_throttle_min_bps", 32000); 103 MinimumAdaptiveThrottleRate = throttleConfig.GetInt("adaptive_throttle_min_bps", 32000);
107
108 // http textures do use udp bandwidth setting
109// CannibalizeTextureRate = (double)throttleConfig.GetFloat("CannibalizeTextureRate", 0.0f);
110// CannibalizeTextureRate = Util.Clamp<double>(CannibalizeTextureRate,0.0, 0.9);
111 CannibalizeTextureRate = 0f;
112
113 } 104 }
114 catch (Exception) { } 105 catch (Exception) { }
115 } 106 }
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/UnackedPacketCollection.cs b/OpenSim/Region/ClientStack/Linden/UDP/UnackedPacketCollection.cs
index 76f4c6f..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
189 // Process all the pending adds 189 // Process all the pending adds
190 OutgoingPacket pendingAdd; 190 OutgoingPacket pendingAdd;
191 while (m_pendingAdds.TryDequeue(out pendingAdd)) 191 while (m_pendingAdds.TryDequeue(out pendingAdd))
192 {
192 if (pendingAdd != null) 193 if (pendingAdd != null)
193 m_packets[pendingAdd.SequenceNumber] = pendingAdd; 194 m_packets[pendingAdd.SequenceNumber] = pendingAdd;
195 }
194 196
195 // Process all the pending removes, including updating statistics and round-trip times 197 // Process all the pending removes, including updating statistics and round-trip times
196 PendingAck pendingAcknowledgement; 198 PendingAck pendingAcknowledgement;
@@ -204,13 +206,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP
204 { 206 {
205 m_packets.Remove(pendingAcknowledgement.SequenceNumber); 207 m_packets.Remove(pendingAcknowledgement.SequenceNumber);
206 208
209 // Update stats
210 Interlocked.Add(ref ackedPacket.Client.UnackedBytes, -ackedPacket.Buffer.DataLength);
211
212 ackedPacket.Client.FreeUDPBuffer(ackedPacket.Buffer);
213 ackedPacket.Buffer = null;
214
207 // As with other network applications, assume that an acknowledged packet is an 215 // As with other network applications, assume that an acknowledged packet is an
208 // indication that the network can handle a little more load, speed up the transmission 216 // indication that the network can handle a little more load, speed up the transmission
209 ackedPacket.Client.FlowThrottle.AcknowledgePackets(1); 217 ackedPacket.Client.FlowThrottle.AcknowledgePackets(1);
210 218
211 // Update stats
212 Interlocked.Add(ref ackedPacket.Client.UnackedBytes, -ackedPacket.Buffer.DataLength);
213
214 if (!pendingAcknowledgement.FromResend) 219 if (!pendingAcknowledgement.FromResend)
215 { 220 {
216 // Calculate the round-trip time for this packet and its ACK 221 // Calculate the round-trip time for this packet and its ACK
@@ -244,6 +249,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
244 249
245 // Update stats 250 // Update stats
246 Interlocked.Add(ref removedPacket.Client.UnackedBytes, -removedPacket.Buffer.DataLength); 251 Interlocked.Add(ref removedPacket.Client.UnackedBytes, -removedPacket.Buffer.DataLength);
252
253 removedPacket.Client.FreeUDPBuffer(removedPacket.Buffer);
254 removedPacket.Buffer = null;
247 } 255 }
248 } 256 }
249 } 257 }