aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ClientStack
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/ClientStack')
-rw-r--r--OpenSim/Region/ClientStack/ClientStackUserSettings.cs48
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs1871
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLImageManager.cs2
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs140
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs425
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/TokenBucket.cs217
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/UnackedPacketCollection.cs157
-rw-r--r--OpenSim/Region/ClientStack/ThrottleSettings.cs57
8 files changed, 1591 insertions, 1326 deletions
diff --git a/OpenSim/Region/ClientStack/ClientStackUserSettings.cs b/OpenSim/Region/ClientStack/ClientStackUserSettings.cs
deleted file mode 100644
index 231b3aa..0000000
--- a/OpenSim/Region/ClientStack/ClientStackUserSettings.cs
+++ /dev/null
@@ -1,48 +0,0 @@
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
28namespace OpenSim.Region.ClientStack
29{
30 /// <summary>
31 /// Allow users to tweak parameters for the client stack.
32 ///
33 /// At the moment this is very incomplete - other tweakable settings could be added. This is also somewhat LL client
34 /// oriented right now.
35 /// </summary>
36 public class ClientStackUserSettings
37 {
38 /// <summary>
39 /// The settings for the throttle that governs how many packets in total are sent to the client.
40 /// </summary>
41 public ThrottleSettings TotalThrottleSettings;
42
43 /// <summary>
44 /// A multiplier applied to all client throttle settings. Default value is x2 (temporarily)
45 /// </summary>
46 public float ClientThrottleMultipler = 2;
47 }
48}
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
index 05a2a63..0bb7a71 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
@@ -45,12 +45,50 @@ using OpenSim.Region.Framework.Interfaces;
45using OpenSim.Region.Framework.Scenes; 45using OpenSim.Region.Framework.Scenes;
46using OpenSim.Region.Framework.Scenes.Hypergrid; 46using OpenSim.Region.Framework.Scenes.Hypergrid;
47using OpenSim.Services.Interfaces; 47using OpenSim.Services.Interfaces;
48using Timer=System.Timers.Timer; 48using Timer = System.Timers.Timer;
49using AssetLandmark = OpenSim.Framework.AssetLandmark; 49using AssetLandmark = OpenSim.Framework.AssetLandmark;
50using Nini.Config; 50using Nini.Config;
51 51
52namespace OpenSim.Region.ClientStack.LindenUDP 52namespace OpenSim.Region.ClientStack.LindenUDP
53{ 53{
54 #region Enums
55
56 /// <summary>
57 /// Specifies the fields that have been changed when sending a prim or
58 /// avatar update
59 /// </summary>
60 [Flags]
61 public enum PrimUpdateFlags : uint
62 {
63 None = 0,
64 AttachmentPoint = 1 << 0,
65 Material = 1 << 1,
66 ClickAction = 1 << 2,
67 Scale = 1 << 3,
68 ParentID = 1 << 4,
69 PrimFlags = 1 << 5,
70 PrimData = 1 << 6,
71 MediaURL = 1 << 7,
72 ScratchPad = 1 << 8,
73 Textures = 1 << 9,
74 TextureAnim = 1 << 10,
75 NameValue = 1 << 11,
76 Position = 1 << 12,
77 Rotation = 1 << 13,
78 Velocity = 1 << 14,
79 Acceleration = 1 << 15,
80 AngularVelocity = 1 << 16,
81 CollisionPlane = 1 << 17,
82 Text = 1 << 18,
83 Particles = 1 << 19,
84 ExtraData = 1 << 20,
85 Sound = 1 << 21,
86 Joint = 1 << 22,
87 FullUpdate = UInt32.MaxValue
88 }
89
90 #endregion Enums
91
54 public delegate bool PacketMethod(IClientAPI simClient, Packet packet); 92 public delegate bool PacketMethod(IClientAPI simClient, Packet packet);
55 93
56 /// <summary> 94 /// <summary>
@@ -257,6 +295,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
257 public event MuteListRequest OnMuteListRequest; 295 public event MuteListRequest OnMuteListRequest;
258 public event AvatarInterestUpdate OnAvatarInterestUpdate; 296 public event AvatarInterestUpdate OnAvatarInterestUpdate;
259 public event PlacesQuery OnPlacesQuery; 297 public event PlacesQuery OnPlacesQuery;
298 public event AgentFOV OnAgentFOV;
260 299
261 #endregion Events 300 #endregion Events
262 301
@@ -282,12 +321,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
282 private readonly IGroupsModule m_GroupsModule; 321 private readonly IGroupsModule m_GroupsModule;
283 322
284 private int m_cachedTextureSerial; 323 private int m_cachedTextureSerial;
285 private Timer m_avatarTerseUpdateTimer; 324 private PriorityQueue<double, ImprovedTerseObjectUpdatePacket.ObjectDataBlock> m_avatarTerseUpdates;
286 private List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> m_avatarTerseUpdates = new List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>(); 325 private PriorityQueue<double, ImprovedTerseObjectUpdatePacket.ObjectDataBlock> m_primTerseUpdates;
287 private Timer m_primTerseUpdateTimer; 326 private PriorityQueue<double, ObjectUpdatePacket.ObjectDataBlock> m_primFullUpdates;
288 private List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> m_primTerseUpdates = new List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>();
289 private Timer m_primFullUpdateTimer;
290 private List<ObjectUpdatePacket.ObjectDataBlock> m_primFullUpdates = new List<ObjectUpdatePacket.ObjectDataBlock>();
291 private int m_moneyBalance; 327 private int m_moneyBalance;
292 private int m_animationSequenceNumber = 1; 328 private int m_animationSequenceNumber = 1;
293 private bool m_SendLogoutPacketWhenClosing = true; 329 private bool m_SendLogoutPacketWhenClosing = true;
@@ -296,26 +332,26 @@ namespace OpenSim.Region.ClientStack.LindenUDP
296 332
297 protected Dictionary<PacketType, PacketMethod> m_packetHandlers = new Dictionary<PacketType, PacketMethod>(); 333 protected Dictionary<PacketType, PacketMethod> m_packetHandlers = new Dictionary<PacketType, PacketMethod>();
298 protected Dictionary<string, GenericMessage> m_genericPacketHandlers = new Dictionary<string, GenericMessage>(); //PauPaw:Local Generic Message handlers 334 protected Dictionary<string, GenericMessage> m_genericPacketHandlers = new Dictionary<string, GenericMessage>(); //PauPaw:Local Generic Message handlers
299 protected IScene m_scene; 335 protected Scene m_scene;
300 protected LLImageManager m_imageManager; 336 protected LLImageManager m_imageManager;
301 protected string m_firstName; 337 protected string m_firstName;
302 protected string m_lastName; 338 protected string m_lastName;
303 protected Thread m_clientThread; 339 protected Thread m_clientThread;
304 protected Vector3 m_startpos; 340 protected Vector3 m_startpos;
305 protected EndPoint m_userEndPoint; 341 protected EndPoint m_userEndPoint;
306 protected UUID m_activeGroupID = UUID.Zero; 342 protected UUID m_activeGroupID;
307 protected string m_activeGroupName = String.Empty; 343 protected string m_activeGroupName = String.Empty;
308 protected ulong m_activeGroupPowers; 344 protected ulong m_activeGroupPowers;
309 protected Dictionary<UUID,ulong> m_groupPowers = new Dictionary<UUID, ulong>(); 345 protected Dictionary<UUID, ulong> m_groupPowers = new Dictionary<UUID, ulong>();
310 protected int m_terrainCheckerCount; 346 protected int m_terrainCheckerCount;
311 347 protected uint m_agentFOVCounter;
312 // LL uses these limits, apparently. Compressed terse would be 23, but we don't have that yet 348
313 protected int m_primTerseUpdatesPerPacket = 10; 349 // These numbers are guesses at a decent tradeoff between responsiveness
314 protected int m_primFullUpdatesPerPacket = 14; 350 // of the interest list and throughput. Lower is more responsive, higher
315 protected int m_primTerseUpdateRate = 10; 351 // is better throughput
316 protected int m_primFullUpdateRate = 14; 352 protected int m_primTerseUpdatesPerPacket = 25;
317 protected int m_avatarTerseUpdateRate = 50; 353 protected int m_primFullUpdatesPerPacket = 100;
318 protected int m_avatarTerseUpdatesPerPacket = 5; 354 protected int m_avatarTerseUpdatesPerPacket = 10;
319 /// <summary>Number of texture packets to put on the queue each time the 355 /// <summary>Number of texture packets to put on the queue each time the
320 /// OnQueueEmpty event is triggered for the texture category</summary> 356 /// OnQueueEmpty event is triggered for the texture category</summary>
321 protected int m_textureSendLimit = 20; 357 protected int m_textureSendLimit = 20;
@@ -369,21 +405,26 @@ namespace OpenSim.Region.ClientStack.LindenUDP
369 /// <summary> 405 /// <summary>
370 /// Constructor 406 /// Constructor
371 /// </summary> 407 /// </summary>
372 public LLClientView(EndPoint remoteEP, IScene scene, LLUDPServer udpServer, LLUDPClient udpClient, AuthenticateResponse sessionInfo, 408 public LLClientView(EndPoint remoteEP, Scene scene, LLUDPServer udpServer, LLUDPClient udpClient, AuthenticateResponse sessionInfo,
373 UUID agentId, UUID sessionId, uint circuitCode) 409 UUID agentId, UUID sessionId, uint circuitCode)
374 { 410 {
375 RegisterInterface<IClientIM>(this); 411 RegisterInterface<IClientIM>(this);
376 RegisterInterface<IClientChat>(this); 412 RegisterInterface<IClientChat>(this);
377 RegisterInterface<IClientIPEndpoint>(this); 413 RegisterInterface<IClientIPEndpoint>(this);
378 414
379 InitDefaultAnimations(); 415 InitDefaultAnimations();
380 416
381 m_scene = scene; 417 m_scene = scene;
418
419 m_avatarTerseUpdates = new PriorityQueue<double, ImprovedTerseObjectUpdatePacket.ObjectDataBlock>();
420 m_primTerseUpdates = new PriorityQueue<double, ImprovedTerseObjectUpdatePacket.ObjectDataBlock>();
421 m_primFullUpdates = new PriorityQueue<double, ObjectUpdatePacket.ObjectDataBlock>(m_scene.Entities.Count);
422
382 m_assetService = m_scene.RequestModuleInterface<IAssetService>(); 423 m_assetService = m_scene.RequestModuleInterface<IAssetService>();
383 m_hyperAssets = m_scene.RequestModuleInterface<IHyperAssetService>(); 424 m_hyperAssets = m_scene.RequestModuleInterface<IHyperAssetService>();
384 m_GroupsModule = scene.RequestModuleInterface<IGroupsModule>(); 425 m_GroupsModule = scene.RequestModuleInterface<IGroupsModule>();
385 m_imageManager = new LLImageManager(this, m_assetService, Scene.RequestModuleInterface<IJ2KDecoder>()); 426 m_imageManager = new LLImageManager(this, m_assetService, Scene.RequestModuleInterface<IJ2KDecoder>());
386 m_channelVersion = Utils.StringToBytes(scene.GetSimulatorVersion()); 427 m_channelVersion = Util.StringToBytes256(scene.GetSimulatorVersion());
387 m_agentId = agentId; 428 m_agentId = agentId;
388 m_sessionId = sessionId; 429 m_sessionId = sessionId;
389 m_secureSessionId = sessionInfo.LoginInfo.SecureSession; 430 m_secureSessionId = sessionInfo.LoginInfo.SecureSession;
@@ -438,25 +479,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
438 // Remove ourselves from the scene 479 // Remove ourselves from the scene
439 m_scene.RemoveClient(AgentId); 480 m_scene.RemoveClient(AgentId);
440 481
441 // Shut down timers. Thread Context of this method is murky. Lock all timers
442 if (m_avatarTerseUpdateTimer.Enabled)
443 lock (m_avatarTerseUpdateTimer)
444 m_avatarTerseUpdateTimer.Stop();
445 if (m_primTerseUpdateTimer.Enabled)
446 lock (m_primTerseUpdateTimer)
447 m_primTerseUpdateTimer.Stop();
448 if (m_primFullUpdateTimer.Enabled)
449 lock (m_primFullUpdateTimer)
450 m_primFullUpdateTimer.Stop();
451
452 // We can't reach into other scenes and close the connection 482 // We can't reach into other scenes and close the connection
453 // We need to do this over grid communications 483 // We need to do this over grid communications
454 //m_scene.CloseAllAgents(CircuitCode); 484 //m_scene.CloseAllAgents(CircuitCode);
455 485
456 m_avatarTerseUpdateTimer.Dispose();
457 m_primTerseUpdateTimer.Dispose();
458 m_primFullUpdateTimer.Dispose();
459
460 // Disable UDP handling for this client 486 // Disable UDP handling for this client
461 m_udpClient.Shutdown(); 487 m_udpClient.Shutdown();
462 488
@@ -474,7 +500,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
474 kupack.UserInfo.SessionID = SessionId; 500 kupack.UserInfo.SessionID = SessionId;
475 kupack.TargetBlock.TargetIP = 0; 501 kupack.TargetBlock.TargetIP = 0;
476 kupack.TargetBlock.TargetPort = 0; 502 kupack.TargetBlock.TargetPort = 0;
477 kupack.UserInfo.Reason = Utils.StringToBytes(message); 503 kupack.UserInfo.Reason = Util.StringToBytes256(message);
478 OutPacket(kupack, ThrottleOutPacketType.Task); 504 OutPacket(kupack, ThrottleOutPacketType.Task);
479 // You must sleep here or users get no message! 505 // You must sleep here or users get no message!
480 Thread.Sleep(500); 506 Thread.Sleep(500);
@@ -483,18 +509,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
483 509
484 public void Stop() 510 public void Stop()
485 { 511 {
486 // Shut down timers. Thread Context is Murky, lock all timers!
487 if (m_avatarTerseUpdateTimer.Enabled)
488 lock (m_avatarTerseUpdateTimer)
489 m_avatarTerseUpdateTimer.Stop();
490
491 if (m_primTerseUpdateTimer.Enabled)
492 lock (m_primTerseUpdateTimer)
493 m_primTerseUpdateTimer.Stop();
494 512
495 if (m_primFullUpdateTimer.Enabled)
496 lock (m_primFullUpdateTimer)
497 m_primFullUpdateTimer.Stop();
498 } 513 }
499 514
500 #endregion Client Methods 515 #endregion Client Methods
@@ -590,18 +605,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
590 605
591 public virtual void Start() 606 public virtual void Start()
592 { 607 {
593 m_avatarTerseUpdateTimer = new Timer(m_avatarTerseUpdateRate);
594 m_avatarTerseUpdateTimer.Elapsed += new ElapsedEventHandler(ProcessAvatarTerseUpdates);
595 m_avatarTerseUpdateTimer.AutoReset = false;
596
597 m_primTerseUpdateTimer = new Timer(m_primTerseUpdateRate);
598 m_primTerseUpdateTimer.Elapsed += new ElapsedEventHandler(ProcessPrimTerseUpdates);
599 m_primTerseUpdateTimer.AutoReset = false;
600
601 m_primFullUpdateTimer = new Timer(m_primFullUpdateRate);
602 m_primFullUpdateTimer.Elapsed += new ElapsedEventHandler(ProcessPrimFullUpdates);
603 m_primFullUpdateTimer.AutoReset = false;
604
605 m_scene.AddNewClient(this); 608 m_scene.AddNewClient(this);
606 609
607 RefreshGroupMembership(); 610 RefreshGroupMembership();
@@ -618,7 +621,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
618 } 621 }
619 622
620 // Sound 623 // Sound
621 public void SoundTrigger(UUID soundId, UUID owerid, UUID Objectid,UUID ParentId,float Gain, Vector3 Position,UInt64 Handle) 624 public void SoundTrigger(UUID soundId, UUID owerid, UUID Objectid, UUID ParentId, float Gain, Vector3 Position, UInt64 Handle)
622 { 625 {
623 } 626 }
624 627
@@ -642,7 +645,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
642 handshake.RegionInfo.WaterHeight = args.waterHeight; 645 handshake.RegionInfo.WaterHeight = args.waterHeight;
643 646
644 handshake.RegionInfo.RegionFlags = args.regionFlags; 647 handshake.RegionInfo.RegionFlags = args.regionFlags;
645 handshake.RegionInfo.SimName = Utils.StringToBytes(args.regionName); 648 handshake.RegionInfo.SimName = Util.StringToBytes256(args.regionName);
646 handshake.RegionInfo.SimOwner = args.SimOwner; 649 handshake.RegionInfo.SimOwner = args.SimOwner;
647 handshake.RegionInfo.TerrainBase0 = args.terrainBase0; 650 handshake.RegionInfo.TerrainBase0 = args.terrainBase0;
648 handshake.RegionInfo.TerrainBase1 = args.terrainBase1; 651 handshake.RegionInfo.TerrainBase1 = args.terrainBase1;
@@ -655,7 +658,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
655 handshake.RegionInfo.CacheID = UUID.Random(); //I guess this is for the client to remember an old setting? 658 handshake.RegionInfo.CacheID = UUID.Random(); //I guess this is for the client to remember an old setting?
656 handshake.RegionInfo2 = new RegionHandshakePacket.RegionInfo2Block(); 659 handshake.RegionInfo2 = new RegionHandshakePacket.RegionInfo2Block();
657 handshake.RegionInfo2.RegionID = regionInfo.RegionID; 660 handshake.RegionInfo2.RegionID = regionInfo.RegionID;
658 661
659 handshake.RegionInfo3 = new RegionHandshakePacket.RegionInfo3Block(); 662 handshake.RegionInfo3 = new RegionHandshakePacket.RegionInfo3Block();
660 handshake.RegionInfo3.CPUClassID = 9; 663 handshake.RegionInfo3.CPUClassID = 9;
661 handshake.RegionInfo3.CPURatio = 1; 664 handshake.RegionInfo3.CPURatio = 1;
@@ -698,11 +701,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
698 { 701 {
699 ChatFromSimulatorPacket reply = (ChatFromSimulatorPacket)PacketPool.Instance.GetPacket(PacketType.ChatFromSimulator); 702 ChatFromSimulatorPacket reply = (ChatFromSimulatorPacket)PacketPool.Instance.GetPacket(PacketType.ChatFromSimulator);
700 reply.ChatData.Audible = audible; 703 reply.ChatData.Audible = audible;
701 reply.ChatData.Message = Utils.StringToBytes(message); 704 reply.ChatData.Message = Util.StringToBytes1024(message);
702 reply.ChatData.ChatType = type; 705 reply.ChatData.ChatType = type;
703 reply.ChatData.SourceType = source; 706 reply.ChatData.SourceType = source;
704 reply.ChatData.Position = fromPos; 707 reply.ChatData.Position = fromPos;
705 reply.ChatData.FromName = Utils.StringToBytes(fromName); 708 reply.ChatData.FromName = Util.StringToBytes256(fromName);
706 reply.ChatData.OwnerID = fromAgentID; 709 reply.ChatData.OwnerID = fromAgentID;
707 reply.ChatData.SourceID = fromAgentID; 710 reply.ChatData.SourceID = fromAgentID;
708 711
@@ -723,7 +726,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
723 726
724 msg.AgentData.AgentID = new UUID(im.fromAgentID); 727 msg.AgentData.AgentID = new UUID(im.fromAgentID);
725 msg.AgentData.SessionID = UUID.Zero; 728 msg.AgentData.SessionID = UUID.Zero;
726 msg.MessageBlock.FromAgentName = Utils.StringToBytes(im.fromAgentName); 729 msg.MessageBlock.FromAgentName = Util.StringToBytes256(im.fromAgentName);
727 msg.MessageBlock.Dialog = im.dialog; 730 msg.MessageBlock.Dialog = im.dialog;
728 msg.MessageBlock.FromGroup = im.fromGroup; 731 msg.MessageBlock.FromGroup = im.fromGroup;
729 if (im.imSessionID == UUID.Zero.Guid) 732 if (im.imSessionID == UUID.Zero.Guid)
@@ -736,12 +739,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
736 msg.MessageBlock.RegionID = new UUID(im.RegionID); 739 msg.MessageBlock.RegionID = new UUID(im.RegionID);
737 msg.MessageBlock.Timestamp = im.timestamp; 740 msg.MessageBlock.Timestamp = im.timestamp;
738 msg.MessageBlock.ToAgentID = new UUID(im.toAgentID); 741 msg.MessageBlock.ToAgentID = new UUID(im.toAgentID);
739 // Cap the message length at 1099. There is a limit in ImprovedInstantMessagePacket 742 msg.MessageBlock.Message = Util.StringToBytes1024(im.message);
740 // the limit is 1100 but a 0 byte gets added to mark the end of the string
741 if (im.message != null && im.message.Length > 1099)
742 msg.MessageBlock.Message = Utils.StringToBytes(im.message.Substring(0, 1099));
743 else
744 msg.MessageBlock.Message = Utils.StringToBytes(im.message);
745 msg.MessageBlock.BinaryBucket = im.binaryBucket; 743 msg.MessageBlock.BinaryBucket = im.binaryBucket;
746 744
747 if (im.message.StartsWith("[grouptest]")) 745 if (im.message.StartsWith("[grouptest]"))
@@ -759,7 +757,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
759 eq.ChatterboxInvitation( 757 eq.ChatterboxInvitation(
760 new UUID("00000000-68f9-1111-024e-222222111123"), 758 new UUID("00000000-68f9-1111-024e-222222111123"),
761 "OpenSimulator Testing", new UUID(im.fromAgentID), im.message, new UUID(im.toAgentID), im.fromAgentName, im.dialog, 0, 759 "OpenSimulator Testing", new UUID(im.fromAgentID), im.message, new UUID(im.toAgentID), im.fromAgentName, im.dialog, 0,
762 false, 0, new Vector3(), 1, new UUID(im.imSessionID), im.fromGroup, Utils.StringToBytes("OpenSimulator Testing")); 760 false, 0, new Vector3(), 1, new UUID(im.imSessionID), im.fromGroup, Util.StringToBytes256("OpenSimulator Testing"));
763 761
764 eq.ChatterBoxSessionAgentListUpdates( 762 eq.ChatterBoxSessionAgentListUpdates(
765 new UUID("00000000-68f9-1111-024e-222222111123"), 763 new UUID("00000000-68f9-1111-024e-222222111123"),
@@ -776,13 +774,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
776 public void SendGenericMessage(string method, List<string> message) 774 public void SendGenericMessage(string method, List<string> message)
777 { 775 {
778 GenericMessagePacket gmp = new GenericMessagePacket(); 776 GenericMessagePacket gmp = new GenericMessagePacket();
779 gmp.MethodData.Method = Utils.StringToBytes(method); 777 gmp.MethodData.Method = Util.StringToBytes256(method);
780 gmp.ParamList = new GenericMessagePacket.ParamListBlock[message.Count]; 778 gmp.ParamList = new GenericMessagePacket.ParamListBlock[message.Count];
781 int i = 0; 779 int i = 0;
782 foreach (string val in message) 780 foreach (string val in message)
783 { 781 {
784 gmp.ParamList[i] = new GenericMessagePacket.ParamListBlock(); 782 gmp.ParamList[i] = new GenericMessagePacket.ParamListBlock();
785 gmp.ParamList[i++].Parameter = Utils.StringToBytes(val); 783 gmp.ParamList[i++].Parameter = Util.StringToBytes256(val);
786 } 784 }
787 OutPacket(gmp, ThrottleOutPacketType.Task); 785 OutPacket(gmp, ThrottleOutPacketType.Task);
788 } 786 }
@@ -793,7 +791,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
793 /// <param name="map">heightmap</param> 791 /// <param name="map">heightmap</param>
794 public virtual void SendLayerData(float[] map) 792 public virtual void SendLayerData(float[] map)
795 { 793 {
796 ThreadPool.QueueUserWorkItem(DoSendLayerData, map); 794 ThreadPool.UnsafeQueueUserWorkItem(DoSendLayerData, map);
797 } 795 }
798 796
799 /// <summary> 797 /// <summary>
@@ -802,32 +800,55 @@ namespace OpenSim.Region.ClientStack.LindenUDP
802 /// <param name="o"></param> 800 /// <param name="o"></param>
803 private void DoSendLayerData(object o) 801 private void DoSendLayerData(object o)
804 { 802 {
805 float[] map = (float[])o; 803 float[] map = LLHeightFieldMoronize((float[])o);
806 804
807 try 805 try
808 { 806 {
809 for (int y = 0; y < 16; y++) 807 //for (int y = 0; y < 16; y++)
810 { 808 //{
811 // For some terrains, sending more than one terrain patch at once results in a libsecondlife exception 809 // for (int x = 0; x < 16; x++)
812 // see http://opensimulator.org/mantis/view.php?id=1662 810 // {
813 //for (int x = 0; x < 16; x += 4) 811 // SendLayerData(x, y, map);
814 //{ 812 // }
815 // SendLayerPacket(map, y, x); 813 //}
816 // Thread.Sleep(150); 814
817 //} 815 // Send LayerData in a spiral pattern. Fun!
818 for (int x = 0; x < 16; x++) 816 SendLayerTopRight(map, 0, 0, 15, 15);
819 {
820 SendLayerData(x, y, LLHeightFieldMoronize(map));
821 Thread.Sleep(35);
822 }
823 }
824 } 817 }
825 catch (Exception e) 818 catch (Exception e)
826 { 819 {
827 m_log.Warn("[CLIENT]: ClientView.API.cs: SendLayerData() - Failed with exception " + e); 820 m_log.Error("[CLIENT]: SendLayerData() Failed with exception: " + e.Message, e);
828 } 821 }
829 } 822 }
830 823
824 private void SendLayerTopRight(float[] map, int x1, int y1, int x2, int y2)
825 {
826 // Row
827 for (int i = x1; i <= x2; i++)
828 SendLayerData(i, y1, map);
829
830 // Column
831 for (int j = y1 + 1; j <= y2; j++)
832 SendLayerData(x2, j, map);
833
834 if (x2 - x1 > 0)
835 SendLayerBottomLeft(map, x1, y1 + 1, x2 - 1, y2);
836 }
837
838 void SendLayerBottomLeft(float[] map, int x1, int y1, int x2, int y2)
839 {
840 // Row in reverse
841 for (int i = x2; i >= x1; i--)
842 SendLayerData(i, y2, map);
843
844 // Column in reverse
845 for (int j = y2 - 1; j >= y1; j--)
846 SendLayerData(x1, j, map);
847
848 if (x2 - x1 > 0)
849 SendLayerTopRight(map, x1 + 1, y1, x2, y2 - 1);
850 }
851
831 /// <summary> 852 /// <summary>
832 /// Sends a set of four patches (x, x+1, ..., x+3) to the client 853 /// Sends a set of four patches (x, x+1, ..., x+3) to the client
833 /// </summary> 854 /// </summary>
@@ -856,22 +877,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP
856 { 877 {
857 try 878 try
858 { 879 {
859 int[] patches = new int[1]; 880 int[] patches = new int[] { py * 16 + px };
860 int patchx, patchy; 881 float[] heightmap = (map.Length == 65536) ?
861 patchx = px; 882 map :
862 patchy = py; 883 LLHeightFieldMoronize(map);
863
864 patches[0] = patchx + 0 + patchy * 16;
865 884
866 LayerDataPacket layerpack = TerrainCompressor.CreateLandPacket(((map.Length==65536)? map : LLHeightFieldMoronize(map)), patches); 885 LayerDataPacket layerpack = TerrainCompressor.CreateLandPacket(heightmap, patches);
867 layerpack.Header.Zerocoded = true; 886 layerpack.Header.Reliable = true;
868 887
869 OutPacket(layerpack, ThrottleOutPacketType.Land); 888 OutPacket(layerpack, ThrottleOutPacketType.Land);
870
871 } 889 }
872 catch (Exception e) 890 catch (Exception e)
873 { 891 {
874 m_log.Warn("[client]: ClientView.API.cs: SendLayerData() - Failed with exception " + e.ToString()); 892 m_log.Error("[CLIENT]: SendLayerData() Failed with exception: " + e.Message, e);
875 } 893 }
876 } 894 }
877 895
@@ -900,7 +918,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
900 Array.Copy(map, i * (int)Constants.RegionSize, returnmap, i * 256, 256); 918 Array.Copy(map, i * (int)Constants.RegionSize, returnmap, i * 256, 256);
901 } 919 }
902 920
903
904 //Array.Copy(map,0,returnmap,0,(map.Length < 65536)? map.Length : 65536); 921 //Array.Copy(map,0,returnmap,0,(map.Length < 65536)? map.Length : 65536);
905 922
906 return returnmap; 923 return returnmap;
@@ -914,7 +931,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
914 /// <param name="windSpeeds">16x16 array of wind speeds</param> 931 /// <param name="windSpeeds">16x16 array of wind speeds</param>
915 public virtual void SendWindData(Vector2[] windSpeeds) 932 public virtual void SendWindData(Vector2[] windSpeeds)
916 { 933 {
917 ThreadPool.QueueUserWorkItem(new WaitCallback(DoSendWindData), (object)windSpeeds); 934 ThreadPool.UnsafeQueueUserWorkItem(new WaitCallback(DoSendWindData), (object)windSpeeds);
918 } 935 }
919 936
920 /// <summary> 937 /// <summary>
@@ -923,7 +940,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
923 /// <param name="windSpeeds">16x16 array of cloud densities</param> 940 /// <param name="windSpeeds">16x16 array of cloud densities</param>
924 public virtual void SendCloudData(float[] cloudDensity) 941 public virtual void SendCloudData(float[] cloudDensity)
925 { 942 {
926 ThreadPool.QueueUserWorkItem(new WaitCallback(DoSendCloudData), (object)cloudDensity); 943 ThreadPool.UnsafeQueueUserWorkItem(new WaitCallback(DoSendCloudData), (object)cloudDensity);
927 } 944 }
928 945
929 /// <summary> 946 /// <summary>
@@ -1012,14 +1029,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1012 agentData.child = false; 1029 agentData.child = false;
1013 agentData.firstname = m_firstName; 1030 agentData.firstname = m_firstName;
1014 agentData.lastname = m_lastName; 1031 agentData.lastname = m_lastName;
1015 1032
1016 ICapabilitiesModule capsModule = m_scene.RequestModuleInterface<ICapabilitiesModule>(); 1033 ICapabilitiesModule capsModule = m_scene.RequestModuleInterface<ICapabilitiesModule>();
1017 1034
1018 if (capsModule == null) // can happen when shutting down. 1035 if (capsModule == null) // can happen when shutting down.
1019 return agentData; 1036 return agentData;
1020 1037
1021 agentData.CapsPath = capsModule.GetCapsPath(m_agentId); 1038 agentData.CapsPath = capsModule.GetCapsPath(m_agentId);
1022 agentData.ChildrenCapSeeds = new Dictionary<ulong,string>(capsModule.GetChildrenSeeds(m_agentId)); 1039 agentData.ChildrenCapSeeds = new Dictionary<ulong, string>(capsModule.GetChildrenSeeds(m_agentId));
1023 1040
1024 return agentData; 1041 return agentData;
1025 } 1042 }
@@ -1046,7 +1063,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1046 newSimPack.RegionData.SimIP += (uint)byteIP[1] << 8; 1063 newSimPack.RegionData.SimIP += (uint)byteIP[1] << 8;
1047 newSimPack.RegionData.SimIP += (uint)byteIP[0]; 1064 newSimPack.RegionData.SimIP += (uint)byteIP[0];
1048 newSimPack.RegionData.SimPort = (ushort)externalIPEndPoint.Port; 1065 newSimPack.RegionData.SimPort = (ushort)externalIPEndPoint.Port;
1049 newSimPack.RegionData.SeedCapability = Utils.StringToBytes(capsURL); 1066 newSimPack.RegionData.SeedCapability = Util.StringToBytes256(capsURL);
1050 1067
1051 // Hack to get this out immediately and skip throttles 1068 // Hack to get this out immediately and skip throttles
1052 OutPacket(newSimPack, ThrottleOutPacketType.Unknown); 1069 OutPacket(newSimPack, ThrottleOutPacketType.Unknown);
@@ -1124,7 +1141,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1124 teleport.Info.RegionHandle = regionHandle; 1141 teleport.Info.RegionHandle = regionHandle;
1125 teleport.Info.SimAccess = simAccess; 1142 teleport.Info.SimAccess = simAccess;
1126 1143
1127 teleport.Info.SeedCapability = Utils.StringToBytes(capsURL); 1144 teleport.Info.SeedCapability = Util.StringToBytes256(capsURL);
1128 1145
1129 IPAddress oIP = newRegionEndPoint.Address; 1146 IPAddress oIP = newRegionEndPoint.Address;
1130 byte[] byteIP = oIP.GetAddressBytes(); 1147 byte[] byteIP = oIP.GetAddressBytes();
@@ -1149,7 +1166,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1149 { 1166 {
1150 TeleportFailedPacket tpFailed = (TeleportFailedPacket)PacketPool.Instance.GetPacket(PacketType.TeleportFailed); 1167 TeleportFailedPacket tpFailed = (TeleportFailedPacket)PacketPool.Instance.GetPacket(PacketType.TeleportFailed);
1151 tpFailed.Info.AgentID = AgentId; 1168 tpFailed.Info.AgentID = AgentId;
1152 tpFailed.Info.Reason = Utils.StringToBytes(reason); 1169 tpFailed.Info.Reason = Util.StringToBytes256(reason);
1153 tpFailed.AlertInfo = new TeleportFailedPacket.AlertInfoBlock[0]; 1170 tpFailed.AlertInfo = new TeleportFailedPacket.AlertInfoBlock[0];
1154 1171
1155 // Hack to get this out immediately and skip throttles 1172 // Hack to get this out immediately and skip throttles
@@ -1211,11 +1228,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1211 StartPingCheckPacket pc = (StartPingCheckPacket)PacketPool.Instance.GetPacket(PacketType.StartPingCheck); 1228 StartPingCheckPacket pc = (StartPingCheckPacket)PacketPool.Instance.GetPacket(PacketType.StartPingCheck);
1212 pc.Header.Reliable = false; 1229 pc.Header.Reliable = false;
1213 1230
1214 OutgoingPacket oldestPacket = m_udpClient.NeedAcks.GetOldest();
1215
1216 pc.PingID.PingID = seq; 1231 pc.PingID.PingID = seq;
1217 pc.PingID.OldestUnacked = (oldestPacket != null) ? oldestPacket.SequenceNumber : 0; 1232 // We *could* get OldestUnacked, but it would hurt performance and not provide any benefit
1218 1233 pc.PingID.OldestUnacked = 0;
1234
1219 OutPacket(pc, ThrottleOutPacketType.Unknown); 1235 OutPacket(pc, ThrottleOutPacketType.Unknown);
1220 } 1236 }
1221 1237
@@ -1521,7 +1537,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1521 inventoryReply.Header.Zerocoded = true; 1537 inventoryReply.Header.Zerocoded = true;
1522 OutPacket(inventoryReply, ThrottleOutPacketType.Asset); 1538 OutPacket(inventoryReply, ThrottleOutPacketType.Asset);
1523 } 1539 }
1524 1540
1525 protected void SendBulkUpdateInventoryFolder(InventoryFolderBase folderBase) 1541 protected void SendBulkUpdateInventoryFolder(InventoryFolderBase folderBase)
1526 { 1542 {
1527 // We will use the same transaction id for all the separate packets to be sent out in this update. 1543 // We will use the same transaction id for all the separate packets to be sent out in this update.
@@ -1545,7 +1561,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1545 bulkUpdate.FolderData = folderDataBlocks.ToArray(); 1561 bulkUpdate.FolderData = folderDataBlocks.ToArray();
1546 List<BulkUpdateInventoryPacket.ItemDataBlock> foo = new List<BulkUpdateInventoryPacket.ItemDataBlock>(); 1562 List<BulkUpdateInventoryPacket.ItemDataBlock> foo = new List<BulkUpdateInventoryPacket.ItemDataBlock>();
1547 bulkUpdate.ItemData = foo.ToArray(); 1563 bulkUpdate.ItemData = foo.ToArray();
1548 1564
1549 //m_log.Debug("SendBulkUpdateInventory :" + bulkUpdate); 1565 //m_log.Debug("SendBulkUpdateInventory :" + bulkUpdate);
1550 OutPacket(bulkUpdate, ThrottleOutPacketType.Asset); 1566 OutPacket(bulkUpdate, ThrottleOutPacketType.Asset);
1551 } 1567 }
@@ -1668,7 +1684,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1668 1684
1669 return itemBlock; 1685 return itemBlock;
1670 } 1686 }
1671 1687
1672 public void SendBulkUpdateInventory(InventoryNodeBase node) 1688 public void SendBulkUpdateInventory(InventoryNodeBase node)
1673 { 1689 {
1674 if (node is InventoryItemBase) 1690 if (node is InventoryItemBase)
@@ -1678,7 +1694,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1678 else 1694 else
1679 m_log.ErrorFormat("[CLIENT]: Client for {0} sent unknown inventory node named {1}", Name, node.Name); 1695 m_log.ErrorFormat("[CLIENT]: Client for {0} sent unknown inventory node named {1}", Name, node.Name);
1680 } 1696 }
1681 1697
1682 protected void SendBulkUpdateInventoryItem(InventoryItemBase item) 1698 protected void SendBulkUpdateInventoryItem(InventoryItemBase item)
1683 { 1699 {
1684 const uint FULL_MASK_PERMISSIONS = (uint)PermissionMask.All; 1700 const uint FULL_MASK_PERMISSIONS = (uint)PermissionMask.All;
@@ -1881,11 +1897,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1881 AgentDataUpdatePacket sendAgentDataUpdate = (AgentDataUpdatePacket)PacketPool.Instance.GetPacket(PacketType.AgentDataUpdate); 1897 AgentDataUpdatePacket sendAgentDataUpdate = (AgentDataUpdatePacket)PacketPool.Instance.GetPacket(PacketType.AgentDataUpdate);
1882 sendAgentDataUpdate.AgentData.ActiveGroupID = activegroupid; 1898 sendAgentDataUpdate.AgentData.ActiveGroupID = activegroupid;
1883 sendAgentDataUpdate.AgentData.AgentID = agentid; 1899 sendAgentDataUpdate.AgentData.AgentID = agentid;
1884 sendAgentDataUpdate.AgentData.FirstName = Utils.StringToBytes(firstname); 1900 sendAgentDataUpdate.AgentData.FirstName = Util.StringToBytes256(firstname);
1885 sendAgentDataUpdate.AgentData.GroupName = Utils.StringToBytes(groupname); 1901 sendAgentDataUpdate.AgentData.GroupName = Util.StringToBytes256(groupname);
1886 sendAgentDataUpdate.AgentData.GroupPowers = grouppowers; 1902 sendAgentDataUpdate.AgentData.GroupPowers = grouppowers;
1887 sendAgentDataUpdate.AgentData.GroupTitle = Utils.StringToBytes(grouptitle); 1903 sendAgentDataUpdate.AgentData.GroupTitle = Util.StringToBytes256(grouptitle);
1888 sendAgentDataUpdate.AgentData.LastName = Utils.StringToBytes(lastname); 1904 sendAgentDataUpdate.AgentData.LastName = Util.StringToBytes256(lastname);
1889 OutPacket(sendAgentDataUpdate, ThrottleOutPacketType.Task); 1905 OutPacket(sendAgentDataUpdate, ThrottleOutPacketType.Task);
1890 } 1906 }
1891 1907
@@ -1898,7 +1914,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1898 { 1914 {
1899 AlertMessagePacket alertPack = (AlertMessagePacket)PacketPool.Instance.GetPacket(PacketType.AlertMessage); 1915 AlertMessagePacket alertPack = (AlertMessagePacket)PacketPool.Instance.GetPacket(PacketType.AlertMessage);
1900 alertPack.AlertData = new AlertMessagePacket.AlertDataBlock(); 1916 alertPack.AlertData = new AlertMessagePacket.AlertDataBlock();
1901 alertPack.AlertData.Message = Utils.StringToBytes(message); 1917 alertPack.AlertData.Message = Util.StringToBytes256(message);
1902 alertPack.AlertInfo = new AlertMessagePacket.AlertInfoBlock[0]; 1918 alertPack.AlertInfo = new AlertMessagePacket.AlertInfoBlock[0];
1903 OutPacket(alertPack, ThrottleOutPacketType.Task); 1919 OutPacket(alertPack, ThrottleOutPacketType.Task);
1904 } 1920 }
@@ -1925,7 +1941,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1925 { 1941 {
1926 AgentAlertMessagePacket alertPack = (AgentAlertMessagePacket)PacketPool.Instance.GetPacket(PacketType.AgentAlertMessage); 1942 AgentAlertMessagePacket alertPack = (AgentAlertMessagePacket)PacketPool.Instance.GetPacket(PacketType.AgentAlertMessage);
1927 alertPack.AgentData.AgentID = AgentId; 1943 alertPack.AgentData.AgentID = AgentId;
1928 alertPack.AlertData.Message = Utils.StringToBytes(message); 1944 alertPack.AlertData.Message = Util.StringToBytes256(message);
1929 alertPack.AlertData.Modal = modal; 1945 alertPack.AlertData.Modal = modal;
1930 1946
1931 return alertPack; 1947 return alertPack;
@@ -1935,12 +1951,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1935 string url) 1951 string url)
1936 { 1952 {
1937 LoadURLPacket loadURL = (LoadURLPacket)PacketPool.Instance.GetPacket(PacketType.LoadURL); 1953 LoadURLPacket loadURL = (LoadURLPacket)PacketPool.Instance.GetPacket(PacketType.LoadURL);
1938 loadURL.Data.ObjectName = Utils.StringToBytes(objectname); 1954 loadURL.Data.ObjectName = Util.StringToBytes256(objectname);
1939 loadURL.Data.ObjectID = objectID; 1955 loadURL.Data.ObjectID = objectID;
1940 loadURL.Data.OwnerID = ownerID; 1956 loadURL.Data.OwnerID = ownerID;
1941 loadURL.Data.OwnerIsGroup = groupOwned; 1957 loadURL.Data.OwnerIsGroup = groupOwned;
1942 loadURL.Data.Message = Utils.StringToBytes(message); 1958 loadURL.Data.Message = Util.StringToBytes256(message);
1943 loadURL.Data.URL = Utils.StringToBytes(url); 1959 loadURL.Data.URL = Util.StringToBytes256(url);
1944 OutPacket(loadURL, ThrottleOutPacketType.Task); 1960 OutPacket(loadURL, ThrottleOutPacketType.Task);
1945 } 1961 }
1946 1962
@@ -1948,18 +1964,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1948 { 1964 {
1949 ScriptDialogPacket dialog = (ScriptDialogPacket)PacketPool.Instance.GetPacket(PacketType.ScriptDialog); 1965 ScriptDialogPacket dialog = (ScriptDialogPacket)PacketPool.Instance.GetPacket(PacketType.ScriptDialog);
1950 dialog.Data.ObjectID = objectID; 1966 dialog.Data.ObjectID = objectID;
1951 dialog.Data.ObjectName = Utils.StringToBytes(objectname); 1967 dialog.Data.ObjectName = Util.StringToBytes256(objectname);
1952 // this is the username of the *owner* 1968 // this is the username of the *owner*
1953 dialog.Data.FirstName = Utils.StringToBytes(ownerFirstName); 1969 dialog.Data.FirstName = Util.StringToBytes256(ownerFirstName);
1954 dialog.Data.LastName = Utils.StringToBytes(ownerLastName); 1970 dialog.Data.LastName = Util.StringToBytes256(ownerLastName);
1955 dialog.Data.Message = Utils.StringToBytes(msg); 1971 dialog.Data.Message = Util.StringToBytes1024(msg);
1956 dialog.Data.ImageID = textureID; 1972 dialog.Data.ImageID = textureID;
1957 dialog.Data.ChatChannel = ch; 1973 dialog.Data.ChatChannel = ch;
1958 ScriptDialogPacket.ButtonsBlock[] buttons = new ScriptDialogPacket.ButtonsBlock[buttonlabels.Length]; 1974 ScriptDialogPacket.ButtonsBlock[] buttons = new ScriptDialogPacket.ButtonsBlock[buttonlabels.Length];
1959 for (int i = 0; i < buttonlabels.Length; i++) 1975 for (int i = 0; i < buttonlabels.Length; i++)
1960 { 1976 {
1961 buttons[i] = new ScriptDialogPacket.ButtonsBlock(); 1977 buttons[i] = new ScriptDialogPacket.ButtonsBlock();
1962 buttons[i].ButtonLabel = Utils.StringToBytes(buttonlabels[i]); 1978 buttons[i].ButtonLabel = Util.StringToBytes256(buttonlabels[i]);
1963 } 1979 }
1964 dialog.Buttons = buttons; 1980 dialog.Buttons = buttons;
1965 OutPacket(dialog, ThrottleOutPacketType.Task); 1981 OutPacket(dialog, ThrottleOutPacketType.Task);
@@ -2115,19 +2131,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2115 avatarReply.AgentData.AgentID = AgentId; 2131 avatarReply.AgentData.AgentID = AgentId;
2116 avatarReply.AgentData.AvatarID = avatarID; 2132 avatarReply.AgentData.AvatarID = avatarID;
2117 if (aboutText != null) 2133 if (aboutText != null)
2118 avatarReply.PropertiesData.AboutText = Utils.StringToBytes(aboutText); 2134 avatarReply.PropertiesData.AboutText = Util.StringToBytes1024(aboutText);
2119 else 2135 else
2120 avatarReply.PropertiesData.AboutText = Utils.StringToBytes(""); 2136 avatarReply.PropertiesData.AboutText = Utils.EmptyBytes;
2121 avatarReply.PropertiesData.BornOn = Utils.StringToBytes(bornOn); 2137 avatarReply.PropertiesData.BornOn = Util.StringToBytes256(bornOn);
2122 avatarReply.PropertiesData.CharterMember = charterMember; 2138 avatarReply.PropertiesData.CharterMember = charterMember;
2123 if (flAbout != null) 2139 if (flAbout != null)
2124 avatarReply.PropertiesData.FLAboutText = Utils.StringToBytes(flAbout); 2140 avatarReply.PropertiesData.FLAboutText = Util.StringToBytes256(flAbout);
2125 else 2141 else
2126 avatarReply.PropertiesData.FLAboutText = Utils.StringToBytes(""); 2142 avatarReply.PropertiesData.FLAboutText = Utils.EmptyBytes;
2127 avatarReply.PropertiesData.Flags = flags; 2143 avatarReply.PropertiesData.Flags = flags;
2128 avatarReply.PropertiesData.FLImageID = flImageID; 2144 avatarReply.PropertiesData.FLImageID = flImageID;
2129 avatarReply.PropertiesData.ImageID = imageID; 2145 avatarReply.PropertiesData.ImageID = imageID;
2130 avatarReply.PropertiesData.ProfileURL = Utils.StringToBytes(profileURL); 2146 avatarReply.PropertiesData.ProfileURL = Util.StringToBytes256(profileURL);
2131 avatarReply.PropertiesData.PartnerID = partnerID; 2147 avatarReply.PropertiesData.PartnerID = partnerID;
2132 OutPacket(avatarReply, ThrottleOutPacketType.Task); 2148 OutPacket(avatarReply, ThrottleOutPacketType.Task);
2133 } 2149 }
@@ -2254,7 +2270,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2254 Group.Contribution = GroupMembership[i].Contribution; 2270 Group.Contribution = GroupMembership[i].Contribution;
2255 Group.GroupID = GroupMembership[i].GroupID; 2271 Group.GroupID = GroupMembership[i].GroupID;
2256 Group.GroupInsigniaID = GroupMembership[i].GroupPicture; 2272 Group.GroupInsigniaID = GroupMembership[i].GroupPicture;
2257 Group.GroupName = Utils.StringToBytes(GroupMembership[i].GroupName); 2273 Group.GroupName = Util.StringToBytes256(GroupMembership[i].GroupName);
2258 Group.GroupPowers = GroupMembership[i].GroupPowers; 2274 Group.GroupPowers = GroupMembership[i].GroupPowers;
2259 Groups[i] = Group; 2275 Groups[i] = Group;
2260 2276
@@ -2288,7 +2304,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2288 UUIDGroupNameReplyPacket.UUIDNameBlockBlock[] uidnameblock = new UUIDGroupNameReplyPacket.UUIDNameBlockBlock[1]; 2304 UUIDGroupNameReplyPacket.UUIDNameBlockBlock[] uidnameblock = new UUIDGroupNameReplyPacket.UUIDNameBlockBlock[1];
2289 UUIDGroupNameReplyPacket.UUIDNameBlockBlock uidnamebloc = new UUIDGroupNameReplyPacket.UUIDNameBlockBlock(); 2305 UUIDGroupNameReplyPacket.UUIDNameBlockBlock uidnamebloc = new UUIDGroupNameReplyPacket.UUIDNameBlockBlock();
2290 uidnamebloc.ID = groupLLUID; 2306 uidnamebloc.ID = groupLLUID;
2291 uidnamebloc.GroupName = Utils.StringToBytes(GroupName); 2307 uidnamebloc.GroupName = Util.StringToBytes256(GroupName);
2292 uidnameblock[0] = uidnamebloc; 2308 uidnameblock[0] = uidnamebloc;
2293 pack.UUIDNameBlock = uidnameblock; 2309 pack.UUIDNameBlock = uidnameblock;
2294 OutPacket(pack, ThrottleOutPacketType.Task); 2310 OutPacket(pack, ThrottleOutPacketType.Task);
@@ -2313,8 +2329,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2313 lsrepdb.Score = lsrpia[i].Score; 2329 lsrepdb.Score = lsrpia[i].Score;
2314 lsrepdb.TaskID = lsrpia[i].TaskID; 2330 lsrepdb.TaskID = lsrpia[i].TaskID;
2315 lsrepdb.TaskLocalID = lsrpia[i].TaskLocalID; 2331 lsrepdb.TaskLocalID = lsrpia[i].TaskLocalID;
2316 lsrepdb.TaskName = Utils.StringToBytes(lsrpia[i].TaskName); 2332 lsrepdb.TaskName = Util.StringToBytes256(lsrpia[i].TaskName);
2317 lsrepdb.OwnerName = Utils.StringToBytes(lsrpia[i].OwnerName); 2333 lsrepdb.OwnerName = Util.StringToBytes256(lsrpia[i].OwnerName);
2318 lsrepdba[i] = lsrepdb; 2334 lsrepdba[i] = lsrepdb;
2319 } 2335 }
2320 lsrp.ReportData = lsrepdba; 2336 lsrp.ReportData = lsrepdba;
@@ -3102,9 +3118,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3102 awb.ItemID = wearables[i].ItemID; 3118 awb.ItemID = wearables[i].ItemID;
3103 aw.WearableData[i] = awb; 3119 aw.WearableData[i] = awb;
3104 3120
3105// m_log.DebugFormat( 3121 // m_log.DebugFormat(
3106// "[APPEARANCE]: Sending wearable item/asset {0} {1} (index {2}) for {3}", 3122 // "[APPEARANCE]: Sending wearable item/asset {0} {1} (index {2}) for {3}",
3107// awb.ItemID, awb.AssetID, i, Name); 3123 // awb.ItemID, awb.AssetID, i, Name);
3108 } 3124 }
3109 3125
3110 OutPacket(aw, ThrottleOutPacketType.Task); 3126 OutPacket(aw, ThrottleOutPacketType.Task);
@@ -3127,7 +3143,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3127 3143
3128 avp.Sender.IsTrial = false; 3144 avp.Sender.IsTrial = false;
3129 avp.Sender.ID = agentID; 3145 avp.Sender.ID = agentID;
3130 OutPacket(avp, ThrottleOutPacketType.State); 3146 OutPacket(avp, ThrottleOutPacketType.Task);
3131 } 3147 }
3132 3148
3133 public void SendAnimations(UUID[] animations, int[] seqs, UUID sourceAgentId, UUID[] objectIDs) 3149 public void SendAnimations(UUID[] animations, int[] seqs, UUID sourceAgentId, UUID[] objectIDs)
@@ -3159,123 +3175,174 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3159 3175
3160 #endregion 3176 #endregion
3161 3177
3162 #region Avatar Packet/data sending Methods 3178 #region Prim/Avatar Updates
3163 3179
3164 /// <summary> 3180 /*void SendObjectUpdate(SceneObjectPart obj, PrimFlags creatorFlags, PrimUpdateFlags updateFlags)
3165 /// send a objectupdate packet with information about the clients avatar
3166 /// </summary>
3167 public void SendAvatarData(ulong regionHandle, string firstName, string lastName, string grouptitle, UUID avatarID,
3168 uint avatarLocalID, Vector3 Pos, byte[] textureEntry, uint parentID, Quaternion rotation)
3169 { 3181 {
3170 ObjectUpdatePacket objupdate = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate); 3182 bool canUseCompressed, canUseImproved;
3171 // TODO: don't create new blocks if recycling an old packet 3183 UpdateFlagsToPacketType(creatorFlags, updateFlags, out canUseCompressed, out canUseImproved);
3172 objupdate.RegionData.RegionHandle = regionHandle;
3173 objupdate.RegionData.TimeDilation = ushort.MaxValue;
3174 objupdate.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[1];
3175 objupdate.ObjectData[0] = CreateDefaultAvatarPacket(textureEntry);
3176 3184
3177 //give this avatar object a local id and assign the user a name 3185 if (!canUseImproved && !canUseCompressed)
3178 objupdate.ObjectData[0].ID = avatarLocalID; 3186 SendFullObjectUpdate(obj, creatorFlags, updateFlags);
3179 objupdate.ObjectData[0].FullID = avatarID; 3187 else if (!canUseImproved)
3180 objupdate.ObjectData[0].ParentID = parentID; 3188 SendObjectUpdateCompressed(obj, creatorFlags, updateFlags);
3181 objupdate.ObjectData[0].NameValue = 3189 else
3182 Utils.StringToBytes("FirstName STRING RW SV " + firstName + "\nLastName STRING RW SV " + lastName + "\nTitle STRING RW SV " + grouptitle); 3190 SendImprovedTerseObjectUpdate(obj, creatorFlags, updateFlags);
3191 }
3183 3192
3184 Vector3 pos2 = new Vector3(Pos.X, Pos.Y, Pos.Z); 3193 void SendFullObjectUpdate(SceneObjectPart obj, PrimFlags creatorFlags, PrimUpdateFlags updateFlags)
3185 byte[] pb = pos2.GetBytes(); 3194 {
3186 Array.Copy(pb, 0, objupdate.ObjectData[0].ObjectData, 16, pb.Length); 3195 IClientAPI owner;
3196 if (m_scene.ClientManager.TryGetValue(obj.OwnerID, out owner) && owner is LLClientView)
3197 {
3198 LLClientView llOwner = (LLClientView)owner;
3187 3199
3188 byte[] rot = rotation.GetBytes(); 3200 // Send an update out to the owner
3189 Array.Copy(rot, 0, objupdate.ObjectData[0].ObjectData, 52, rot.Length); 3201 ObjectUpdatePacket updateToOwner = new ObjectUpdatePacket();
3202 updateToOwner.RegionData.RegionHandle = obj.RegionHandle;
3203 //updateToOwner.RegionData.TimeDilation = (ushort)(timeDilation * (float)UInt16.MaxValue);
3204 updateToOwner.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[1];
3205 updateToOwner.ObjectData[0] = BuildUpdateBlock(obj, obj.Flags | creatorFlags | PrimFlags.ObjectYouOwner, 0);
3190 3206
3191 objupdate.Header.Zerocoded = true; 3207 m_udpServer.SendPacket(llOwner.UDPClient, updateToOwner, ThrottleOutPacketType.State, true);
3192 OutPacket(objupdate, ThrottleOutPacketType.Task); 3208 }
3209
3210 // Send an update out to everyone else
3211 ObjectUpdatePacket updateToOthers = new ObjectUpdatePacket();
3212 updateToOthers.RegionData.RegionHandle = obj.RegionHandle;
3213 //updateToOthers.RegionData.TimeDilation = (ushort)(timeDilation * (float)UInt16.MaxValue);
3214 updateToOthers.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[1];
3215 updateToOthers.ObjectData[0] = BuildUpdateBlock(obj, obj.Flags, 0);
3216
3217 m_scene.ClientManager.ForEach(
3218 delegate(IClientAPI client)
3219 {
3220 if (client.AgentId != obj.OwnerID && client is LLClientView)
3221 {
3222 LLClientView llClient = (LLClientView)client;
3223 m_udpServer.SendPacket(llClient.UDPClient, updateToOthers, ThrottleOutPacketType.State, true);
3224 }
3225 }
3226 );
3193 } 3227 }
3194 3228
3195 /// <summary> 3229 void SendObjectUpdateCompressed(SceneObjectPart obj, PrimFlags creatorFlags, PrimUpdateFlags updateFlags)
3196 /// Send a terse positional/rotation/velocity update about an avatar
3197 /// to the client. This avatar can be that of the client itself.
3198 /// </summary>
3199 public virtual void SendAvatarTerseUpdate(ulong regionHandle,
3200 ushort timeDilation, uint localID, Vector3 position,
3201 Vector3 velocity, Quaternion rotation, UUID agentid)
3202 { 3230 {
3203 if (rotation.X == rotation.Y && 3231 }
3204 rotation.Y == rotation.Z &&
3205 rotation.Z == rotation.W && rotation.W == 0)
3206 rotation = Quaternion.Identity;
3207 3232
3208 ImprovedTerseObjectUpdatePacket.ObjectDataBlock terseBlock = 3233 void SendImprovedTerseObjectUpdate(SceneObjectPart obj, PrimFlags creatorFlags, PrimUpdateFlags updateFlags)
3209 CreateAvatarImprovedBlock(localID, position, velocity,rotation); 3234 {
3210 3235 }
3211 lock (m_avatarTerseUpdates) 3236
3212 { 3237 void UpdateFlagsToPacketType(PrimFlags creatorFlags, PrimUpdateFlags updateFlags, out bool canUseCompressed, out bool canUseImproved)
3213 m_avatarTerseUpdates.Add(terseBlock); 3238 {
3239 canUseCompressed = true;
3240 canUseImproved = true;
3214 3241
3215 // If packet is full or own movement packet, send it. 3242 if ((updateFlags & PrimUpdateFlags.FullUpdate) == PrimUpdateFlags.FullUpdate || creatorFlags != PrimFlags.None)
3216 if (m_avatarTerseUpdates.Count >= m_avatarTerseUpdatesPerPacket) 3243 {
3244 canUseCompressed = false;
3245 canUseImproved = false;
3246 }
3247 else
3248 {
3249 if ((updateFlags & PrimUpdateFlags.Velocity) != 0 ||
3250 (updateFlags & PrimUpdateFlags.Acceleration) != 0 ||
3251 (updateFlags & PrimUpdateFlags.CollisionPlane) != 0 ||
3252 (updateFlags & PrimUpdateFlags.Joint) != 0)
3217 { 3253 {
3218 ProcessAvatarTerseUpdates(this, null); 3254 canUseCompressed = false;
3219 } 3255 }
3220 else if (m_avatarTerseUpdates.Count == 1) 3256
3257 if ((updateFlags & PrimUpdateFlags.PrimFlags) != 0 ||
3258 (updateFlags & PrimUpdateFlags.ParentID) != 0 ||
3259 (updateFlags & PrimUpdateFlags.Scale) != 0 ||
3260 (updateFlags & PrimUpdateFlags.PrimData) != 0 ||
3261 (updateFlags & PrimUpdateFlags.Text) != 0 ||
3262 (updateFlags & PrimUpdateFlags.NameValue) != 0 ||
3263 (updateFlags & PrimUpdateFlags.ExtraData) != 0 ||
3264 (updateFlags & PrimUpdateFlags.TextureAnim) != 0 ||
3265 (updateFlags & PrimUpdateFlags.Sound) != 0 ||
3266 (updateFlags & PrimUpdateFlags.Particles) != 0 ||
3267 (updateFlags & PrimUpdateFlags.Material) != 0 ||
3268 (updateFlags & PrimUpdateFlags.ClickAction) != 0 ||
3269 (updateFlags & PrimUpdateFlags.MediaURL) != 0 ||
3270 (updateFlags & PrimUpdateFlags.Joint) != 0)
3221 { 3271 {
3222 lock (m_avatarTerseUpdateTimer) 3272 canUseImproved = false;
3223 m_avatarTerseUpdateTimer.Start();
3224 } 3273 }
3225 } 3274 }
3226 } 3275 }*/
3276
3277 #endregion Prim/Avatar Updates
3278
3279 #region Avatar Packet/Data Sending Methods
3227 3280
3228 private void ProcessAvatarTerseUpdates(object sender, ElapsedEventArgs e) 3281 /// <summary>
3282 /// Send an ObjectUpdate packet with information about an avatar
3283 /// </summary>
3284 public void SendAvatarData(SendAvatarData data)
3229 { 3285 {
3230 lock (m_avatarTerseUpdates) 3286 ObjectUpdatePacket objupdate = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate);
3231 { 3287 objupdate.Header.Zerocoded = true;
3232 ImprovedTerseObjectUpdatePacket terse = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ImprovedTerseObjectUpdate);
3233 3288
3234 terse.RegionData = new ImprovedTerseObjectUpdatePacket.RegionDataBlock(); 3289 objupdate.RegionData.RegionHandle = data.RegionHandle;
3290 objupdate.RegionData.TimeDilation = ushort.MaxValue;
3235 3291
3236 terse.RegionData.RegionHandle = Scene.RegionInfo.RegionHandle; 3292 objupdate.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[1];
3237 terse.RegionData.TimeDilation = 3293 objupdate.ObjectData[0] = CreateAvatarUpdateBlock(data);
3238 (ushort)(Scene.TimeDilation * ushort.MaxValue);
3239 3294
3240 int max = m_avatarTerseUpdatesPerPacket; 3295 OutPacket(objupdate, ThrottleOutPacketType.Task);
3241 if (max > m_avatarTerseUpdates.Count) 3296 }
3242 max = m_avatarTerseUpdates.Count;
3243 3297
3244 int count = 0; 3298 /// <summary>
3245 int size = 0; 3299 /// Send a terse positional/rotation/velocity update about an avatar
3300 /// to the client. This avatar can be that of the client itself.
3301 /// </summary>
3302 public virtual void SendAvatarTerseUpdate(SendAvatarTerseData data)
3303 {
3304 if (data.Priority == double.NaN)
3305 {
3306 m_log.Error("[LLClientView] SendAvatarTerseUpdate received a NaN priority, dropping update");
3307 return;
3308 }
3246 3309
3247 byte[] zerobuffer = new byte[1024]; 3310 Quaternion rotation = data.Rotation;
3248 byte[] blockbuffer = new byte[1024]; 3311 if (rotation.W == 0.0f && rotation.X == 0.0f && rotation.Y == 0.0f && rotation.Z == 0.0f)
3312 rotation = Quaternion.Identity;
3249 3313
3250 for (count = 0 ; count < max ; count++) 3314 ImprovedTerseObjectUpdatePacket.ObjectDataBlock terseBlock = CreateImprovedTerseBlock(data);
3251 {
3252 int length = 0;
3253 m_avatarTerseUpdates[count].ToBytes(blockbuffer, ref length);
3254 length = Helpers.ZeroEncode(blockbuffer, length, zerobuffer);
3255 if (size + length > Packet.MTU)
3256 break;
3257 size += length;
3258 }
3259 3315
3260 terse.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[count]; 3316 lock (m_avatarTerseUpdates.SyncRoot)
3317 m_avatarTerseUpdates.Enqueue(data.Priority, terseBlock, data.LocalID);
3261 3318
3262 for (int i = 0 ; i < count ; i++) 3319 // If we received an update about our own avatar, process the avatar update priority queue immediately
3263 { 3320 if (data.AgentID == m_agentId)
3264 terse.ObjectData[i] = m_avatarTerseUpdates[0]; 3321 ProcessAvatarTerseUpdates();
3265 m_avatarTerseUpdates.RemoveAt(0); 3322 }
3266 }
3267 3323
3268 terse.Header.Reliable = false; 3324 private void ProcessAvatarTerseUpdates()
3269 terse.Header.Zerocoded = true; 3325 {
3270 // FIXME: Move this to ThrottleOutPacketType.State when the real prioritization code is committed 3326 ImprovedTerseObjectUpdatePacket terse = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ImprovedTerseObjectUpdate);
3271 OutPacket(terse, ThrottleOutPacketType.Task); 3327 terse.Header.Reliable = false;
3328 terse.Header.Zerocoded = true;
3272 3329
3273 if (m_avatarTerseUpdates.Count == 0) 3330 //terse.RegionData = new ImprovedTerseObjectUpdatePacket.RegionDataBlock();
3274 { 3331 terse.RegionData.RegionHandle = Scene.RegionInfo.RegionHandle;
3275 lock (m_avatarTerseUpdateTimer) 3332 terse.RegionData.TimeDilation = (ushort)(Scene.TimeDilation * ushort.MaxValue);
3276 m_avatarTerseUpdateTimer.Stop(); 3333
3277 } 3334 lock (m_avatarTerseUpdates.SyncRoot)
3335 {
3336 int count = Math.Min(m_avatarTerseUpdates.Count, m_avatarTerseUpdatesPerPacket);
3337 if (count == 0)
3338 return;
3339
3340 terse.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[count];
3341 for (int i = 0; i < count; i++)
3342 terse.ObjectData[i] = m_avatarTerseUpdates.Dequeue();
3278 } 3343 }
3344
3345 OutPacket(terse, ThrottleOutPacketType.Task);
3279 } 3346 }
3280 3347
3281 public void SendCoarseLocationUpdate(List<UUID> users, List<Vector3> CoarseLocations) 3348 public void SendCoarseLocationUpdate(List<UUID> users, List<Vector3> CoarseLocations)
@@ -3294,7 +3361,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3294 { 3361 {
3295 CoarseLocationUpdatePacket.LocationBlock lb = 3362 CoarseLocationUpdatePacket.LocationBlock lb =
3296 new CoarseLocationUpdatePacket.LocationBlock(); 3363 new CoarseLocationUpdatePacket.LocationBlock();
3297 3364
3298 lb.X = (byte)CoarseLocations[i].X; 3365 lb.X = (byte)CoarseLocations[i].X;
3299 lb.Y = (byte)CoarseLocations[i].Y; 3366 lb.Y = (byte)CoarseLocations[i].Y;
3300 3367
@@ -3314,319 +3381,209 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3314 OutPacket(loc, ThrottleOutPacketType.Task); 3381 OutPacket(loc, ThrottleOutPacketType.Task);
3315 } 3382 }
3316 3383
3317 #endregion 3384 #endregion Avatar Packet/Data Sending Methods
3318 3385
3319 #region Primitive Packet/data Sending Methods 3386 #region Primitive Packet/Data Sending Methods
3320 3387
3321 /// <summary> 3388 public void SendPrimitiveToClient(SendPrimitiveData data)
3322 ///
3323 /// </summary>
3324 /// <param name="localID"></param>
3325 /// <param name="rotation"></param>
3326 /// <param name="attachPoint"></param>
3327 public void AttachObject(uint localID, Quaternion rotation, byte attachPoint, UUID ownerID)
3328 { 3389 {
3329 if (attachPoint > 30 && ownerID != AgentId) // Someone else's HUD 3390 if (data.priority == double.NaN)
3391 {
3392 m_log.Error("[LLClientView] SendPrimitiveToClient received a NaN priority, dropping update");
3330 return; 3393 return;
3394 }
3331 3395
3332 ObjectAttachPacket attach = (ObjectAttachPacket)PacketPool.Instance.GetPacket(PacketType.ObjectAttach); 3396 Quaternion rotation = data.rotation;
3333 // TODO: don't create new blocks if recycling an old packet 3397 if (rotation.W == 0.0f && rotation.X == 0.0f && rotation.Y == 0.0f && rotation.Z == 0.0f)
3334 attach.AgentData.AgentID = AgentId; 3398 rotation = Quaternion.Identity;
3335 attach.AgentData.SessionID = m_sessionId;
3336 attach.AgentData.AttachmentPoint = attachPoint;
3337 attach.ObjectData = new ObjectAttachPacket.ObjectDataBlock[1];
3338 attach.ObjectData[0] = new ObjectAttachPacket.ObjectDataBlock();
3339 attach.ObjectData[0].ObjectLocalID = localID;
3340 attach.ObjectData[0].Rotation = rotation;
3341 attach.Header.Zerocoded = true;
3342 OutPacket(attach, ThrottleOutPacketType.Task);
3343 }
3344
3345 public void SendPrimitiveToClient(
3346 ulong regionHandle, ushort timeDilation, uint localID, PrimitiveBaseShape primShape,
3347 Vector3 pos, Vector3 vel, Vector3 acc, Quaternion rotation, Vector3 rvel,
3348 uint flags, UUID objectID, UUID ownerID, string text, byte[] color,
3349 uint parentID, byte[] particleSystem, byte clickAction, byte material)
3350 {
3351 byte[] textureanim = new byte[0];
3352
3353 SendPrimitiveToClient(regionHandle, timeDilation, localID, primShape, pos, vel,
3354 acc, rotation, rvel, flags,
3355 objectID, ownerID, text, color, parentID, particleSystem,
3356 clickAction, material, textureanim, false, 0, UUID.Zero, UUID.Zero, 0, 0, 0);
3357 }
3358
3359 public void SendPrimitiveToClient(
3360 ulong regionHandle, ushort timeDilation, uint localID, PrimitiveBaseShape primShape,
3361 Vector3 pos, Vector3 velocity, Vector3 acceleration, Quaternion rotation, Vector3 rotational_velocity,
3362 uint flags,
3363 UUID objectID, UUID ownerID, string text, byte[] color, uint parentID, byte[] particleSystem,
3364 byte clickAction, byte material, byte[] textureanim, bool attachment, uint AttachPoint, UUID AssetId, UUID SoundId, double SoundGain, byte SoundFlags, double SoundRadius)
3365 {
3366 3399
3367 if (AttachPoint > 30 && ownerID != AgentId) // Someone else's HUD 3400 if (data.AttachPoint > 30 && data.ownerID != AgentId) // Someone else's HUD
3368 return; 3401 return;
3369 if (primShape.PCode == 9 && primShape.State != 0 && parentID == 0) 3402 if (data.primShape.State != 0 && data.parentID == 0 && data.primShape.PCode == 9)
3370 return; 3403 return;
3371 3404
3372 if (rotation.X == rotation.Y && rotation.Y == rotation.Z && rotation.Z == rotation.W && rotation.W == 0) 3405 ObjectUpdatePacket.ObjectDataBlock objectData = CreatePrimUpdateBlock(data);
3373 rotation = Quaternion.Identity;
3374 3406
3375 ObjectUpdatePacket.ObjectDataBlock objectData = CreatePrimUpdateBlock(primShape, flags); 3407 lock (m_primFullUpdates.SyncRoot)
3408 m_primFullUpdates.Enqueue(data.priority, objectData, data.localID);
3409 }
3376 3410
3377 objectData.ID = localID; 3411 void ProcessPrimFullUpdates()
3378 objectData.FullID = objectID; 3412 {
3379 objectData.OwnerID = ownerID; 3413 ObjectUpdatePacket outPacket = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate);
3414 outPacket.Header.Zerocoded = true;
3380 3415
3381 objectData.Text = Util.StringToBytes256(text); 3416 outPacket.RegionData.RegionHandle = Scene.RegionInfo.RegionHandle;
3382 objectData.TextColor[0] = color[0]; 3417 outPacket.RegionData.TimeDilation = (ushort)(Scene.TimeDilation * ushort.MaxValue);
3383 objectData.TextColor[1] = color[1];
3384 objectData.TextColor[2] = color[2];
3385 objectData.TextColor[3] = color[3];
3386 objectData.ParentID = parentID;
3387 objectData.PSBlock = particleSystem;
3388 objectData.ClickAction = clickAction;
3389 objectData.Material = material;
3390 objectData.Flags = 0;
3391 3418
3392 if (attachment) 3419 lock (m_primFullUpdates.SyncRoot)
3393 { 3420 {
3394 // Necessary??? 3421 int count = Math.Min(m_primFullUpdates.Count, m_primFullUpdatesPerPacket);
3395 objectData.JointAxisOrAnchor = new Vector3(0, 0, 2); 3422 if (count == 0)
3396 objectData.JointPivot = new Vector3(0, 0, 0); 3423 return;
3397
3398 // Item from inventory???
3399 objectData.NameValue =
3400 Utils.StringToBytes("AttachItemID STRING RW SV " + AssetId.Guid);
3401 objectData.State = (byte)((AttachPoint % 16) * 16 + (AttachPoint / 16));
3402 }
3403 3424
3404 // Xantor 20080528: Send sound info as well 3425 outPacket.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[count];
3405 // Xantor 20080530: Zero out everything if there's no SoundId, so zerocompression will work again 3426 for (int i = 0; i < count; i++)
3406 objectData.Sound = SoundId; 3427 outPacket.ObjectData[i] = m_primFullUpdates.Dequeue();
3407 if (SoundId == UUID.Zero)
3408 {
3409 objectData.OwnerID = UUID.Zero;
3410 objectData.Gain = 0.0f;
3411 objectData.Radius = 0.0f;
3412 objectData.Flags = 0;
3413 }
3414 else
3415 {
3416 objectData.OwnerID = ownerID;
3417 objectData.Gain = (float)SoundGain;
3418 objectData.Radius = (float)SoundRadius;
3419 objectData.Flags = SoundFlags;
3420 } 3428 }
3421 3429
3422 byte[] pb = pos.GetBytes(); 3430 OutPacket(outPacket, ThrottleOutPacketType.State);
3423 Array.Copy(pb, 0, objectData.ObjectData, 0, pb.Length); 3431 }
3424
3425 byte[] vel = velocity.GetBytes();
3426 Array.Copy(vel, 0, objectData.ObjectData, pb.Length, vel.Length);
3427
3428 byte[] rot = rotation.GetBytes();
3429 Array.Copy(rot, 0, objectData.ObjectData, 36, rot.Length);
3430
3431 byte[] rvel = rotational_velocity.GetBytes();
3432 Array.Copy(rvel, 0, objectData.ObjectData, 36 + rot.Length, rvel.Length);
3433 3432
3434 if (textureanim.Length > 0) 3433 public void SendPrimTerseUpdate(SendPrimitiveTerseData data)
3434 {
3435 if (data.Priority == double.NaN)
3435 { 3436 {
3436 objectData.TextureAnim = textureanim; 3437 m_log.Error("[LLClientView] SendPrimTerseUpdate received a NaN priority, dropping update");
3438 return;
3437 } 3439 }
3438 3440
3439 lock (m_primFullUpdates) 3441 Quaternion rotation = data.Rotation;
3440 { 3442 if (rotation.W == 0.0f && rotation.X == 0.0f && rotation.Y == 0.0f && rotation.Z == 0.0f)
3441 if (m_primFullUpdates.Count == 0) 3443 rotation = Quaternion.Identity;
3442 m_primFullUpdateTimer.Start();
3443 3444
3444 m_primFullUpdates.Add(objectData); 3445 if (data.AttachPoint > 30 && data.OwnerID != AgentId) // Someone else's HUD
3446 return;
3445 3447
3446 if (m_primFullUpdates.Count >= m_primFullUpdatesPerPacket) 3448 ImprovedTerseObjectUpdatePacket.ObjectDataBlock objectData = CreateImprovedTerseBlock(data);
3447 ProcessPrimFullUpdates(this, null);
3448 }
3449 }
3450 3449
3451 void HandleQueueEmpty(ThrottleOutPacketType queue) 3450 lock (m_primTerseUpdates.SyncRoot)
3452 { 3451 m_primTerseUpdates.Enqueue(data.Priority, objectData, data.LocalID);
3453 switch (queue)
3454 {
3455 case ThrottleOutPacketType.Texture:
3456 ProcessTextureRequests();
3457 break;
3458 }
3459 } 3452 }
3460 3453
3461 void ProcessTextureRequests() 3454 void ProcessPrimTerseUpdates()
3462 { 3455 {
3463 if (m_imageManager != null) 3456 ImprovedTerseObjectUpdatePacket outPacket = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ImprovedTerseObjectUpdate);
3464 m_imageManager.ProcessImageQueue(m_textureSendLimit); 3457 outPacket.Header.Reliable = false;
3465 } 3458 outPacket.Header.Zerocoded = true;
3466 3459
3467 void ProcessPrimFullUpdates(object sender, ElapsedEventArgs e) 3460 outPacket.RegionData.RegionHandle = Scene.RegionInfo.RegionHandle;
3468 { 3461 outPacket.RegionData.TimeDilation = (ushort)(Scene.TimeDilation * ushort.MaxValue);
3469 lock (m_primFullUpdates)
3470 {
3471 if (m_primFullUpdates.Count == 0 && m_primFullUpdateTimer.Enabled)
3472 {
3473 lock (m_primFullUpdateTimer)
3474 m_primFullUpdateTimer.Stop();
3475 3462
3463 lock (m_primTerseUpdates.SyncRoot)
3464 {
3465 int count = Math.Min(m_primTerseUpdates.Count, m_primTerseUpdatesPerPacket);
3466 if (count == 0)
3476 return; 3467 return;
3477 }
3478
3479 ObjectUpdatePacket outPacket =
3480 (ObjectUpdatePacket)PacketPool.Instance.GetPacket(
3481 PacketType.ObjectUpdate);
3482 3468
3483 outPacket.RegionData.RegionHandle = 3469 outPacket.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[count];
3484 Scene.RegionInfo.RegionHandle; 3470 for (int i = 0; i < count; i++)
3485 outPacket.RegionData.TimeDilation = 3471 outPacket.ObjectData[i] = m_primTerseUpdates.Dequeue();
3486 (ushort)(Scene.TimeDilation * ushort.MaxValue); 3472 }
3487
3488 int max = m_primFullUpdates.Count;
3489 if (max > m_primFullUpdatesPerPacket)
3490 max = m_primFullUpdatesPerPacket;
3491
3492 int count = 0;
3493 int size = 0;
3494 3473
3495 byte[] zerobuffer = new byte[1024]; 3474 OutPacket(outPacket, ThrottleOutPacketType.State);
3496 byte[] blockbuffer = new byte[1024]; 3475 }
3497 3476
3498 for (count = 0 ; count < max ; count++) 3477 public void ReprioritizeUpdates(StateUpdateTypes type, UpdatePriorityHandler handler)
3478 {
3479 PriorityQueue<double, ImprovedTerseObjectUpdatePacket.ObjectDataBlock>.UpdatePriorityHandler terse_update_priority_handler =
3480 delegate(ref double priority, uint local_id)
3499 { 3481 {
3500 int length = 0; 3482 priority = handler(new UpdatePriorityData(priority, local_id));
3501 m_primFullUpdates[count].ToBytes(blockbuffer, ref length); 3483 return priority != double.NaN;
3502 length = Helpers.ZeroEncode(blockbuffer, length, zerobuffer); 3484 };
3503 if (size + length > Packet.MTU) 3485 PriorityQueue<double, ObjectUpdatePacket.ObjectDataBlock>.UpdatePriorityHandler update_priority_handler =
3504 break; 3486 delegate(ref double priority, uint local_id)
3505 size += length; 3487 {
3506 } 3488 priority = handler(new UpdatePriorityData(priority, local_id));
3489 return priority != double.NaN;
3490 };
3507 3491
3508 outPacket.ObjectData = 3492 if ((type & StateUpdateTypes.AvatarTerse) != 0)
3509 new ObjectUpdatePacket.ObjectDataBlock[count]; 3493 {
3494 lock (m_avatarTerseUpdates.SyncRoot)
3495 m_avatarTerseUpdates.Reprioritize(terse_update_priority_handler);
3496 }
3510 3497
3511 for (int index = 0 ; index < count ; index++) 3498 if ((type & StateUpdateTypes.PrimitiveFull) != 0)
3512 { 3499 {
3513 outPacket.ObjectData[index] = m_primFullUpdates[0]; 3500 lock (m_primFullUpdates.SyncRoot)
3514 m_primFullUpdates.RemoveAt(0); 3501 m_primFullUpdates.Reprioritize(update_priority_handler);
3515 } 3502 }
3516 3503
3517 outPacket.Header.Zerocoded = true; 3504 if ((type & StateUpdateTypes.PrimitiveTerse) != 0)
3518 OutPacket(outPacket, ThrottleOutPacketType.State); 3505 {
3506 lock (m_primTerseUpdates.SyncRoot)
3507 m_primTerseUpdates.Reprioritize(terse_update_priority_handler);
3508 }
3509 }
3519 3510
3520 if (m_primFullUpdates.Count == 0 && m_primFullUpdateTimer.Enabled) 3511 public void FlushPrimUpdates()
3521 lock (m_primFullUpdateTimer) 3512 {
3522 m_primFullUpdateTimer.Stop(); 3513 while (m_primFullUpdates.Count > 0)
3514 {
3515 ProcessPrimFullUpdates();
3516 }
3517 while (m_primTerseUpdates.Count > 0)
3518 {
3519 ProcessPrimTerseUpdates();
3520 }
3521 while (m_avatarTerseUpdates.Count > 0)
3522 {
3523 ProcessAvatarTerseUpdates();
3523 } 3524 }
3524 } 3525 }
3525 3526
3527 #endregion Primitive Packet/Data Sending Methods
3528
3526 /// <summary> 3529 /// <summary>
3527 /// 3530 ///
3528 /// </summary> 3531 /// </summary>
3529 public void SendPrimTerseUpdate(ulong regionHandle, ushort timeDilation, uint localID, Vector3 position, 3532 /// <param name="localID"></param>
3530 Quaternion rotation, Vector3 velocity, Vector3 rotationalvelocity, byte state, UUID AssetId, UUID ownerID, int attachPoint) 3533 /// <param name="rotation"></param>
3534 /// <param name="attachPoint"></param>
3535 public void AttachObject(uint localID, Quaternion rotation, byte attachPoint, UUID ownerID)
3531 { 3536 {
3532 if (attachPoint > 30 && ownerID != AgentId) // Someone else's HUD 3537 if (attachPoint > 30 && ownerID != AgentId) // Someone else's HUD
3533 return; 3538 return;
3534 3539
3535 if (rotation.X == rotation.Y && rotation.Y == rotation.Z && rotation.Z == rotation.W && rotation.W == 0) 3540 ObjectAttachPacket attach = (ObjectAttachPacket)PacketPool.Instance.GetPacket(PacketType.ObjectAttach);
3536 rotation = Quaternion.Identity; 3541 // TODO: don't create new blocks if recycling an old packet
3537 3542 attach.AgentData.AgentID = AgentId;
3538 ImprovedTerseObjectUpdatePacket.ObjectDataBlock objectData = 3543 attach.AgentData.SessionID = m_sessionId;
3539 CreatePrimImprovedBlock(localID, position, rotation, 3544 attach.AgentData.AttachmentPoint = attachPoint;
3540 velocity, rotationalvelocity, state); 3545 attach.ObjectData = new ObjectAttachPacket.ObjectDataBlock[1];
3541 3546 attach.ObjectData[0] = new ObjectAttachPacket.ObjectDataBlock();
3542 lock (m_primTerseUpdates) 3547 attach.ObjectData[0].ObjectLocalID = localID;
3543 { 3548 attach.ObjectData[0].Rotation = rotation;
3544 if (m_primTerseUpdates.Count == 0) 3549 attach.Header.Zerocoded = true;
3545 m_primTerseUpdateTimer.Start(); 3550 OutPacket(attach, ThrottleOutPacketType.Task);
3546
3547 m_primTerseUpdates.Add(objectData);
3548
3549 if (m_primTerseUpdates.Count >= m_primTerseUpdatesPerPacket)
3550 ProcessPrimTerseUpdates(this, null);
3551 }
3552 } 3551 }
3553 3552
3554 void ProcessPrimTerseUpdates(object sender, ElapsedEventArgs e) 3553 void HandleQueueEmpty(ThrottleOutPacketType queue)
3555 { 3554 {
3556 lock (m_primTerseUpdates) 3555 switch (queue)
3557 { 3556 {
3558 if (m_primTerseUpdates.Count == 0) 3557 case ThrottleOutPacketType.Texture:
3559 { 3558 ProcessTextureRequests();
3560 lock (m_primTerseUpdateTimer) 3559 break;
3561 m_primTerseUpdateTimer.Stop(); 3560 case ThrottleOutPacketType.Task:
3562 3561 lock (m_avatarTerseUpdates.SyncRoot)
3563 return; 3562 {
3564 } 3563 if (m_avatarTerseUpdates.Count > 0)
3565 3564 ProcessAvatarTerseUpdates();
3566 ImprovedTerseObjectUpdatePacket outPacket = 3565 }
3567 (ImprovedTerseObjectUpdatePacket) 3566 break;
3568 PacketPool.Instance.GetPacket( 3567 case ThrottleOutPacketType.State:
3569 PacketType.ImprovedTerseObjectUpdate); 3568 lock (m_primFullUpdates.SyncRoot)
3570 3569 {
3571 outPacket.RegionData.RegionHandle = 3570 if (m_primFullUpdates.Count > 0)
3572 Scene.RegionInfo.RegionHandle; 3571 ProcessPrimFullUpdates();
3573 outPacket.RegionData.TimeDilation = 3572 }
3574 (ushort)(Scene.TimeDilation * ushort.MaxValue);
3575
3576 int max = m_primTerseUpdates.Count;
3577 if (max > m_primTerseUpdatesPerPacket)
3578 max = m_primTerseUpdatesPerPacket;
3579
3580 int count = 0;
3581 int size = 0;
3582
3583 byte[] zerobuffer = new byte[1024];
3584 byte[] blockbuffer = new byte[1024];
3585
3586 for (count = 0 ; count < max ; count++)
3587 {
3588 int length = 0;
3589 m_primTerseUpdates[count].ToBytes(blockbuffer, ref length);
3590 length = Helpers.ZeroEncode(blockbuffer, length, zerobuffer);
3591 if (size + length > Packet.MTU)
3592 break;
3593 size += length;
3594 }
3595
3596 outPacket.ObjectData =
3597 new ImprovedTerseObjectUpdatePacket.
3598 ObjectDataBlock[count];
3599
3600 for (int index = 0 ; index < count ; index++)
3601 {
3602 outPacket.ObjectData[index] = m_primTerseUpdates[0];
3603 m_primTerseUpdates.RemoveAt(0);
3604 }
3605
3606 outPacket.Header.Reliable = false;
3607 outPacket.Header.Zerocoded = true;
3608 OutPacket(outPacket, ThrottleOutPacketType.State);
3609 3573
3610 if (m_primTerseUpdates.Count == 0) 3574 lock (m_primTerseUpdates.SyncRoot)
3611 lock (m_primTerseUpdateTimer) 3575 {
3612 m_primTerseUpdateTimer.Stop(); 3576 if (m_primTerseUpdates.Count > 0)
3577 ProcessPrimTerseUpdates();
3578 }
3579 break;
3613 } 3580 }
3614 } 3581 }
3615 3582
3616 public void FlushPrimUpdates() 3583 void ProcessTextureRequests()
3617 { 3584 {
3618 while (m_primFullUpdates.Count > 0) 3585 if (m_imageManager != null)
3619 { 3586 m_imageManager.ProcessImageQueue(m_textureSendLimit);
3620 ProcessPrimFullUpdates(this, null);
3621 }
3622 while (m_primTerseUpdates.Count > 0)
3623 {
3624 ProcessPrimTerseUpdates(this, null);
3625 }
3626 while (m_avatarTerseUpdates.Count > 0)
3627 {
3628 ProcessAvatarTerseUpdates(this, null);
3629 }
3630 } 3587 }
3631 3588
3632 public void SendAssetUploadCompleteMessage(sbyte AssetType, bool Success, UUID AssetFullID) 3589 public void SendAssetUploadCompleteMessage(sbyte AssetType, bool Success, UUID AssetFullID)
@@ -3659,7 +3616,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3659 newPack.Header.Zerocoded = true; 3616 newPack.Header.Zerocoded = true;
3660 OutPacket(newPack, ThrottleOutPacketType.Asset); 3617 OutPacket(newPack, ThrottleOutPacketType.Asset);
3661 } 3618 }
3662 3619
3663 public void SendInitiateDownload(string simFileName, string clientFileName) 3620 public void SendInitiateDownload(string simFileName, string clientFileName)
3664 { 3621 {
3665 InitiateDownloadPacket newPack = new InitiateDownloadPacket(); 3622 InitiateDownloadPacket newPack = new InitiateDownloadPacket();
@@ -3668,7 +3625,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3668 newPack.FileData.ViewerFilename = Utils.StringToBytes(clientFileName); 3625 newPack.FileData.ViewerFilename = Utils.StringToBytes(clientFileName);
3669 OutPacket(newPack, ThrottleOutPacketType.Asset); 3626 OutPacket(newPack, ThrottleOutPacketType.Asset);
3670 } 3627 }
3671 3628
3672 public void SendImageFirstPart( 3629 public void SendImageFirstPart(
3673 ushort numParts, UUID ImageUUID, uint ImageSize, byte[] ImageData, byte imageCodec) 3630 ushort numParts, UUID ImageUUID, uint ImageSize, byte[] ImageData, byte imageCodec)
3674 { 3631 {
@@ -3810,8 +3767,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3810 OutPacket(proper, ThrottleOutPacketType.Task); 3767 OutPacket(proper, ThrottleOutPacketType.Task);
3811 } 3768 }
3812 3769
3813 #endregion
3814
3815 #region Estate Data Sending Methods 3770 #region Estate Data Sending Methods
3816 3771
3817 private static bool convertParamStringToBool(byte[] field) 3772 private static bool convertParamStringToBool(byte[] field)
@@ -3858,7 +3813,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3858 3813
3859 public void SendBannedUserList(UUID invoice, EstateBan[] bl, uint estateID) 3814 public void SendBannedUserList(UUID invoice, EstateBan[] bl, uint estateID)
3860 { 3815 {
3861 List<UUID>BannedUsers = new List<UUID>(); 3816 List<UUID> BannedUsers = new List<UUID>();
3862 3817
3863 for (int i = 0; i < bl.Length; i++) 3818 for (int i = 0; i < bl.Length; i++)
3864 { 3819 {
@@ -3922,7 +3877,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3922 rinfoblk.UseEstateSun = args.useEstateSun; 3877 rinfoblk.UseEstateSun = args.useEstateSun;
3923 rinfoblk.WaterHeight = args.waterHeight; 3878 rinfoblk.WaterHeight = args.waterHeight;
3924 rinfoblk.SimName = Utils.StringToBytes(args.simName); 3879 rinfoblk.SimName = Utils.StringToBytes(args.simName);
3925 3880
3926 rinfopack.RegionInfo2 = new RegionInfoPacket.RegionInfo2Block(); 3881 rinfopack.RegionInfo2 = new RegionInfoPacket.RegionInfo2Block();
3927 rinfopack.RegionInfo2.HardMaxAgents = uint.MaxValue; 3882 rinfopack.RegionInfo2.HardMaxAgents = uint.MaxValue;
3928 rinfopack.RegionInfo2.HardMaxObjects = uint.MaxValue; 3883 rinfopack.RegionInfo2.HardMaxObjects = uint.MaxValue;
@@ -4169,7 +4124,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4169 4124
4170 public void SendLandObjectOwners(LandData land, List<UUID> groups, Dictionary<UUID, int> ownersAndCount) 4125 public void SendLandObjectOwners(LandData land, List<UUID> groups, Dictionary<UUID, int> ownersAndCount)
4171 { 4126 {
4172 4127
4173 4128
4174 int notifyCount = ownersAndCount.Count; 4129 int notifyCount = ownersAndCount.Count;
4175 ParcelObjectOwnersReplyPacket pack = (ParcelObjectOwnersReplyPacket)PacketPool.Instance.GetPacket(PacketType.ParcelObjectOwnersReply); 4130 ParcelObjectOwnersReplyPacket pack = (ParcelObjectOwnersReplyPacket)PacketPool.Instance.GetPacket(PacketType.ParcelObjectOwnersReply);
@@ -4218,325 +4173,223 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4218 4173
4219 #region Helper Methods 4174 #region Helper Methods
4220 4175
4221 protected ImprovedTerseObjectUpdatePacket.ObjectDataBlock CreateAvatarImprovedBlock(uint localID, Vector3 pos, 4176 protected ImprovedTerseObjectUpdatePacket.ObjectDataBlock CreateImprovedTerseBlock(SendAvatarTerseData data)
4222 Vector3 velocity,
4223 Quaternion rotation)
4224 { 4177 {
4225 byte[] bytes = new byte[60]; 4178 return CreateImprovedTerseBlock(true, data.LocalID, 0, data.CollisionPlane, data.Position, data.Velocity,
4226 int i = 0; 4179 data.Acceleration, data.Rotation, Vector3.Zero, data.TextureEntry);
4227 ImprovedTerseObjectUpdatePacket.ObjectDataBlock dat = PacketPool.GetDataBlock<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>();
4228
4229 dat.TextureEntry = new byte[0]; // AvatarTemplate.TextureEntry;
4230
4231 uint ID = localID;
4232
4233 bytes[i++] = (byte)(ID % 256);
4234 bytes[i++] = (byte)((ID >> 8) % 256);
4235 bytes[i++] = (byte)((ID >> 16) % 256);
4236 bytes[i++] = (byte)((ID >> 24) % 256);
4237 bytes[i++] = 0;
4238 bytes[i++] = 1;
4239 i += 14;
4240 bytes[i++] = 128;
4241 bytes[i++] = 63;
4242
4243 byte[] pb = pos.GetBytes();
4244 Array.Copy(pb, 0, bytes, i, pb.Length);
4245 i += 12;
4246
4247 Vector3 internDirec = new Vector3(velocity.X, velocity.Y, velocity.Z);
4248
4249 internDirec = internDirec / 128.0f;
4250 internDirec.X += 1;
4251 internDirec.Y += 1;
4252 internDirec.Z += 1;
4253
4254 ushort InternVelocityX = (ushort)(32768 * internDirec.X);
4255 ushort InternVelocityY = (ushort)(32768 * internDirec.Y);
4256 ushort InternVelocityZ = (ushort)(32768 * internDirec.Z);
4257
4258 ushort ac = 32767;
4259 bytes[i++] = (byte)(InternVelocityX % 256);
4260 bytes[i++] = (byte)((InternVelocityX >> 8) % 256);
4261 bytes[i++] = (byte)(InternVelocityY % 256);
4262 bytes[i++] = (byte)((InternVelocityY >> 8) % 256);
4263 bytes[i++] = (byte)(InternVelocityZ % 256);
4264 bytes[i++] = (byte)((InternVelocityZ >> 8) % 256);
4265
4266 //accel
4267 bytes[i++] = (byte)(ac % 256);
4268 bytes[i++] = (byte)((ac >> 8) % 256);
4269 bytes[i++] = (byte)(ac % 256);
4270 bytes[i++] = (byte)((ac >> 8) % 256);
4271 bytes[i++] = (byte)(ac % 256);
4272 bytes[i++] = (byte)((ac >> 8) % 256);
4273
4274 //rotation
4275 ushort rw, rx, ry, rz;
4276 rw = (ushort)(32768 * (rotation.W + 1));
4277 rx = (ushort)(32768 * (rotation.X + 1));
4278 ry = (ushort)(32768 * (rotation.Y + 1));
4279 rz = (ushort)(32768 * (rotation.Z + 1));
4280
4281 //rot
4282 bytes[i++] = (byte)(rx % 256);
4283 bytes[i++] = (byte)((rx >> 8) % 256);
4284 bytes[i++] = (byte)(ry % 256);
4285 bytes[i++] = (byte)((ry >> 8) % 256);
4286 bytes[i++] = (byte)(rz % 256);
4287 bytes[i++] = (byte)((rz >> 8) % 256);
4288 bytes[i++] = (byte)(rw % 256);
4289 bytes[i++] = (byte)((rw >> 8) % 256);
4290
4291 //rotation vel
4292 bytes[i++] = (byte)(ac % 256);
4293 bytes[i++] = (byte)((ac >> 8) % 256);
4294 bytes[i++] = (byte)(ac % 256);
4295 bytes[i++] = (byte)((ac >> 8) % 256);
4296 bytes[i++] = (byte)(ac % 256);
4297 bytes[i++] = (byte)((ac >> 8) % 256);
4298
4299 dat.Data = bytes;
4300
4301 return (dat);
4302 } 4180 }
4303 4181
4304 /// <summary> 4182 protected ImprovedTerseObjectUpdatePacket.ObjectDataBlock CreateImprovedTerseBlock(SendPrimitiveTerseData data)
4305 ///
4306 /// </summary>
4307 /// <param name="localID"></param>
4308 /// <param name="position"></param>
4309 /// <param name="rotation"></param>
4310 /// <returns></returns>
4311 protected ImprovedTerseObjectUpdatePacket.ObjectDataBlock CreatePrimImprovedBlock(uint localID,
4312 Vector3 position,
4313 Quaternion rotation,
4314 Vector3 velocity,
4315 Vector3 rotationalvelocity,
4316 byte state)
4317 { 4183 {
4318 uint ID = localID; 4184 return CreateImprovedTerseBlock(false, data.LocalID, data.State, Vector4.Zero, data.Position, data.Velocity,
4319 byte[] bytes = new byte[60]; 4185 data.Acceleration, data.Rotation, data.AngularVelocity, data.TextureEntry);
4320
4321 int i = 0;
4322 ImprovedTerseObjectUpdatePacket.ObjectDataBlock dat = PacketPool.GetDataBlock<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>();
4323 dat.TextureEntry = new byte[0];
4324 bytes[i++] = (byte)(ID % 256);
4325 bytes[i++] = (byte)((ID >> 8) % 256);
4326 bytes[i++] = (byte)((ID >> 16) % 256);
4327 bytes[i++] = (byte)((ID >> 24) % 256);
4328 bytes[i++] = (byte)(((state & 0xf0) >> 4) | ((state & 0x0f) << 4));
4329 bytes[i++] = 0;
4330
4331 byte[] pb = position.GetBytes();
4332 Array.Copy(pb, 0, bytes, i, pb.Length);
4333 i += 12;
4334 ushort ac = 32767;
4335
4336 ushort velx, vely, velz;
4337 Vector3 vel = new Vector3(velocity.X, velocity.Y, velocity.Z);
4338
4339 vel = vel / 128.0f;
4340 vel.X += 1;
4341 vel.Y += 1;
4342 vel.Z += 1;
4343 //vel
4344 velx = (ushort)(32768 * (vel.X));
4345 vely = (ushort)(32768 * (vel.Y));
4346 velz = (ushort)(32768 * (vel.Z));
4347
4348 bytes[i++] = (byte)(velx % 256);
4349 bytes[i++] = (byte)((velx >> 8) % 256);
4350 bytes[i++] = (byte)(vely % 256);
4351 bytes[i++] = (byte)((vely >> 8) % 256);
4352 bytes[i++] = (byte)(velz % 256);
4353 bytes[i++] = (byte)((velz >> 8) % 256);
4354
4355 //accel
4356 bytes[i++] = (byte)(ac % 256);
4357 bytes[i++] = (byte)((ac >> 8) % 256);
4358 bytes[i++] = (byte)(ac % 256);
4359 bytes[i++] = (byte)((ac >> 8) % 256);
4360 bytes[i++] = (byte)(ac % 256);
4361 bytes[i++] = (byte)((ac >> 8) % 256);
4362
4363 ushort rw, rx, ry, rz;
4364 rw = (ushort)(32768 * (rotation.W + 1));
4365 rx = (ushort)(32768 * (rotation.X + 1));
4366 ry = (ushort)(32768 * (rotation.Y + 1));
4367 rz = (ushort)(32768 * (rotation.Z + 1));
4368
4369 //rot
4370 bytes[i++] = (byte)(rx % 256);
4371 bytes[i++] = (byte)((rx >> 8) % 256);
4372 bytes[i++] = (byte)(ry % 256);
4373 bytes[i++] = (byte)((ry >> 8) % 256);
4374 bytes[i++] = (byte)(rz % 256);
4375 bytes[i++] = (byte)((rz >> 8) % 256);
4376 bytes[i++] = (byte)(rw % 256);
4377 bytes[i++] = (byte)((rw >> 8) % 256);
4378
4379 //rotation vel
4380 Vector3 rvel = new Vector3(rotationalvelocity.X, rotationalvelocity.Y, rotationalvelocity.Z);
4381
4382 rvel = rvel / 128.0f;
4383 rvel.X += 1;
4384 rvel.Y += 1;
4385 rvel.Z += 1;
4386 //vel
4387 ushort rvelx = (ushort)(32768 * (rvel.X));
4388 ushort rvely = (ushort)(32768 * (rvel.Y));
4389 ushort rvelz = (ushort)(32768 * (rvel.Z));
4390
4391 bytes[i++] = (byte)(rvelx % 256);
4392 bytes[i++] = (byte)((rvelx >> 8) % 256);
4393 bytes[i++] = (byte)(rvely % 256);
4394 bytes[i++] = (byte)((rvely >> 8) % 256);
4395 bytes[i++] = (byte)(rvelz % 256);
4396 bytes[i++] = (byte)((rvelz >> 8) % 256);
4397 dat.Data = bytes;
4398
4399 return dat;
4400 } 4186 }
4401 4187
4402 /// <summary> 4188 protected ImprovedTerseObjectUpdatePacket.ObjectDataBlock CreateImprovedTerseBlock(bool avatar, uint localID, byte state,
4403 /// Create the ObjectDataBlock for a ObjectUpdatePacket (for a Primitive) 4189 Vector4 collisionPlane, Vector3 position, Vector3 velocity, Vector3 acceleration, Quaternion rotation,
4404 /// </summary> 4190 Vector3 angularVelocity, byte[] textureEntry)
4405 /// <param name="primData"></param> 4191 {
4406 /// <returns></returns> 4192 int pos = 0;
4407 protected ObjectUpdatePacket.ObjectDataBlock CreatePrimUpdateBlock(PrimitiveBaseShape primShape, uint flags) 4193 byte[] data = new byte[(avatar ? 60 : 44)];
4408 {
4409 ObjectUpdatePacket.ObjectDataBlock objupdate = PacketPool.GetDataBlock<ObjectUpdatePacket.ObjectDataBlock>();
4410 SetDefaultPrimPacketValues(objupdate);
4411 objupdate.UpdateFlags = flags;
4412 SetPrimPacketShapeData(objupdate, primShape);
4413
4414 if ((primShape.PCode == (byte)PCode.NewTree) || (primShape.PCode == (byte)PCode.Tree) || (primShape.PCode == (byte)PCode.Grass))
4415 {
4416 objupdate.Data = new byte[1];
4417 objupdate.Data[0] = primShape.State;
4418 }
4419 return objupdate;
4420 }
4421
4422 protected void SetPrimPacketShapeData(ObjectUpdatePacket.ObjectDataBlock objectData, PrimitiveBaseShape primData)
4423 {
4424 objectData.TextureEntry = primData.TextureEntry;
4425 objectData.PCode = primData.PCode;
4426 objectData.State = primData.State;
4427 objectData.PathBegin = primData.PathBegin;
4428 objectData.PathEnd = primData.PathEnd;
4429 objectData.PathScaleX = primData.PathScaleX;
4430 objectData.PathScaleY = primData.PathScaleY;
4431 objectData.PathShearX = primData.PathShearX;
4432 objectData.PathShearY = primData.PathShearY;
4433 objectData.PathSkew = primData.PathSkew;
4434 objectData.ProfileBegin = primData.ProfileBegin;
4435 objectData.ProfileEnd = primData.ProfileEnd;
4436 objectData.Scale = primData.Scale;
4437 objectData.PathCurve = primData.PathCurve;
4438 objectData.ProfileCurve = primData.ProfileCurve;
4439 objectData.ProfileHollow = primData.ProfileHollow;
4440 objectData.PathRadiusOffset = primData.PathRadiusOffset;
4441 objectData.PathRevolutions = primData.PathRevolutions;
4442 objectData.PathTaperX = primData.PathTaperX;
4443 objectData.PathTaperY = primData.PathTaperY;
4444 objectData.PathTwist = primData.PathTwist;
4445 objectData.PathTwistBegin = primData.PathTwistBegin;
4446 objectData.ExtraParams = primData.ExtraParams;
4447 }
4448 4194
4449 /// <summary> 4195 // LocalID
4450 /// Set some default values in a ObjectUpdatePacket 4196 Utils.UIntToBytes(localID, data, pos);
4451 /// </summary> 4197 pos += 4;
4452 /// <param name="objdata"></param>
4453 protected void SetDefaultPrimPacketValues(ObjectUpdatePacket.ObjectDataBlock objdata)
4454 {
4455 objdata.PSBlock = new byte[0];
4456 objdata.ExtraParams = new byte[1];
4457 objdata.MediaURL = new byte[0];
4458 objdata.NameValue = new byte[0];
4459 objdata.Text = new byte[0];
4460 objdata.TextColor = new byte[4];
4461 objdata.JointAxisOrAnchor = new Vector3(0, 0, 0);
4462 objdata.JointPivot = new Vector3(0, 0, 0);
4463 objdata.Material = 3;
4464 objdata.TextureAnim = new byte[0];
4465 objdata.Sound = UUID.Zero;
4466 objdata.State = 0;
4467 objdata.Data = new byte[0];
4468
4469 objdata.ObjectData = new byte[60];
4470 objdata.ObjectData[46] = 128;
4471 objdata.ObjectData[47] = 63;
4472 }
4473 4198
4474 /// <summary> 4199 // Avatar/CollisionPlane
4475 /// 4200 data[pos++] = state;
4476 /// </summary> 4201 if (avatar)
4477 /// <returns></returns> 4202 {
4478 public ObjectUpdatePacket.ObjectDataBlock CreateDefaultAvatarPacket(byte[] textureEntry) 4203 data[pos++] = 1;
4479 { 4204
4480 ObjectUpdatePacket.ObjectDataBlock objdata = PacketPool.GetDataBlock<ObjectUpdatePacket.ObjectDataBlock>(); 4205 if (collisionPlane == Vector4.Zero)
4481 // new OpenMetaverse.Packets.ObjectUpdatePacket.ObjectDataBlock(data1, ref i); 4206 collisionPlane = Vector4.UnitW;
4482 4207
4483 SetDefaultAvatarPacketValues(ref objdata); 4208 collisionPlane.ToBytes(data, pos);
4484 objdata.UpdateFlags = 61 + (9 << 8) + (130 << 16) + (16 << 24); 4209 pos += 16;
4485 objdata.PathCurve = 16; 4210 }
4486 objdata.ProfileCurve = 1; 4211 else
4487 objdata.PathScaleX = 100;
4488 objdata.PathScaleY = 100;
4489 objdata.ParentID = 0;
4490 objdata.OwnerID = UUID.Zero;
4491 objdata.Scale = new Vector3(1, 1, 1);
4492 objdata.PCode = (byte)PCode.Avatar;
4493 if (textureEntry != null)
4494 { 4212 {
4495 objdata.TextureEntry = textureEntry; 4213 ++pos;
4496 } 4214 }
4497 Vector3 pos = new Vector3(objdata.ObjectData, 16);
4498 pos.X = 100f;
4499 objdata.ID = 8880000;
4500 objdata.NameValue = Utils.StringToBytes("FirstName STRING RW SV Test \nLastName STRING RW SV User ");
4501 //Vector3 pos2 = new Vector3(100f, 100f, 23f);
4502 //objdata.FullID=user.AgentId;
4503 byte[] pb = pos.GetBytes();
4504 Array.Copy(pb, 0, objdata.ObjectData, 16, pb.Length);
4505 4215
4506 return objdata; 4216 // Position
4507 } 4217 position.ToBytes(data, pos);
4218 pos += 12;
4508 4219
4509 /// <summary> 4220 // Velocity
4510 /// 4221 Utils.UInt16ToBytes(Utils.FloatToUInt16(velocity.X, -128.0f, 128.0f), data, pos); pos += 2;
4511 /// </summary> 4222 Utils.UInt16ToBytes(Utils.FloatToUInt16(velocity.Y, -128.0f, 128.0f), data, pos); pos += 2;
4512 /// <param name="objdata"></param> 4223 Utils.UInt16ToBytes(Utils.FloatToUInt16(velocity.Z, -128.0f, 128.0f), data, pos); pos += 2;
4513 protected void SetDefaultAvatarPacketValues(ref ObjectUpdatePacket.ObjectDataBlock objdata) 4224
4514 { 4225 // Acceleration
4515 objdata.PSBlock = new byte[0]; 4226 Utils.UInt16ToBytes(Utils.FloatToUInt16(acceleration.X, -64.0f, 64.0f), data, pos); pos += 2;
4516 objdata.ExtraParams = new byte[1]; 4227 Utils.UInt16ToBytes(Utils.FloatToUInt16(acceleration.Y, -64.0f, 64.0f), data, pos); pos += 2;
4517 objdata.MediaURL = new byte[0]; 4228 Utils.UInt16ToBytes(Utils.FloatToUInt16(acceleration.Z, -64.0f, 64.0f), data, pos); pos += 2;
4518 objdata.NameValue = new byte[0]; 4229
4519 objdata.Text = new byte[0]; 4230 // Rotation
4520 objdata.TextColor = new byte[4]; 4231 Utils.UInt16ToBytes(Utils.FloatToUInt16(rotation.X, -1.0f, 1.0f), data, pos); pos += 2;
4521 objdata.JointAxisOrAnchor = new Vector3(0, 0, 0); 4232 Utils.UInt16ToBytes(Utils.FloatToUInt16(rotation.Y, -1.0f, 1.0f), data, pos); pos += 2;
4522 objdata.JointPivot = new Vector3(0, 0, 0); 4233 Utils.UInt16ToBytes(Utils.FloatToUInt16(rotation.Z, -1.0f, 1.0f), data, pos); pos += 2;
4523 objdata.Material = 4; 4234 Utils.UInt16ToBytes(Utils.FloatToUInt16(rotation.W, -1.0f, 1.0f), data, pos); pos += 2;
4524 objdata.TextureAnim = new byte[0]; 4235
4525 objdata.Sound = UUID.Zero; 4236 // Angular Velocity
4526 Primitive.TextureEntry ntex = new Primitive.TextureEntry(new UUID("00000000-0000-0000-5005-000000000005")); 4237 Utils.UInt16ToBytes(Utils.FloatToUInt16(angularVelocity.X, -64.0f, 64.0f), data, pos); pos += 2;
4527 objdata.TextureEntry = ntex.GetBytes(); 4238 Utils.UInt16ToBytes(Utils.FloatToUInt16(angularVelocity.Y, -64.0f, 64.0f), data, pos); pos += 2;
4528 4239 Utils.UInt16ToBytes(Utils.FloatToUInt16(angularVelocity.Z, -64.0f, 64.0f), data, pos); pos += 2;
4529 objdata.State = 0; 4240
4530 objdata.Data = new byte[0]; 4241 ImprovedTerseObjectUpdatePacket.ObjectDataBlock block = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock();
4531 4242 block.Data = data;
4532 objdata.ObjectData = new byte[76]; 4243
4533 objdata.ObjectData[15] = 128; 4244 if (textureEntry != null && textureEntry.Length > 0)
4534 objdata.ObjectData[16] = 63; 4245 {
4535 objdata.ObjectData[56] = 128; 4246 byte[] teBytesFinal = new byte[textureEntry.Length + 4];
4536 objdata.ObjectData[61] = 102; 4247
4537 objdata.ObjectData[62] = 40; 4248 // Texture Length
4538 objdata.ObjectData[63] = 61; 4249 Utils.IntToBytes(textureEntry.Length, textureEntry, 0);
4539 objdata.ObjectData[64] = 189; 4250 // Texture
4251 Buffer.BlockCopy(textureEntry, 0, teBytesFinal, 4, textureEntry.Length);
4252
4253 block.TextureEntry = teBytesFinal;
4254 }
4255 else
4256 {
4257 block.TextureEntry = Utils.EmptyBytes;
4258 }
4259
4260 return block;
4261 }
4262
4263 protected ObjectUpdatePacket.ObjectDataBlock CreateAvatarUpdateBlock(SendAvatarData data)
4264 {
4265 byte[] objectData = new byte[76];
4266
4267 Vector4.UnitW.ToBytes(objectData, 0); // TODO: Collision plane support
4268 data.Position.ToBytes(objectData, 16);
4269 //data.Velocity.ToBytes(objectData, 28);
4270 //data.Acceleration.ToBytes(objectData, 40);
4271 data.Rotation.ToBytes(objectData, 52);
4272 //data.AngularVelocity.ToBytes(objectData, 64);
4273
4274 ObjectUpdatePacket.ObjectDataBlock update = new ObjectUpdatePacket.ObjectDataBlock();
4275
4276 update.Data = Utils.EmptyBytes;
4277 update.ExtraParams = new byte[1];
4278 update.FullID = data.AvatarID;
4279 update.ID = data.AvatarLocalID;
4280 update.Material = (byte)Material.Flesh;
4281 update.MediaURL = Utils.EmptyBytes;
4282 update.NameValue = Utils.StringToBytes("FirstName STRING RW SV " + data.FirstName + "\nLastName STRING RW SV " +
4283 data.LastName + "\nTitle STRING RW SV " + data.GroupTitle);
4284 update.ObjectData = objectData;
4285 update.ParentID = data.ParentID;
4286 update.PathCurve = 16;
4287 update.PathScaleX = 100;
4288 update.PathScaleY = 100;
4289 update.PCode = (byte)PCode.Avatar;
4290 update.ProfileCurve = 1;
4291 update.PSBlock = Utils.EmptyBytes;
4292 update.Scale = Vector3.One;
4293 update.Text = Utils.EmptyBytes;
4294 update.TextColor = new byte[4];
4295 update.TextureAnim = Utils.EmptyBytes;
4296 update.TextureEntry = data.TextureEntry ?? Utils.EmptyBytes;
4297 update.UpdateFlags = 61 + (9 << 8) + (130 << 16) + (16 << 24); // TODO: Replace these numbers with PrimFlags
4298
4299 return update;
4300 }
4301
4302 protected ObjectUpdatePacket.ObjectDataBlock CreatePrimUpdateBlock(SendPrimitiveData data)
4303 {
4304 byte[] objectData = new byte[60];
4305 data.pos.ToBytes(objectData, 0);
4306 data.vel.ToBytes(objectData, 12);
4307 data.acc.ToBytes(objectData, 24);
4308 data.rotation.ToBytes(objectData, 36);
4309 data.rvel.ToBytes(objectData, 48);
4310
4311 ObjectUpdatePacket.ObjectDataBlock update = new ObjectUpdatePacket.ObjectDataBlock();
4312 update.ClickAction = (byte)data.clickAction;
4313 update.CRC = 0;
4314 update.ExtraParams = data.primShape.ExtraParams ?? Utils.EmptyBytes;
4315 update.FullID = data.objectID;
4316 update.ID = data.localID;
4317 //update.JointAxisOrAnchor = Vector3.Zero; // These are deprecated
4318 //update.JointPivot = Vector3.Zero;
4319 //update.JointType = 0;
4320 update.Material = data.material;
4321 update.MediaURL = Utils.EmptyBytes; // FIXME: Support this in OpenSim
4322 if (data.attachment)
4323 {
4324 update.NameValue = Util.StringToBytes256("AttachItemID STRING RW SV " + data.AssetId);
4325 update.State = (byte)((data.AttachPoint % 16) * 16 + (data.AttachPoint / 16));
4326 }
4327 else
4328 {
4329 update.NameValue = Utils.EmptyBytes;
4330 update.State = data.primShape.State;
4331 }
4332 update.ObjectData = objectData;
4333 update.ParentID = data.parentID;
4334 update.PathBegin = data.primShape.PathBegin;
4335 update.PathCurve = data.primShape.PathCurve;
4336 update.PathEnd = data.primShape.PathEnd;
4337 update.PathRadiusOffset = data.primShape.PathRadiusOffset;
4338 update.PathRevolutions = data.primShape.PathRevolutions;
4339 update.PathScaleX = data.primShape.PathScaleX;
4340 update.PathScaleY = data.primShape.PathScaleY;
4341 update.PathShearX = data.primShape.PathShearX;
4342 update.PathShearY = data.primShape.PathShearY;
4343 update.PathSkew = data.primShape.PathSkew;
4344 update.PathTaperX = data.primShape.PathTaperX;
4345 update.PathTaperY = data.primShape.PathTaperY;
4346 update.PathTwist = data.primShape.PathTwist;
4347 update.PathTwistBegin = data.primShape.PathTwistBegin;
4348 update.PCode = data.primShape.PCode;
4349 update.ProfileBegin = data.primShape.ProfileBegin;
4350 update.ProfileCurve = data.primShape.ProfileCurve;
4351 update.ProfileEnd = data.primShape.ProfileEnd;
4352 update.ProfileHollow = data.primShape.ProfileHollow;
4353 update.PSBlock = data.particleSystem ?? Utils.EmptyBytes;
4354 update.TextColor = data.color ?? Color4.Black.GetBytes(true);
4355 update.TextureAnim = data.textureanim ?? Utils.EmptyBytes;
4356 update.TextureEntry = data.primShape.TextureEntry ?? Utils.EmptyBytes;
4357 update.Scale = data.primShape.Scale;
4358 update.Text = Util.StringToBytes256(data.text);
4359 update.UpdateFlags = (uint)data.flags;
4360
4361 if (data.SoundId != UUID.Zero)
4362 {
4363 update.Sound = data.SoundId;
4364 update.OwnerID = data.ownerID;
4365 update.Gain = (float)data.SoundVolume;
4366 update.Radius = (float)data.SoundRadius;
4367 update.Flags = data.SoundFlags;
4368 }
4369
4370 switch ((PCode)data.primShape.PCode)
4371 {
4372 case PCode.Grass:
4373 case PCode.Tree:
4374 case PCode.NewTree:
4375 update.Data = new byte[] { data.primShape.State };
4376 break;
4377 default:
4378 // TODO: Support ScratchPad
4379 //if (prim.ScratchPad != null)
4380 //{
4381 // update.Data = new byte[prim.ScratchPad.Length];
4382 // Buffer.BlockCopy(prim.ScratchPad, 0, update.Data, 0, update.Data.Length);
4383 //}
4384 //else
4385 //{
4386 // update.Data = Utils.EmptyBytes;
4387 //}
4388 update.Data = Utils.EmptyBytes;
4389 break;
4390 }
4391
4392 return update;
4540 } 4393 }
4541 4394
4542 public void SendNameReply(UUID profileId, string firstname, string lastname) 4395 public void SendNameReply(UUID profileId, string firstname, string lastname)
@@ -4546,8 +4399,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4546 packet.UUIDNameBlock = new UUIDNameReplyPacket.UUIDNameBlockBlock[1]; 4399 packet.UUIDNameBlock = new UUIDNameReplyPacket.UUIDNameBlockBlock[1];
4547 packet.UUIDNameBlock[0] = new UUIDNameReplyPacket.UUIDNameBlockBlock(); 4400 packet.UUIDNameBlock[0] = new UUIDNameReplyPacket.UUIDNameBlockBlock();
4548 packet.UUIDNameBlock[0].ID = profileId; 4401 packet.UUIDNameBlock[0].ID = profileId;
4549 packet.UUIDNameBlock[0].FirstName = Utils.StringToBytes(firstname); 4402 packet.UUIDNameBlock[0].FirstName = Util.StringToBytes256(firstname);
4550 packet.UUIDNameBlock[0].LastName = Utils.StringToBytes(lastname); 4403 packet.UUIDNameBlock[0].LastName = Util.StringToBytes256(lastname);
4551 4404
4552 OutPacket(packet, ThrottleOutPacketType.Task); 4405 OutPacket(packet, ThrottleOutPacketType.Task);
4553 } 4406 }
@@ -4593,7 +4446,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4593 4446
4594 private bool HandleMoneyTransferRequest(IClientAPI sender, Packet Pack) 4447 private bool HandleMoneyTransferRequest(IClientAPI sender, Packet Pack)
4595 { 4448 {
4596 MoneyTransferRequestPacket money = (MoneyTransferRequestPacket) Pack; 4449 MoneyTransferRequestPacket money = (MoneyTransferRequestPacket)Pack;
4597 // validate the agent owns the agentID and sessionID 4450 // validate the agent owns the agentID and sessionID
4598 if (money.MoneyData.SourceID == sender.AgentId && money.AgentData.AgentID == sender.AgentId && 4451 if (money.MoneyData.SourceID == sender.AgentId && money.AgentData.AgentID == sender.AgentId &&
4599 money.AgentData.SessionID == sender.SessionId) 4452 money.AgentData.SessionID == sender.SessionId)
@@ -4614,7 +4467,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4614 4467
4615 private bool HandleParcelBuyRequest(IClientAPI sender, Packet Pack) 4468 private bool HandleParcelBuyRequest(IClientAPI sender, Packet Pack)
4616 { 4469 {
4617 ParcelBuyPacket parcel = (ParcelBuyPacket) Pack; 4470 ParcelBuyPacket parcel = (ParcelBuyPacket)Pack;
4618 if (parcel.AgentData.AgentID == AgentId && parcel.AgentData.SessionID == SessionId) 4471 if (parcel.AgentData.AgentID == AgentId && parcel.AgentData.SessionID == SessionId)
4619 { 4472 {
4620 ParcelBuy handlerParcelBuy = OnParcelBuy; 4473 ParcelBuy handlerParcelBuy = OnParcelBuy;
@@ -4634,7 +4487,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4634 private bool HandleUUIDGroupNameRequest(IClientAPI sender, Packet Pack) 4487 private bool HandleUUIDGroupNameRequest(IClientAPI sender, Packet Pack)
4635 { 4488 {
4636 UUIDGroupNameRequestPacket upack = (UUIDGroupNameRequestPacket)Pack; 4489 UUIDGroupNameRequestPacket upack = (UUIDGroupNameRequestPacket)Pack;
4637 4490
4638 4491
4639 for (int i = 0; i < upack.UUIDNameBlock.Length; i++) 4492 for (int i = 0; i < upack.UUIDNameBlock.Length; i++)
4640 { 4493 {
@@ -4650,7 +4503,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4650 4503
4651 public bool HandleGenericMessage(IClientAPI sender, Packet pack) 4504 public bool HandleGenericMessage(IClientAPI sender, Packet pack)
4652 { 4505 {
4653 GenericMessagePacket gmpack = (GenericMessagePacket) pack; 4506 GenericMessagePacket gmpack = (GenericMessagePacket)pack;
4654 if (m_genericPacketHandlers.Count == 0) return false; 4507 if (m_genericPacketHandlers.Count == 0) return false;
4655 if (gmpack.AgentData.SessionID != SessionId) return false; 4508 if (gmpack.AgentData.SessionID != SessionId) return false;
4656 4509
@@ -4743,8 +4596,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4743 scriptQuestion.Data.TaskID = taskID; 4596 scriptQuestion.Data.TaskID = taskID;
4744 scriptQuestion.Data.ItemID = itemID; 4597 scriptQuestion.Data.ItemID = itemID;
4745 scriptQuestion.Data.Questions = question; 4598 scriptQuestion.Data.Questions = question;
4746 scriptQuestion.Data.ObjectName = Utils.StringToBytes(taskName); 4599 scriptQuestion.Data.ObjectName = Util.StringToBytes256(taskName);
4747 scriptQuestion.Data.ObjectOwner = Utils.StringToBytes(ownerName); 4600 scriptQuestion.Data.ObjectOwner = Util.StringToBytes256(ownerName);
4748 4601
4749 OutPacket(scriptQuestion, ThrottleOutPacketType.Task); 4602 OutPacket(scriptQuestion, ThrottleOutPacketType.Task);
4750 } 4603 }
@@ -4787,7 +4640,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4787 { 4640 {
4788 if (((LogoutRequestPacket)packet).AgentData.SessionID != SessionId) return false; 4641 if (((LogoutRequestPacket)packet).AgentData.SessionID != SessionId) return false;
4789 } 4642 }
4790 4643
4791 return Logout(client); 4644 return Logout(client);
4792 } 4645 }
4793 4646
@@ -4845,7 +4698,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4845 4698
4846 cachedresp.Header.Zerocoded = true; 4699 cachedresp.Header.Zerocoded = true;
4847 OutPacket(cachedresp, ThrottleOutPacketType.Task); 4700 OutPacket(cachedresp, ThrottleOutPacketType.Task);
4848 4701
4849 return true; 4702 return true;
4850 } 4703 }
4851 4704
@@ -4895,7 +4748,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4895 UpdatePrimSingleRotation handlerUpdatePrimSingleRotation = OnUpdatePrimSingleRotation; 4748 UpdatePrimSingleRotation handlerUpdatePrimSingleRotation = OnUpdatePrimSingleRotation;
4896 if (handlerUpdatePrimSingleRotation != null) 4749 if (handlerUpdatePrimSingleRotation != null)
4897 { 4750 {
4898 // m_log.Info("new tab rotation is " + rot1.X + " , " + rot1.Y + " , " + rot1.Z + " , " + rot1.W); 4751 // m_log.Info("new tab rotation is " + rot1.X + " , " + rot1.Y + " , " + rot1.Z + " , " + rot1.W);
4899 handlerUpdatePrimSingleRotation(localId, rot1, this); 4752 handlerUpdatePrimSingleRotation(localId, rot1, this);
4900 } 4753 }
4901 break; 4754 break;
@@ -4906,8 +4759,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4906 UpdatePrimSingleRotationPosition handlerUpdatePrimSingleRotationPosition = OnUpdatePrimSingleRotationPosition; 4759 UpdatePrimSingleRotationPosition handlerUpdatePrimSingleRotationPosition = OnUpdatePrimSingleRotationPosition;
4907 if (handlerUpdatePrimSingleRotationPosition != null) 4760 if (handlerUpdatePrimSingleRotationPosition != null)
4908 { 4761 {
4909 // m_log.Debug("new mouse rotation position is " + rotPos.X + " , " + rotPos.Y + " , " + rotPos.Z); 4762 // m_log.Debug("new mouse rotation position is " + rotPos.X + " , " + rotPos.Y + " , " + rotPos.Z);
4910 // m_log.Info("new mouse rotation is " + rot2.X + " , " + rot2.Y + " , " + rot2.Z + " , " + rot2.W); 4763 // m_log.Info("new mouse rotation is " + rot2.X + " , " + rot2.Y + " , " + rot2.Z + " , " + rot2.W);
4911 handlerUpdatePrimSingleRotationPosition(localId, rot2, rotPos, this); 4764 handlerUpdatePrimSingleRotationPosition(localId, rot2, rotPos, this);
4912 } 4765 }
4913 break; 4766 break;
@@ -4918,7 +4771,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4918 UpdateVector handlerUpdatePrimScale = OnUpdatePrimScale; 4771 UpdateVector handlerUpdatePrimScale = OnUpdatePrimScale;
4919 if (handlerUpdatePrimScale != null) 4772 if (handlerUpdatePrimScale != null)
4920 { 4773 {
4921// m_log.Debug("new scale is " + scale4.X + " , " + scale4.Y + " , " + scale4.Z); 4774 // m_log.Debug("new scale is " + scale4.X + " , " + scale4.Y + " , " + scale4.Z);
4922 handlerUpdatePrimScale(localId, scale4, this); 4775 handlerUpdatePrimScale(localId, scale4, this);
4923 } 4776 }
4924 break; 4777 break;
@@ -4957,7 +4810,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4957 UpdatePrimRotation handlerUpdatePrimRotation = OnUpdatePrimGroupRotation; 4810 UpdatePrimRotation handlerUpdatePrimRotation = OnUpdatePrimGroupRotation;
4958 if (handlerUpdatePrimRotation != null) 4811 if (handlerUpdatePrimRotation != null)
4959 { 4812 {
4960 // Console.WriteLine("new rotation is " + rot3.X + " , " + rot3.Y + " , " + rot3.Z + " , " + rot3.W); 4813 // Console.WriteLine("new rotation is " + rot3.X + " , " + rot3.Y + " , " + rot3.Z + " , " + rot3.W);
4961 handlerUpdatePrimRotation(localId, rot3, this); 4814 handlerUpdatePrimRotation(localId, rot3, this);
4962 } 4815 }
4963 break; 4816 break;
@@ -4968,8 +4821,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4968 handlerUpdatePrimGroupRotation = OnUpdatePrimGroupMouseRotation; 4821 handlerUpdatePrimGroupRotation = OnUpdatePrimGroupMouseRotation;
4969 if (handlerUpdatePrimGroupRotation != null) 4822 if (handlerUpdatePrimGroupRotation != null)
4970 { 4823 {
4971 // m_log.Debug("new rotation position is " + pos.X + " , " + pos.Y + " , " + pos.Z); 4824 // m_log.Debug("new rotation position is " + pos.X + " , " + pos.Y + " , " + pos.Z);
4972 // m_log.Debug("new group mouse rotation is " + rot4.X + " , " + rot4.Y + " , " + rot4.Z + " , " + rot4.W); 4825 // m_log.Debug("new group mouse rotation is " + rot4.X + " , " + rot4.Y + " , " + rot4.Z + " , " + rot4.W);
4973 handlerUpdatePrimGroupRotation(localId, pos3, rot4, this); 4826 handlerUpdatePrimGroupRotation(localId, pos3, rot4, this);
4974 } 4827 }
4975 break; 4828 break;
@@ -4980,7 +4833,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4980 UpdateVector handlerUpdatePrimGroupScale = OnUpdatePrimGroupScale; 4833 UpdateVector handlerUpdatePrimGroupScale = OnUpdatePrimGroupScale;
4981 if (handlerUpdatePrimGroupScale != null) 4834 if (handlerUpdatePrimGroupScale != null)
4982 { 4835 {
4983// m_log.Debug("new scale is " + scale7.X + " , " + scale7.Y + " , " + scale7.Z); 4836 // m_log.Debug("new scale is " + scale7.X + " , " + scale7.Y + " , " + scale7.Z);
4984 handlerUpdatePrimGroupScale(localId, scale7, this); 4837 handlerUpdatePrimGroupScale(localId, scale7, this);
4985 } 4838 }
4986 break; 4839 break;
@@ -5138,7 +4991,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5138 if (m_moneyBalance + debit >= 0) 4991 if (m_moneyBalance + debit >= 0)
5139 { 4992 {
5140 m_moneyBalance += debit; 4993 m_moneyBalance += debit;
5141 SendMoneyBalance(UUID.Zero, true, Utils.StringToBytes("Poof Poof!"), m_moneyBalance); 4994 SendMoneyBalance(UUID.Zero, true, Util.StringToBytes256("Poof Poof!"), m_moneyBalance);
5142 return true; 4995 return true;
5143 } 4996 }
5144 return false; 4997 return false;
@@ -5212,7 +5065,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5212 // Main packet processing conditional 5065 // Main packet processing conditional
5213 switch (Pack.Type) 5066 switch (Pack.Type)
5214 { 5067 {
5215 #region Scene/Avatar 5068 #region Scene/Avatar
5216 5069
5217 case PacketType.AvatarPropertiesRequest: 5070 case PacketType.AvatarPropertiesRequest:
5218 AvatarPropertiesRequestPacket avatarProperties = (AvatarPropertiesRequestPacket)Pack; 5071 AvatarPropertiesRequestPacket avatarProperties = (AvatarPropertiesRequestPacket)Pack;
@@ -5463,7 +5316,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5463 break; 5316 break;
5464 5317
5465 case PacketType.DeRezObject: 5318 case PacketType.DeRezObject:
5466 DeRezObjectPacket DeRezPacket = (DeRezObjectPacket) Pack; 5319 DeRezObjectPacket DeRezPacket = (DeRezObjectPacket)Pack;
5467 5320
5468 #region Packet Session and User Check 5321 #region Packet Session and User Check
5469 if (m_checkPackets) 5322 if (m_checkPackets)
@@ -5484,13 +5337,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5484 { 5337 {
5485 deRezIDs.Add(data.ObjectLocalID); 5338 deRezIDs.Add(data.ObjectLocalID);
5486 } 5339 }
5487 // It just so happens that the values on the DeRezAction enumerator match the Destination 5340 // It just so happens that the values on the DeRezAction enumerator match the Destination
5488 // values given by a Second Life client 5341 // values given by a Second Life client
5489 handlerDeRezObject(this, deRezIDs, 5342 handlerDeRezObject(this, deRezIDs,
5490 DeRezPacket.AgentBlock.GroupID, 5343 DeRezPacket.AgentBlock.GroupID,
5491 (DeRezAction)DeRezPacket.AgentBlock.Destination, 5344 (DeRezAction)DeRezPacket.AgentBlock.Destination,
5492 DeRezPacket.AgentBlock.DestinationID); 5345 DeRezPacket.AgentBlock.DestinationID);
5493 5346
5494 } 5347 }
5495 break; 5348 break;
5496 5349
@@ -5594,7 +5447,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5594 } 5447 }
5595 5448
5596 break; 5449 break;
5597 5450
5598 case PacketType.AgentIsNowWearing: 5451 case PacketType.AgentIsNowWearing:
5599 if (OnAvatarNowWearing != null) 5452 if (OnAvatarNowWearing != null)
5600 { 5453 {
@@ -5798,7 +5651,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5798 5651
5799 if (lastarg != null) 5652 if (lastarg != null)
5800 { 5653 {
5801 update = 5654 update =
5802 ( 5655 (
5803 (x.BodyRotation != lastarg.BodyRotation) || 5656 (x.BodyRotation != lastarg.BodyRotation) ||
5804 (x.CameraAtAxis != lastarg.CameraAtAxis) || 5657 (x.CameraAtAxis != lastarg.CameraAtAxis) ||
@@ -5991,7 +5844,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5991 } 5844 }
5992 5845
5993 break; 5846 break;
5994 5847
5995 case PacketType.UserInfoRequest: 5848 case PacketType.UserInfoRequest:
5996 UserInfoRequest handlerUserInfoRequest = OnUserInfoRequest; 5849 UserInfoRequest handlerUserInfoRequest = OnUserInfoRequest;
5997 if (handlerUserInfoRequest != null) 5850 if (handlerUserInfoRequest != null)
@@ -6003,7 +5856,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6003 SendUserInfoReply(false, true, ""); 5856 SendUserInfoReply(false, true, "");
6004 } 5857 }
6005 break; 5858 break;
6006 5859
6007 case PacketType.UpdateUserInfo: 5860 case PacketType.UpdateUserInfo:
6008 UpdateUserInfoPacket updateUserInfo = (UpdateUserInfoPacket)Pack; 5861 UpdateUserInfoPacket updateUserInfo = (UpdateUserInfoPacket)Pack;
6009 5862
@@ -6030,7 +5883,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6030 visible, this); 5883 visible, this);
6031 } 5884 }
6032 break; 5885 break;
6033 5886
6034 case PacketType.SetStartLocationRequest: 5887 case PacketType.SetStartLocationRequest:
6035 SetStartLocationRequestPacket avSetStartLocationRequestPacket = (SetStartLocationRequestPacket)Pack; 5888 SetStartLocationRequestPacket avSetStartLocationRequestPacket = (SetStartLocationRequestPacket)Pack;
6036 5889
@@ -6088,9 +5941,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6088 } 5941 }
6089 break; 5942 break;
6090 5943
6091 #endregion 5944 #endregion
6092 5945
6093 #region Objects/m_sceneObjects 5946 #region Objects/m_sceneObjects
6094 5947
6095 case PacketType.ObjectLink: 5948 case PacketType.ObjectLink:
6096 ObjectLinkPacket link = (ObjectLinkPacket)Pack; 5949 ObjectLinkPacket link = (ObjectLinkPacket)Pack;
@@ -6121,7 +5974,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6121 handlerLinkObjects(this, parentprimid, childrenprims); 5974 handlerLinkObjects(this, parentprimid, childrenprims);
6122 } 5975 }
6123 break; 5976 break;
6124 5977
6125 case PacketType.ObjectDelink: 5978 case PacketType.ObjectDelink:
6126 ObjectDelinkPacket delink = (ObjectDelinkPacket)Pack; 5979 ObjectDelinkPacket delink = (ObjectDelinkPacket)Pack;
6127 5980
@@ -6150,7 +6003,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6150 } 6003 }
6151 6004
6152 break; 6005 break;
6153 6006
6154 case PacketType.ObjectAdd: 6007 case PacketType.ObjectAdd:
6155 if (OnAddPrim != null) 6008 if (OnAddPrim != null)
6156 { 6009 {
@@ -6180,7 +6033,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6180 handlerAddPrim(AgentId, ActiveGroupId, addPacket.ObjectData.RayEnd, addPacket.ObjectData.Rotation, shape, addPacket.ObjectData.BypassRaycast, addPacket.ObjectData.RayStart, addPacket.ObjectData.RayTargetID, addPacket.ObjectData.RayEndIsIntersection); 6033 handlerAddPrim(AgentId, ActiveGroupId, addPacket.ObjectData.RayEnd, addPacket.ObjectData.Rotation, shape, addPacket.ObjectData.BypassRaycast, addPacket.ObjectData.RayStart, addPacket.ObjectData.RayTargetID, addPacket.ObjectData.RayEndIsIntersection);
6181 } 6034 }
6182 break; 6035 break;
6183 6036
6184 case PacketType.ObjectShape: 6037 case PacketType.ObjectShape:
6185 ObjectShapePacket shapePacket = (ObjectShapePacket)Pack; 6038 ObjectShapePacket shapePacket = (ObjectShapePacket)Pack;
6186 6039
@@ -6225,7 +6078,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6225 } 6078 }
6226 } 6079 }
6227 break; 6080 break;
6228 6081
6229 case PacketType.ObjectExtraParams: 6082 case PacketType.ObjectExtraParams:
6230 ObjectExtraParamsPacket extraPar = (ObjectExtraParamsPacket)Pack; 6083 ObjectExtraParamsPacket extraPar = (ObjectExtraParamsPacket)Pack;
6231 6084
@@ -6241,7 +6094,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6241 ObjectExtraParams handlerUpdateExtraParams = OnUpdateExtraParams; 6094 ObjectExtraParams handlerUpdateExtraParams = OnUpdateExtraParams;
6242 if (handlerUpdateExtraParams != null) 6095 if (handlerUpdateExtraParams != null)
6243 { 6096 {
6244 for (int i = 0 ; i < extraPar.ObjectData.Length ; i++) 6097 for (int i = 0; i < extraPar.ObjectData.Length; i++)
6245 { 6098 {
6246 handlerUpdateExtraParams(m_agentId, extraPar.ObjectData[i].ObjectLocalID, 6099 handlerUpdateExtraParams(m_agentId, extraPar.ObjectData[i].ObjectLocalID,
6247 extraPar.ObjectData[i].ParamType, 6100 extraPar.ObjectData[i].ParamType,
@@ -6642,7 +6495,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6642 break; 6495 break;
6643 case PacketType.ObjectName: 6496 case PacketType.ObjectName:
6644 ObjectNamePacket objName = (ObjectNamePacket)Pack; 6497 ObjectNamePacket objName = (ObjectNamePacket)Pack;
6645 6498
6646 #region Packet Session and User Check 6499 #region Packet Session and User Check
6647 if (m_checkPackets) 6500 if (m_checkPackets)
6648 { 6501 {
@@ -6651,7 +6504,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6651 break; 6504 break;
6652 } 6505 }
6653 #endregion 6506 #endregion
6654 6507
6655 GenericCall7 handlerObjectName = null; 6508 GenericCall7 handlerObjectName = null;
6656 for (int i = 0; i < objName.ObjectData.Length; i++) 6509 for (int i = 0; i < objName.ObjectData.Length; i++)
6657 { 6510 {
@@ -6884,14 +6737,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6884 } 6737 }
6885 break; 6738 break;
6886 6739
6887 #endregion 6740 #endregion
6888 6741
6889 #region Inventory/Asset/Other related packets 6742 #region Inventory/Asset/Other related packets
6890 6743
6891 case PacketType.RequestImage: 6744 case PacketType.RequestImage:
6892 RequestImagePacket imageRequest = (RequestImagePacket)Pack; 6745 RequestImagePacket imageRequest = (RequestImagePacket)Pack;
6893 //m_log.Debug("image request: " + Pack.ToString()); 6746 //m_log.Debug("image request: " + Pack.ToString());
6894 6747
6895 #region Packet Session and User Check 6748 #region Packet Session and User Check
6896 if (m_checkPackets) 6749 if (m_checkPackets)
6897 { 6750 {
@@ -6915,7 +6768,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6915 //handlerTextureRequest = OnRequestTexture; 6768 //handlerTextureRequest = OnRequestTexture;
6916 6769
6917 //if (handlerTextureRequest != null) 6770 //if (handlerTextureRequest != null)
6918 //OnRequestTexture(this, args); 6771 //OnRequestTexture(this, args);
6919 6772
6920 // in the end, we null this, so we have to check if it's null 6773 // in the end, we null this, so we have to check if it's null
6921 if (m_imageManager != null) 6774 if (m_imageManager != null)
@@ -6961,7 +6814,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6961 if (ti.OwnerID != AgentId) 6814 if (ti.OwnerID != AgentId)
6962 break; 6815 break;
6963 6816
6964 if ((ti.CurrentPermissions & ((uint)PermissionMask.Modify| (uint)PermissionMask.Copy | (uint)PermissionMask.Transfer)) != ((uint)PermissionMask.Modify| (uint)PermissionMask.Copy | (uint)PermissionMask.Transfer)) 6817 if ((ti.CurrentPermissions & ((uint)PermissionMask.Modify | (uint)PermissionMask.Copy | (uint)PermissionMask.Transfer)) != ((uint)PermissionMask.Modify | (uint)PermissionMask.Copy | (uint)PermissionMask.Transfer))
6965 break; 6818 break;
6966 6819
6967 if (ti.AssetID != requestID) 6820 if (ti.AssetID != requestID)
@@ -7019,7 +6872,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
7019 case PacketType.AssetUploadRequest: 6872 case PacketType.AssetUploadRequest:
7020 AssetUploadRequestPacket request = (AssetUploadRequestPacket)Pack; 6873 AssetUploadRequestPacket request = (AssetUploadRequestPacket)Pack;
7021 6874
7022 6875
7023 // m_log.Debug("upload request " + request.ToString()); 6876 // m_log.Debug("upload request " + request.ToString());
7024 // m_log.Debug("upload request was for assetid: " + request.AssetBlock.TransactionID.Combine(this.SecureSessionId).ToString()); 6877 // m_log.Debug("upload request was for assetid: " + request.AssetBlock.TransactionID.Combine(this.SecureSessionId).ToString());
7025 UUID temp = UUID.Combine(request.AssetBlock.TransactionID, SecureSessionId); 6878 UUID temp = UUID.Combine(request.AssetBlock.TransactionID, SecureSessionId);
@@ -7036,7 +6889,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
7036 break; 6889 break;
7037 case PacketType.RequestXfer: 6890 case PacketType.RequestXfer:
7038 RequestXferPacket xferReq = (RequestXferPacket)Pack; 6891 RequestXferPacket xferReq = (RequestXferPacket)Pack;
7039 6892
7040 RequestXfer handlerRequestXfer = OnRequestXfer; 6893 RequestXfer handlerRequestXfer = OnRequestXfer;
7041 6894
7042 if (handlerRequestXfer != null) 6895 if (handlerRequestXfer != null)
@@ -7055,7 +6908,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
7055 break; 6908 break;
7056 case PacketType.ConfirmXferPacket: 6909 case PacketType.ConfirmXferPacket:
7057 ConfirmXferPacketPacket confirmXfer = (ConfirmXferPacketPacket)Pack; 6910 ConfirmXferPacketPacket confirmXfer = (ConfirmXferPacketPacket)Pack;
7058 6911
7059 ConfirmXfer handlerConfirmXfer = OnConfirmXfer; 6912 ConfirmXfer handlerConfirmXfer = OnConfirmXfer;
7060 if (handlerConfirmXfer != null) 6913 if (handlerConfirmXfer != null)
7061 { 6914 {
@@ -7150,7 +7003,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
7150 break; 7003 break;
7151 case PacketType.CreateInventoryItem: 7004 case PacketType.CreateInventoryItem:
7152 CreateInventoryItemPacket createItem = (CreateInventoryItemPacket)Pack; 7005 CreateInventoryItemPacket createItem = (CreateInventoryItemPacket)Pack;
7153 7006
7154 #region Packet Session and User Check 7007 #region Packet Session and User Check
7155 if (m_checkPackets) 7008 if (m_checkPackets)
7156 { 7009 {
@@ -7243,7 +7096,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
7243 break; 7096 break;
7244 case PacketType.UpdateInventoryItem: 7097 case PacketType.UpdateInventoryItem:
7245 UpdateInventoryItemPacket inventoryItemUpdate = (UpdateInventoryItemPacket)Pack; 7098 UpdateInventoryItemPacket inventoryItemUpdate = (UpdateInventoryItemPacket)Pack;
7246 7099
7247 #region Packet Session and User Check 7100 #region Packet Session and User Check
7248 if (m_checkPackets) 7101 if (m_checkPackets)
7249 { 7102 {
@@ -7735,7 +7588,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
7735 } 7588 }
7736 break; 7589 break;
7737 7590
7738 #endregion 7591 #endregion
7739 7592
7740 case PacketType.UUIDNameRequest: 7593 case PacketType.UUIDNameRequest:
7741 UUIDNameRequestPacket incoming = (UUIDNameRequestPacket)Pack; 7594 UUIDNameRequestPacket incoming = (UUIDNameRequestPacket)Pack;
@@ -7750,7 +7603,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
7750 } 7603 }
7751 break; 7604 break;
7752 7605
7753 #region Parcel related packets 7606 #region Parcel related packets
7754 7607
7755 case PacketType.RegionHandleRequest: 7608 case PacketType.RegionHandleRequest:
7756 RegionHandleRequestPacket rhrPack = (RegionHandleRequestPacket)Pack; 7609 RegionHandleRequestPacket rhrPack = (RegionHandleRequestPacket)Pack;
@@ -8131,9 +7984,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
8131 } 7984 }
8132 break; 7985 break;
8133 7986
8134 #endregion 7987 #endregion
8135 7988
8136 #region Estate Packets 7989 #region Estate Packets
8137 7990
8138 case PacketType.EstateOwnerMessage: 7991 case PacketType.EstateOwnerMessage:
8139 EstateOwnerMessagePacket messagePacket = (EstateOwnerMessagePacket)Pack; 7992 EstateOwnerMessagePacket messagePacket = (EstateOwnerMessagePacket)Pack;
@@ -8167,21 +8020,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP
8167 convertParamStringToBool(messagePacket.ParamList[7].Parameter), convertParamStringToBool(messagePacket.ParamList[8].Parameter)); 8020 convertParamStringToBool(messagePacket.ParamList[7].Parameter), convertParamStringToBool(messagePacket.ParamList[8].Parameter));
8168 } 8021 }
8169 break; 8022 break;
8170// case "texturebase": 8023 // case "texturebase":
8171// if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) 8024 // if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false))
8172// { 8025 // {
8173// foreach (EstateOwnerMessagePacket.ParamListBlock block in messagePacket.ParamList) 8026 // foreach (EstateOwnerMessagePacket.ParamListBlock block in messagePacket.ParamList)
8174// { 8027 // {
8175// string s = Utils.BytesToString(block.Parameter); 8028 // string s = Utils.BytesToString(block.Parameter);
8176// string[] splitField = s.Split(' '); 8029 // string[] splitField = s.Split(' ');
8177// if (splitField.Length == 2) 8030 // if (splitField.Length == 2)
8178// { 8031 // {
8179// UUID tempUUID = new UUID(splitField[1]); 8032 // UUID tempUUID = new UUID(splitField[1]);
8180// OnSetEstateTerrainBaseTexture(this, Convert.ToInt16(splitField[0]), tempUUID); 8033 // OnSetEstateTerrainBaseTexture(this, Convert.ToInt16(splitField[0]), tempUUID);
8181// } 8034 // }
8182// } 8035 // }
8183// } 8036 // }
8184// break; 8037 // break;
8185 case "texturedetail": 8038 case "texturedetail":
8186 if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) 8039 if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false))
8187 { 8040 {
@@ -8423,7 +8276,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
8423 m_log.Error("EstateOwnerMessage: Unknown method requested\n" + messagePacket); 8276 m_log.Error("EstateOwnerMessage: Unknown method requested\n" + messagePacket);
8424 break; 8277 break;
8425 } 8278 }
8426 8279
8427 //int parcelID, uint reportType, uint requestflags, string filter 8280 //int parcelID, uint reportType, uint requestflags, string filter
8428 8281
8429 //lsrp.RequestData.ParcelLocalID; 8282 //lsrp.RequestData.ParcelLocalID;
@@ -8463,9 +8316,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
8463 } 8316 }
8464 break; 8317 break;
8465 8318
8466 #endregion 8319 #endregion
8467 8320
8468 #region GodPackets 8321 #region GodPackets
8469 8322
8470 case PacketType.RequestGodlikePowers: 8323 case PacketType.RequestGodlikePowers:
8471 RequestGodlikePowersPacket rglpPack = (RequestGodlikePowersPacket)Pack; 8324 RequestGodlikePowersPacket rglpPack = (RequestGodlikePowersPacket)Pack;
@@ -8511,9 +8364,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
8511 //OutPacket(kupack, ThrottleOutPacketType.Task); 8364 //OutPacket(kupack, ThrottleOutPacketType.Task);
8512 break; 8365 break;
8513 8366
8514 #endregion 8367 #endregion
8515 8368
8516 #region Economy/Transaction Packets 8369 #region Economy/Transaction Packets
8517 8370
8518 case PacketType.MoneyBalanceRequest: 8371 case PacketType.MoneyBalanceRequest:
8519 MoneyBalanceRequestPacket moneybalancerequestpacket = (MoneyBalanceRequestPacket)Pack; 8372 MoneyBalanceRequestPacket moneybalancerequestpacket = (MoneyBalanceRequestPacket)Pack;
@@ -8537,7 +8390,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
8537 break; 8390 break;
8538 case PacketType.EconomyDataRequest: 8391 case PacketType.EconomyDataRequest:
8539 8392
8540 8393
8541 EconomyDataRequest handlerEconomoyDataRequest = OnEconomyDataRequest; 8394 EconomyDataRequest handlerEconomoyDataRequest = OnEconomyDataRequest;
8542 if (handlerEconomoyDataRequest != null) 8395 if (handlerEconomoyDataRequest != null)
8543 { 8396 {
@@ -8613,9 +8466,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
8613 } 8466 }
8614 break; 8467 break;
8615 8468
8616 #endregion 8469 #endregion
8617 8470
8618 #region Script Packets 8471 #region Script Packets
8619 8472
8620 case PacketType.GetScriptRunning: 8473 case PacketType.GetScriptRunning:
8621 GetScriptRunningPacket scriptRunning = (GetScriptRunningPacket)Pack; 8474 GetScriptRunningPacket scriptRunning = (GetScriptRunningPacket)Pack;
@@ -8665,9 +8518,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
8665 } 8518 }
8666 break; 8519 break;
8667 8520
8668 #endregion 8521 #endregion
8669 8522
8670 #region Gesture Managment 8523 #region Gesture Managment
8671 8524
8672 case PacketType.ActivateGestures: 8525 case PacketType.ActivateGestures:
8673 ActivateGesturesPacket activateGesturePacket = (ActivateGesturesPacket)Pack; 8526 ActivateGesturesPacket activateGesturePacket = (ActivateGesturesPacket)Pack;
@@ -8734,21 +8587,23 @@ namespace OpenSim.Region.ClientStack.LindenUDP
8734 } 8587 }
8735 break; 8588 break;
8736 8589
8737 #endregion 8590 #endregion
8738
8739 8591
8740 #region unimplemented handlers 8592 case PacketType.AgentFOV:
8593 AgentFOVPacket fovPacket = (AgentFOVPacket)Pack;
8741 8594
8742 case PacketType.StartPingCheck: 8595 if (fovPacket.FOVBlock.GenCounter > m_agentFOVCounter)
8743 StartPingCheckPacket pingStart = (StartPingCheckPacket)Pack; 8596 {
8744 CompletePingCheckPacket pingComplete = new CompletePingCheckPacket(); 8597 m_agentFOVCounter = fovPacket.FOVBlock.GenCounter;
8745 pingComplete.PingID.PingID = pingStart.PingID.PingID; 8598 AgentFOV handlerAgentFOV = OnAgentFOV;
8746 m_udpServer.SendPacket(m_udpClient, pingComplete, ThrottleOutPacketType.Unknown, false); 8599 if (handlerAgentFOV != null)
8600 {
8601 handlerAgentFOV(this, fovPacket.FOVBlock.VerticalAngle);
8602 }
8603 }
8747 break; 8604 break;
8748 8605
8749 case PacketType.CompletePingCheck: 8606 #region unimplemented handlers
8750 // TODO: Do stats tracking or something with these?
8751 break;
8752 8607
8753 case PacketType.ViewerStats: 8608 case PacketType.ViewerStats:
8754 // TODO: handle this packet 8609 // TODO: handle this packet
@@ -8771,8 +8626,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
8771 MapItemRequest handlerMapItemRequest = OnMapItemRequest; 8626 MapItemRequest handlerMapItemRequest = OnMapItemRequest;
8772 if (handlerMapItemRequest != null) 8627 if (handlerMapItemRequest != null)
8773 { 8628 {
8774 handlerMapItemRequest(this,mirpk.AgentData.Flags, mirpk.AgentData.EstateID, 8629 handlerMapItemRequest(this, mirpk.AgentData.Flags, mirpk.AgentData.EstateID,
8775 mirpk.AgentData.Godlike,mirpk.RequestData.ItemType, 8630 mirpk.AgentData.Godlike, mirpk.RequestData.ItemType,
8776 mirpk.RequestData.RegionHandle); 8631 mirpk.RequestData.RegionHandle);
8777 8632
8778 } 8633 }
@@ -9080,7 +8935,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
9080 new GroupTitlesReplyPacket.GroupDataBlock(); 8935 new GroupTitlesReplyPacket.GroupDataBlock();
9081 8936
9082 groupTitlesReply.GroupData[i].Title = 8937 groupTitlesReply.GroupData[i].Title =
9083 Utils.StringToBytes(d.Name); 8938 Util.StringToBytes256(d.Name);
9084 groupTitlesReply.GroupData[i].RoleID = 8939 groupTitlesReply.GroupData[i].RoleID =
9085 d.UUID; 8940 d.UUID;
9086 groupTitlesReply.GroupData[i].Selected = 8941 groupTitlesReply.GroupData[i].Selected =
@@ -9117,10 +8972,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
9117 groupProfileRequest.GroupData.GroupID); 8972 groupProfileRequest.GroupData.GroupID);
9118 8973
9119 groupProfileReply.GroupData.GroupID = d.GroupID; 8974 groupProfileReply.GroupData.GroupID = d.GroupID;
9120 groupProfileReply.GroupData.Name = Utils.StringToBytes(d.Name); 8975 groupProfileReply.GroupData.Name = Util.StringToBytes256(d.Name);
9121 groupProfileReply.GroupData.Charter = Utils.StringToBytes(d.Charter); 8976 groupProfileReply.GroupData.Charter = Util.StringToBytes1024(d.Charter);
9122 groupProfileReply.GroupData.ShowInList = d.ShowInList; 8977 groupProfileReply.GroupData.ShowInList = d.ShowInList;
9123 groupProfileReply.GroupData.MemberTitle = Utils.StringToBytes(d.MemberTitle); 8978 groupProfileReply.GroupData.MemberTitle = Util.StringToBytes256(d.MemberTitle);
9124 groupProfileReply.GroupData.PowersMask = d.PowersMask; 8979 groupProfileReply.GroupData.PowersMask = d.PowersMask;
9125 groupProfileReply.GroupData.InsigniaID = d.InsigniaID; 8980 groupProfileReply.GroupData.InsigniaID = d.InsigniaID;
9126 groupProfileReply.GroupData.FounderID = d.FounderID; 8981 groupProfileReply.GroupData.FounderID = d.FounderID;
@@ -9180,7 +9035,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
9180 groupMembersRequestPacket.GroupData.RequestID; 9035 groupMembersRequestPacket.GroupData.RequestID;
9181 groupMembersReply.GroupData.MemberCount = memberCount; 9036 groupMembersReply.GroupData.MemberCount = memberCount;
9182 9037
9183 for (int i = 0 ; i < blockCount ; i++) 9038 for (int i = 0; i < blockCount; i++)
9184 { 9039 {
9185 GroupMembersData m = members[0]; 9040 GroupMembersData m = members[0];
9186 members.RemoveAt(0); 9041 members.RemoveAt(0);
@@ -9192,11 +9047,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
9192 groupMembersReply.MemberData[i].Contribution = 9047 groupMembersReply.MemberData[i].Contribution =
9193 m.Contribution; 9048 m.Contribution;
9194 groupMembersReply.MemberData[i].OnlineStatus = 9049 groupMembersReply.MemberData[i].OnlineStatus =
9195 Utils.StringToBytes(m.OnlineStatus); 9050 Util.StringToBytes256(m.OnlineStatus);
9196 groupMembersReply.MemberData[i].AgentPowers = 9051 groupMembersReply.MemberData[i].AgentPowers =
9197 m.AgentPowers; 9052 m.AgentPowers;
9198 groupMembersReply.MemberData[i].Title = 9053 groupMembersReply.MemberData[i].Title =
9199 Utils.StringToBytes(m.Title); 9054 Util.StringToBytes256(m.Title);
9200 groupMembersReply.MemberData[i].IsOwner = 9055 groupMembersReply.MemberData[i].IsOwner =
9201 m.IsOwner; 9056 m.IsOwner;
9202 } 9057 }
@@ -9257,11 +9112,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
9257 groupRolesReply.RoleData[i].RoleID = 9112 groupRolesReply.RoleData[i].RoleID =
9258 d.RoleID; 9113 d.RoleID;
9259 groupRolesReply.RoleData[i].Name = 9114 groupRolesReply.RoleData[i].Name =
9260 Utils.StringToBytes(d.Name); 9115 Util.StringToBytes256(d.Name);
9261 groupRolesReply.RoleData[i].Title = 9116 groupRolesReply.RoleData[i].Title =
9262 Utils.StringToBytes(d.Title); 9117 Util.StringToBytes256(d.Title);
9263 groupRolesReply.RoleData[i].Description = 9118 groupRolesReply.RoleData[i].Description =
9264 Utils.StringToBytes(d.Description); 9119 Util.StringToBytes1024(d.Description);
9265 groupRolesReply.RoleData[i].Powers = 9120 groupRolesReply.RoleData[i].Powers =
9266 d.Powers; 9121 d.Powers;
9267 groupRolesReply.RoleData[i].Members = 9122 groupRolesReply.RoleData[i].Members =
@@ -9317,7 +9172,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
9317 groupRoleMembersReply.MemberData = 9172 groupRoleMembersReply.MemberData =
9318 new GroupRoleMembersReplyPacket.MemberDataBlock[pairs]; 9173 new GroupRoleMembersReplyPacket.MemberDataBlock[pairs];
9319 9174
9320 for (int i = 0 ; i < pairs ; i++) 9175 for (int i = 0; i < pairs; i++)
9321 { 9176 {
9322 GroupRoleMembersData d = mappings[0]; 9177 GroupRoleMembersData d = mappings[0];
9323 mappings.RemoveAt(0); 9178 mappings.RemoveAt(0);
@@ -9444,7 +9299,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
9444 ParcelDeedToGroup handlerParcelDeedToGroup = OnParcelDeedToGroup; 9299 ParcelDeedToGroup handlerParcelDeedToGroup = OnParcelDeedToGroup;
9445 if (handlerParcelDeedToGroup != null) 9300 if (handlerParcelDeedToGroup != null)
9446 { 9301 {
9447 handlerParcelDeedToGroup(parcelDeedToGroup.Data.LocalID, parcelDeedToGroup.Data.GroupID,this); 9302 handlerParcelDeedToGroup(parcelDeedToGroup.Data.LocalID, parcelDeedToGroup.Data.GroupID, this);
9448 9303
9449 } 9304 }
9450 } 9305 }
@@ -9488,9 +9343,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
9488 groupNoticesListReply.Data[i].Timestamp = 9343 groupNoticesListReply.Data[i].Timestamp =
9489 g.Timestamp; 9344 g.Timestamp;
9490 groupNoticesListReply.Data[i].FromName = 9345 groupNoticesListReply.Data[i].FromName =
9491 Utils.StringToBytes(g.FromName); 9346 Util.StringToBytes256(g.FromName);
9492 groupNoticesListReply.Data[i].Subject = 9347 groupNoticesListReply.Data[i].Subject =
9493 Utils.StringToBytes(g.Subject); 9348 Util.StringToBytes256(g.Subject);
9494 groupNoticesListReply.Data[i].HasAttachment = 9349 groupNoticesListReply.Data[i].HasAttachment =
9495 g.HasAttachment; 9350 g.HasAttachment;
9496 groupNoticesListReply.Data[i].AssetType = 9351 groupNoticesListReply.Data[i].AssetType =
@@ -9902,7 +9757,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
9902 9757
9903 PickDelete handlerPickDelete = OnPickDelete; 9758 PickDelete handlerPickDelete = OnPickDelete;
9904 if (handlerPickDelete != null) 9759 if (handlerPickDelete != null)
9905 handlerPickDelete(this, pickDelete.Data.PickID); 9760 handlerPickDelete(this, pickDelete.Data.PickID);
9906 break; 9761 break;
9907 case PacketType.PickGodDelete: 9762 case PacketType.PickGodDelete:
9908 PickGodDeletePacket pickGodDelete = 9763 PickGodDeletePacket pickGodDelete =
@@ -9922,7 +9777,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
9922 handlerPickGodDelete(this, 9777 handlerPickGodDelete(this,
9923 pickGodDelete.AgentData.AgentID, 9778 pickGodDelete.AgentData.AgentID,
9924 pickGodDelete.Data.PickID, 9779 pickGodDelete.Data.PickID,
9925 pickGodDelete.Data.QueryID); 9780 pickGodDelete.Data.QueryID);
9926 break; 9781 break;
9927 case PacketType.PickInfoUpdate: 9782 case PacketType.PickInfoUpdate:
9928 PickInfoUpdatePacket pickInfoUpdate = 9783 PickInfoUpdatePacket pickInfoUpdate =
@@ -10013,7 +9868,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
10013 m_log.Warn("[CLIENT]: unhandled packet " + Pack); 9868 m_log.Warn("[CLIENT]: unhandled packet " + Pack);
10014 break; 9869 break;
10015 9870
10016 #endregion 9871 #endregion
10017 } 9872 }
10018 9873
10019 PacketPool.Instance.ReturnPacket(Pack); 9874 PacketPool.Instance.ReturnPacket(Pack);
@@ -10050,7 +9905,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
10050 //shape.Textures = ntex; 9905 //shape.Textures = ntex;
10051 return shape; 9906 return shape;
10052 } 9907 }
10053 9908
10054 public ClientInfo GetClientInfo() 9909 public ClientInfo GetClientInfo()
10055 { 9910 {
10056 ClientInfo info = m_udpClient.GetClientInfo(); 9911 ClientInfo info = m_udpClient.GetClientInfo();
@@ -10078,7 +9933,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
10078 { 9933 {
10079 ParcelMediaCommandMessagePacket commandMessagePacket = new ParcelMediaCommandMessagePacket(); 9934 ParcelMediaCommandMessagePacket commandMessagePacket = new ParcelMediaCommandMessagePacket();
10080 commandMessagePacket.CommandBlock.Flags = flags; 9935 commandMessagePacket.CommandBlock.Flags = flags;
10081 commandMessagePacket.CommandBlock.Command =(uint) command; 9936 commandMessagePacket.CommandBlock.Command = (uint)command;
10082 commandMessagePacket.CommandBlock.Time = time; 9937 commandMessagePacket.CommandBlock.Time = time;
10083 9938
10084 OutPacket(commandMessagePacket, ThrottleOutPacketType.Unknown); 9939 OutPacket(commandMessagePacket, ThrottleOutPacketType.Unknown);
@@ -10089,12 +9944,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
10089 byte mediaLoop) 9944 byte mediaLoop)
10090 { 9945 {
10091 ParcelMediaUpdatePacket updatePacket = new ParcelMediaUpdatePacket(); 9946 ParcelMediaUpdatePacket updatePacket = new ParcelMediaUpdatePacket();
10092 updatePacket.DataBlock.MediaURL = Utils.StringToBytes(mediaUrl); 9947 updatePacket.DataBlock.MediaURL = Util.StringToBytes256(mediaUrl);
10093 updatePacket.DataBlock.MediaID = mediaTextureID; 9948 updatePacket.DataBlock.MediaID = mediaTextureID;
10094 updatePacket.DataBlock.MediaAutoScale = autoScale; 9949 updatePacket.DataBlock.MediaAutoScale = autoScale;
10095 9950
10096 updatePacket.DataBlockExtended.MediaType = Utils.StringToBytes(mediaType); 9951 updatePacket.DataBlockExtended.MediaType = Util.StringToBytes256(mediaType);
10097 updatePacket.DataBlockExtended.MediaDesc = Utils.StringToBytes(mediaDesc); 9952 updatePacket.DataBlockExtended.MediaDesc = Util.StringToBytes256(mediaDesc);
10098 updatePacket.DataBlockExtended.MediaWidth = mediaWidth; 9953 updatePacket.DataBlockExtended.MediaWidth = mediaWidth;
10099 updatePacket.DataBlockExtended.MediaHeight = mediaHeight; 9954 updatePacket.DataBlockExtended.MediaHeight = mediaHeight;
10100 updatePacket.DataBlockExtended.MediaLoop = mediaLoop; 9955 updatePacket.DataBlockExtended.MediaLoop = mediaLoop;
@@ -10106,7 +9961,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
10106 9961
10107 #region Camera 9962 #region Camera
10108 9963
10109 public void SendSetFollowCamProperties (UUID objectID, SortedDictionary<int, float> parameters) 9964 public void SendSetFollowCamProperties(UUID objectID, SortedDictionary<int, float> parameters)
10110 { 9965 {
10111 SetFollowCamPropertiesPacket packet = (SetFollowCamPropertiesPacket)PacketPool.Instance.GetPacket(PacketType.SetFollowCamProperties); 9966 SetFollowCamPropertiesPacket packet = (SetFollowCamPropertiesPacket)PacketPool.Instance.GetPacket(PacketType.SetFollowCamProperties);
10112 packet.ObjectData.ObjectID = objectID; 9967 packet.ObjectData.ObjectID = objectID;
@@ -10124,7 +9979,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
10124 OutPacket(packet, ThrottleOutPacketType.Task); 9979 OutPacket(packet, ThrottleOutPacketType.Task);
10125 } 9980 }
10126 9981
10127 public void SendClearFollowCamProperties (UUID objectID) 9982 public void SendClearFollowCamProperties(UUID objectID)
10128 { 9983 {
10129 ClearFollowCamPropertiesPacket packet = (ClearFollowCamPropertiesPacket)PacketPool.Instance.GetPacket(PacketType.ClearFollowCamProperties); 9984 ClearFollowCamPropertiesPacket packet = (ClearFollowCamPropertiesPacket)PacketPool.Instance.GetPacket(PacketType.ClearFollowCamProperties);
10130 packet.ObjectData.ObjectID = objectID; 9985 packet.ObjectData.ObjectID = objectID;
@@ -10226,8 +10081,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
10226 { 10081 {
10227 return m_udpClient.GetStats(); 10082 return m_udpClient.GetStats();
10228 } 10083 }
10229 10084
10230 public string XReport(string uptime, string version) 10085 public string XReport(string uptime, string version)
10231 { 10086 {
10232 return String.Empty; 10087 return String.Empty;
10233 } 10088 }
@@ -10301,7 +10156,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
10301 } 10156 }
10302 10157
10303 //m_log.DebugFormat("[ASSET CACHE]: Asset transfer request for asset which is {0} already known to be missing. Dropping", requestID); 10158 //m_log.DebugFormat("[ASSET CACHE]: Asset transfer request for asset which is {0} already known to be missing. Dropping", requestID);
10304 10159
10305 // FIXME: We never tell the client about assets which do not exist when requested by this transfer mechanism, which can't be right. 10160 // FIXME: We never tell the client about assets which do not exist when requested by this transfer mechanism, which can't be right.
10306 return; 10161 return;
10307 } 10162 }
@@ -10371,5 +10226,167 @@ namespace OpenSim.Region.ClientStack.LindenUDP
10371 pack.TextureData.TextureID = textureID; 10226 pack.TextureData.TextureID = textureID;
10372 OutPacket(pack, ThrottleOutPacketType.Task); 10227 OutPacket(pack, ThrottleOutPacketType.Task);
10373 } 10228 }
10229
10230 #region PriorityQueue
10231 private class PriorityQueue<TPriority, TValue>
10232 {
10233 internal delegate bool UpdatePriorityHandler(ref TPriority priority, uint local_id);
10234
10235 private MinHeap<MinHeapItem>[] m_heaps = new MinHeap<MinHeapItem>[1];
10236 private Dictionary<uint, LookupItem> m_lookupTable;
10237 private Comparison<TPriority> m_comparison;
10238 private object m_syncRoot = new object();
10239
10240 internal PriorityQueue() :
10241 this(MinHeap<MinHeapItem>.DEFAULT_CAPACITY, Comparer<TPriority>.Default) { }
10242 internal PriorityQueue(int capacity) :
10243 this(capacity, Comparer<TPriority>.Default) { }
10244 internal PriorityQueue(IComparer<TPriority> comparer) :
10245 this(new Comparison<TPriority>(comparer.Compare)) { }
10246 internal PriorityQueue(Comparison<TPriority> comparison) :
10247 this(MinHeap<MinHeapItem>.DEFAULT_CAPACITY, comparison) { }
10248 internal PriorityQueue(int capacity, IComparer<TPriority> comparer) :
10249 this(capacity, new Comparison<TPriority>(comparer.Compare)) { }
10250 internal PriorityQueue(int capacity, Comparison<TPriority> comparison)
10251 {
10252 m_lookupTable = new Dictionary<uint, LookupItem>(capacity);
10253
10254 for (int i = 0; i < m_heaps.Length; ++i)
10255 m_heaps[i] = new MinHeap<MinHeapItem>(capacity);
10256 this.m_comparison = comparison;
10257 }
10258
10259 internal object SyncRoot { get { return this.m_syncRoot; } }
10260 internal int Count
10261 {
10262 get
10263 {
10264 int count = 0;
10265 for (int i = 0; i < m_heaps.Length; ++i)
10266 count = m_heaps[i].Count;
10267 return count;
10268 }
10269 }
10270
10271 internal bool Enqueue(TPriority priority, TValue value, uint local_id)
10272 {
10273 LookupItem item;
10274
10275 if (m_lookupTable.TryGetValue(local_id, out item))
10276 {
10277 item.Heap[item.Handle] = new MinHeapItem(priority, value, local_id, this.m_comparison);
10278 return false;
10279 }
10280 else
10281 {
10282 item.Heap = m_heaps[0];
10283 item.Heap.Add(new MinHeapItem(priority, value, local_id, this.m_comparison), ref item.Handle);
10284 m_lookupTable.Add(local_id, item);
10285 return true;
10286 }
10287 }
10288
10289 internal TValue Peek()
10290 {
10291 for (int i = 0; i < m_heaps.Length; ++i)
10292 if (m_heaps[i].Count > 0)
10293 return m_heaps[i].Min().Value;
10294 throw new InvalidOperationException(string.Format("The {0} is empty", this.GetType().ToString()));
10295 }
10296
10297 internal TValue Dequeue()
10298 {
10299 for (int i = 0; i < m_heaps.Length; ++i)
10300 {
10301 if (m_heaps[i].Count > 0)
10302 {
10303 MinHeapItem item = m_heaps[i].RemoveMin();
10304 m_lookupTable.Remove(item.LocalID);
10305 return item.Value;
10306 }
10307 }
10308 throw new InvalidOperationException(string.Format("The {0} is empty", this.GetType().ToString()));
10309 }
10310
10311 internal void Reprioritize(UpdatePriorityHandler handler)
10312 {
10313 MinHeapItem item;
10314 TPriority priority;
10315
10316 foreach (LookupItem lookup in new List<LookupItem>(this.m_lookupTable.Values))
10317 {
10318 if (lookup.Heap.TryGetValue(lookup.Handle, out item))
10319 {
10320 priority = item.Priority;
10321 if (handler(ref priority, item.LocalID))
10322 {
10323 if (lookup.Heap.ContainsHandle(lookup.Handle))
10324 lookup.Heap[lookup.Handle] =
10325 new MinHeapItem(priority, item.Value, item.LocalID, this.m_comparison);
10326 }
10327 else
10328 {
10329 m_log.Warn("[LLCLIENTVIEW]: UpdatePriorityHandler returned false, dropping update");
10330 lookup.Heap.Remove(lookup.Handle);
10331 this.m_lookupTable.Remove(item.LocalID);
10332 }
10333 }
10334 }
10335 }
10336
10337 #region MinHeapItem
10338 private struct MinHeapItem : IComparable<MinHeapItem>
10339 {
10340 private TPriority priority;
10341 private TValue value;
10342 private uint local_id;
10343 private Comparison<TPriority> comparison;
10344
10345 internal MinHeapItem(TPriority priority, TValue value, uint local_id) :
10346 this(priority, value, local_id, Comparer<TPriority>.Default) { }
10347 internal MinHeapItem(TPriority priority, TValue value, uint local_id, IComparer<TPriority> comparer) :
10348 this(priority, value, local_id, new Comparison<TPriority>(comparer.Compare)) { }
10349 internal MinHeapItem(TPriority priority, TValue value, uint local_id, Comparison<TPriority> comparison)
10350 {
10351 this.priority = priority;
10352 this.value = value;
10353 this.local_id = local_id;
10354 this.comparison = comparison;
10355 }
10356
10357 internal TPriority Priority { get { return this.priority; } }
10358 internal TValue Value { get { return this.value; } }
10359 internal uint LocalID { get { return this.local_id; } }
10360
10361 public override string ToString()
10362 {
10363 StringBuilder sb = new StringBuilder();
10364 sb.Append("[");
10365 if (this.priority != null)
10366 sb.Append(this.priority.ToString());
10367 sb.Append(",");
10368 if (this.value != null)
10369 sb.Append(this.value.ToString());
10370 sb.Append("]");
10371 return sb.ToString();
10372 }
10373
10374 public int CompareTo(MinHeapItem other)
10375 {
10376 return this.comparison(this.priority, other.priority);
10377 }
10378 }
10379 #endregion
10380
10381 #region LookupItem
10382 private struct LookupItem
10383 {
10384 internal MinHeap<MinHeapItem> Heap;
10385 internal IHandle Handle;
10386 }
10387 #endregion
10388 }
10389 #endregion
10390
10374 } 10391 }
10375} 10392}
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLImageManager.cs b/OpenSim/Region/ClientStack/LindenUDP/LLImageManager.cs
index d25bf95..938cf50 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLImageManager.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLImageManager.cs
@@ -51,7 +51,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
51 51
52 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 52 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
53 private bool m_shuttingdown; 53 private bool m_shuttingdown;
54 private long m_lastloopprocessed;
55 private AssetBase m_missingImage; 54 private AssetBase m_missingImage;
56 private LLClientView m_client; //Client we're assigned to 55 private LLClientView m_client; //Client we're assigned to
57 private IAssetService m_assetCache; //Asset Cache 56 private IAssetService m_assetCache; //Asset Cache
@@ -169,7 +168,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
169 168
170 public bool ProcessImageQueue(int packetsToSend) 169 public bool ProcessImageQueue(int packetsToSend)
171 { 170 {
172 m_lastloopprocessed = DateTime.Now.Ticks;
173 int packetsSent = 0; 171 int packetsSent = 0;
174 172
175 while (packetsSent < packetsToSend) 173 while (packetsSent < packetsToSend)
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs
index 4eee6b6..71f4c47 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs
@@ -33,6 +33,8 @@ using OpenSim.Framework;
33using OpenMetaverse; 33using OpenMetaverse;
34using OpenMetaverse.Packets; 34using OpenMetaverse.Packets;
35 35
36using TokenBucket = OpenSim.Region.ClientStack.LindenUDP.TokenBucket;
37
36namespace OpenSim.Region.ClientStack.LindenUDP 38namespace OpenSim.Region.ClientStack.LindenUDP
37{ 39{
38 #region Delegates 40 #region Delegates
@@ -98,12 +100,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
98 /// <summary>True when this connection is alive, otherwise false</summary> 100 /// <summary>True when this connection is alive, otherwise false</summary>
99 public bool IsConnected = true; 101 public bool IsConnected = true;
100 /// <summary>True when this connection is paused, otherwise false</summary> 102 /// <summary>True when this connection is paused, otherwise false</summary>
101 public bool IsPaused = true; 103 public bool IsPaused;
102 /// <summary>Environment.TickCount when the last packet was received for this client</summary> 104 /// <summary>Environment.TickCount when the last packet was received for this client</summary>
103 public int TickLastPacketReceived; 105 public int TickLastPacketReceived;
104 106
105 /// <summary>Timer granularity. This is set to the measured resolution of Environment.TickCount</summary>
106 public readonly float G;
107 /// <summary>Smoothed round-trip time. A smoothed average of the round-trip time for sending a 107 /// <summary>Smoothed round-trip time. A smoothed average of the round-trip time for sending a
108 /// reliable packet to the client and receiving an ACK</summary> 108 /// reliable packet to the client and receiving an ACK</summary>
109 public float SRTT; 109 public float SRTT;
@@ -163,26 +163,26 @@ namespace OpenSim.Region.ClientStack.LindenUDP
163 CircuitCode = circuitCode; 163 CircuitCode = circuitCode;
164 m_udpServer = server; 164 m_udpServer = server;
165 m_defaultThrottleRates = rates; 165 m_defaultThrottleRates = rates;
166 // Create a token bucket throttle for this client that has the scene token bucket as a parent
166 m_throttle = new TokenBucket(parentThrottle, rates.TotalLimit, rates.Total); 167 m_throttle = new TokenBucket(parentThrottle, rates.TotalLimit, rates.Total);
168 // Create an array of token buckets for this clients different throttle categories
167 m_throttleCategories = new TokenBucket[THROTTLE_CATEGORY_COUNT]; 169 m_throttleCategories = new TokenBucket[THROTTLE_CATEGORY_COUNT];
168 170
169 for (int i = 0; i < THROTTLE_CATEGORY_COUNT; i++) 171 for (int i = 0; i < THROTTLE_CATEGORY_COUNT; i++)
170 { 172 {
171 ThrottleOutPacketType type = (ThrottleOutPacketType)i; 173 ThrottleOutPacketType type = (ThrottleOutPacketType)i;
172 174
175 // Initialize the packet outboxes, where packets sit while they are waiting for tokens
173 m_packetOutboxes[i] = new OpenSim.Framework.LocklessQueue<OutgoingPacket>(); 176 m_packetOutboxes[i] = new OpenSim.Framework.LocklessQueue<OutgoingPacket>();
177 // Initialize the token buckets that control the throttling for each category
174 m_throttleCategories[i] = new TokenBucket(m_throttle, rates.GetLimit(type), rates.GetRate(type)); 178 m_throttleCategories[i] = new TokenBucket(m_throttle, rates.GetLimit(type), rates.GetRate(type));
175 } 179 }
176 180
177 // Set the granularity variable used for retransmission calculations to
178 // the measured resolution of Environment.TickCount
179 G = server.TickCountResolution;
180
181 // Default the retransmission timeout to three seconds 181 // Default the retransmission timeout to three seconds
182 RTO = 3000; 182 RTO = 3000;
183 183
184 // Initialize this to a sane value to prevent early disconnects 184 // Initialize this to a sane value to prevent early disconnects
185 TickLastPacketReceived = Environment.TickCount; 185 TickLastPacketReceived = Environment.TickCount & Int32.MaxValue;
186 } 186 }
187 187
188 /// <summary> 188 /// <summary>
@@ -191,7 +191,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
191 public void Shutdown() 191 public void Shutdown()
192 { 192 {
193 IsConnected = false; 193 IsConnected = false;
194 NeedAcks.Clear();
195 for (int i = 0; i < THROTTLE_CATEGORY_COUNT; i++) 194 for (int i = 0; i < THROTTLE_CATEGORY_COUNT; i++)
196 { 195 {
197 m_packetOutboxes[i].Clear(); 196 m_packetOutboxes[i].Clear();
@@ -293,36 +292,59 @@ namespace OpenSim.Region.ClientStack.LindenUDP
293 int state = (int)((float)task * STATE_TASK_PERCENTAGE); 292 int state = (int)((float)task * STATE_TASK_PERCENTAGE);
294 task -= state; 293 task -= state;
295 294
296 int ceiling = Int32.MaxValue; 295 // Make sure none of the throttles are set below our packet MTU,
297 if (m_defaultThrottleRates.Total != 0) 296 // otherwise a throttle could become permanently clogged
298 { 297 resend = Math.Max(resend, LLUDPServer.MTU);
299 ceiling = m_defaultThrottleRates.Total; 298 land = Math.Max(land, LLUDPServer.MTU);
300 if (ceiling < Packet.MTU) ceiling = Packet.MTU; 299 wind = Math.Max(wind, LLUDPServer.MTU);
301 } 300 cloud = Math.Max(cloud, LLUDPServer.MTU);
302 301 task = Math.Max(task, LLUDPServer.MTU);
303 resend = Utils.Clamp(resend, Packet.MTU, ceiling); 302 texture = Math.Max(texture, LLUDPServer.MTU);
304 land = Utils.Clamp(land, Packet.MTU, ceiling); 303 asset = Math.Max(asset, LLUDPServer.MTU);
305 wind = Utils.Clamp(wind, Packet.MTU, ceiling); 304 state = Math.Max(state, LLUDPServer.MTU);
306 cloud = Utils.Clamp(cloud, Packet.MTU, ceiling);
307 task = Utils.Clamp(task, Packet.MTU, ceiling);
308 texture = Utils.Clamp(texture, Packet.MTU, ceiling);
309 asset = Utils.Clamp(asset, Packet.MTU, ceiling);
310 state = Utils.Clamp(state, Packet.MTU, ceiling);
311 305
312 int total = resend + land + wind + cloud + task + texture + asset + state; 306 int total = resend + land + wind + cloud + task + texture + asset + state;
313 int taskTotal = task + state;
314 307
315 m_log.DebugFormat("[LLUDPCLIENT]: {0} is setting throttles. Resend={1}, Land={2}, Wind={3}, Cloud={4}, Task={5}, Texture={6}, Asset={7}, State={8}, Total={9}", 308 m_log.DebugFormat("[LLUDPCLIENT]: {0} is setting throttles. Resend={1}, Land={2}, Wind={3}, Cloud={4}, Task={5}, Texture={6}, Asset={7}, State={8}, Total={9}",
316 AgentID, resend, land, wind, cloud, task, texture, asset, state, total); 309 AgentID, resend, land, wind, cloud, task, texture, asset, state, total);
317 310
318 SetThrottle(ThrottleOutPacketType.Resend, resend, resend); 311 // Update the token buckets with new throttle values
319 SetThrottle(ThrottleOutPacketType.Land, land, land); 312 TokenBucket bucket;
320 SetThrottle(ThrottleOutPacketType.Wind, wind, wind); 313
321 SetThrottle(ThrottleOutPacketType.Cloud, cloud, cloud); 314 bucket = m_throttle;
322 SetThrottle(ThrottleOutPacketType.Task, task, taskTotal); 315 bucket.MaxBurst = total;
323 SetThrottle(ThrottleOutPacketType.Texture, texture, texture); 316
324 SetThrottle(ThrottleOutPacketType.Asset, asset, asset); 317 bucket = m_throttleCategories[(int)ThrottleOutPacketType.Resend];
325 SetThrottle(ThrottleOutPacketType.State, state, taskTotal); 318 bucket.DripRate = resend;
319 bucket.MaxBurst = resend;
320
321 bucket = m_throttleCategories[(int)ThrottleOutPacketType.Land];
322 bucket.DripRate = land;
323 bucket.MaxBurst = land;
324
325 bucket = m_throttleCategories[(int)ThrottleOutPacketType.Wind];
326 bucket.DripRate = wind;
327 bucket.MaxBurst = wind;
328
329 bucket = m_throttleCategories[(int)ThrottleOutPacketType.Cloud];
330 bucket.DripRate = cloud;
331 bucket.MaxBurst = cloud;
332
333 bucket = m_throttleCategories[(int)ThrottleOutPacketType.Asset];
334 bucket.DripRate = asset;
335 bucket.MaxBurst = asset;
336
337 bucket = m_throttleCategories[(int)ThrottleOutPacketType.Task];
338 bucket.DripRate = task + state;
339 bucket.MaxBurst = task + state;
340
341 bucket = m_throttleCategories[(int)ThrottleOutPacketType.State];
342 bucket.DripRate = state;
343 bucket.MaxBurst = state;
344
345 bucket = m_throttleCategories[(int)ThrottleOutPacketType.Texture];
346 bucket.DripRate = texture;
347 bucket.MaxBurst = texture;
326 } 348 }
327 349
328 public byte[] GetThrottlesPacked() 350 public byte[] GetThrottlesPacked()
@@ -342,17 +364,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
342 return data; 364 return data;
343 } 365 }
344 366
345 public void SetThrottle(ThrottleOutPacketType category, int rate, int maxBurst)
346 {
347 int i = (int)category;
348 if (i >= 0 && i < m_throttleCategories.Length)
349 {
350 TokenBucket bucket = m_throttleCategories[(int)category];
351 bucket.DripRate = rate;
352 bucket.MaxBurst = maxBurst;
353 }
354 }
355
356 public bool EnqueueOutgoing(OutgoingPacket packet) 367 public bool EnqueueOutgoing(OutgoingPacket packet)
357 { 368 {
358 int category = (int)packet.Category; 369 int category = (int)packet.Category;
@@ -395,9 +406,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
395 TokenBucket bucket; 406 TokenBucket bucket;
396 bool packetSent = false; 407 bool packetSent = false;
397 408
409 //string queueDebugOutput = String.Empty; // Serious debug business
410
398 for (int i = 0; i < THROTTLE_CATEGORY_COUNT; i++) 411 for (int i = 0; i < THROTTLE_CATEGORY_COUNT; i++)
399 { 412 {
400 bucket = m_throttleCategories[i]; 413 bucket = m_throttleCategories[i];
414 //queueDebugOutput += m_packetOutboxes[i].Count + " "; // Serious debug business
401 415
402 if (m_nextPackets[i] != null) 416 if (m_nextPackets[i] != null)
403 { 417 {
@@ -449,6 +463,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
449 } 463 }
450 } 464 }
451 465
466 //m_log.Info("[LLUDPCLIENT]: Queues: " + queueDebugOutput); // Serious debug business
452 return packetSent; 467 return packetSent;
453 } 468 }
454 469
@@ -479,8 +494,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
479 SRTT = (1.0f - ALPHA) * SRTT + ALPHA * r; 494 SRTT = (1.0f - ALPHA) * SRTT + ALPHA * r;
480 } 495 }
481 496
482 // Always round retransmission timeout up to two seconds 497 RTO = (int)(SRTT + Math.Max(m_udpServer.TickCountResolution, K * RTTVAR));
483 RTO = Math.Max(2000, (int)(SRTT + Math.Max(G, K * RTTVAR))); 498
499 // Clamp the retransmission timeout to manageable values
500 RTO = Utils.Clamp(RTO, 3000, 10000);
501
484 //m_log.Debug("[LLUDPCLIENT]: Setting agent " + this.Agent.FullName + "'s RTO to " + RTO + "ms with an RTTVAR of " + 502 //m_log.Debug("[LLUDPCLIENT]: Setting agent " + this.Agent.FullName + "'s RTO to " + RTO + "ms with an RTTVAR of " +
485 // RTTVAR + " based on new RTT of " + r + "ms"); 503 // RTTVAR + " based on new RTT of " + r + "ms");
486 } 504 }
@@ -493,8 +511,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP
493 /// for</param> 511 /// for</param>
494 private void BeginFireQueueEmpty(int throttleIndex) 512 private void BeginFireQueueEmpty(int throttleIndex)
495 { 513 {
496 if (!m_onQueueEmptyRunning[throttleIndex]) 514 // Unknown is -1 and Resend is 0. Make sure we are only firing the
497 Util.FireAndForget(FireQueueEmpty, throttleIndex); 515 // callback for categories other than those
516 if (throttleIndex > 0)
517 {
518 if (!m_onQueueEmptyRunning[throttleIndex])
519 {
520 m_onQueueEmptyRunning[throttleIndex] = true;
521 Util.FireAndForget(FireQueueEmpty, throttleIndex);
522 }
523 }
498 } 524 }
499 525
500 /// <summary> 526 /// <summary>
@@ -509,16 +535,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP
509 ThrottleOutPacketType type = (ThrottleOutPacketType)i; 535 ThrottleOutPacketType type = (ThrottleOutPacketType)i;
510 QueueEmpty callback = OnQueueEmpty; 536 QueueEmpty callback = OnQueueEmpty;
511 537
538 int start = Environment.TickCount;
539
512 if (callback != null) 540 if (callback != null)
513 { 541 {
514 if (!m_onQueueEmptyRunning[i]) 542 try { callback(type); }
515 { 543 catch (Exception e) { m_log.Error("[LLUDPCLIENT]: OnQueueEmpty(" + type + ") threw an exception: " + e.Message, e); }
516 m_onQueueEmptyRunning[i] = true;
517 try { callback(type); }
518 catch (Exception e) { m_log.Error("[LLUDPCLIENT]: OnQueueEmpty(" + type + ") threw an exception: " + e.Message, e); }
519 m_onQueueEmptyRunning[i] = false;
520 }
521 } 544 }
545
546 // Make sure all queue empty calls take at least a measurable amount of time,
547 // otherwise we'll peg a CPU trying to fire these too fast
548 if (Environment.TickCount == start)
549 System.Threading.Thread.Sleep((int)m_udpServer.TickCountResolution);
550
551 m_onQueueEmptyRunning[i] = false;
522 } 552 }
523 } 553 }
524} 554}
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
index 545a0bc..4bdf132 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
@@ -39,6 +39,8 @@ using OpenSim.Framework.Statistics;
39using OpenSim.Region.Framework.Scenes; 39using OpenSim.Region.Framework.Scenes;
40using OpenMetaverse; 40using OpenMetaverse;
41 41
42using TokenBucket = OpenSim.Region.ClientStack.LindenUDP.TokenBucket;
43
42namespace OpenSim.Region.ClientStack.LindenUDP 44namespace OpenSim.Region.ClientStack.LindenUDP
43{ 45{
44 /// <summary> 46 /// <summary>
@@ -89,8 +91,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
89 /// </summary> 91 /// </summary>
90 public class LLUDPServer : OpenSimUDPBase 92 public class LLUDPServer : OpenSimUDPBase
91 { 93 {
94 /// <summary>Maximum transmission unit, or UDP packet size, for the LLUDP protocol</summary>
95 public const int MTU = 1400;
96
92 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 97 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
93 98
99 /// <summary>The measured resolution of Environment.TickCount</summary>
100 public readonly float TickCountResolution;
101
94 /// <summary>Handlers for incoming packets</summary> 102 /// <summary>Handlers for incoming packets</summary>
95 //PacketEventDictionary packetEvents = new PacketEventDictionary(); 103 //PacketEventDictionary packetEvents = new PacketEventDictionary();
96 /// <summary>Incoming packets that are awaiting handling</summary> 104 /// <summary>Incoming packets that are awaiting handling</summary>
@@ -104,20 +112,35 @@ namespace OpenSim.Region.ClientStack.LindenUDP
104 /// <summary>Manages authentication for agent circuits</summary> 112 /// <summary>Manages authentication for agent circuits</summary>
105 private AgentCircuitManager m_circuitManager; 113 private AgentCircuitManager m_circuitManager;
106 /// <summary>Reference to the scene this UDP server is attached to</summary> 114 /// <summary>Reference to the scene this UDP server is attached to</summary>
107 private IScene m_scene; 115 private Scene m_scene;
108 /// <summary>The X/Y coordinates of the scene this UDP server is attached to</summary> 116 /// <summary>The X/Y coordinates of the scene this UDP server is attached to</summary>
109 private Location m_location; 117 private Location m_location;
110 /// <summary>The measured resolution of Environment.TickCount</summary>
111 private float m_tickCountResolution;
112 /// <summary>The size of the receive buffer for the UDP socket. This value 118 /// <summary>The size of the receive buffer for the UDP socket. This value
113 /// is passed up to the operating system and used in the system networking 119 /// is passed up to the operating system and used in the system networking
114 /// stack. Use zero to leave this value as the default</summary> 120 /// stack. Use zero to leave this value as the default</summary>
115 private int m_recvBufferSize; 121 private int m_recvBufferSize;
116 /// <summary>Flag to process packets asynchronously or synchronously</summary> 122 /// <summary>Flag to process packets asynchronously or synchronously</summary>
117 private bool m_asyncPacketHandling; 123 private bool m_asyncPacketHandling;
124 /// <summary>Tracks whether or not a packet was sent each round so we know
125 /// whether or not to sleep</summary>
126 private bool m_packetSent;
127
128 /// <summary>Environment.TickCount of the last time the outgoing packet handler executed</summary>
129 private int m_tickLastOutgoingPacketHandler;
130 /// <summary>Keeps track of the number of elapsed milliseconds since the last time the outgoing packet handler looped</summary>
131 private int m_elapsedMSOutgoingPacketHandler;
132 /// <summary>Keeps track of the number of 100 millisecond periods elapsed in the outgoing packet handler executed</summary>
133 private int m_elapsed100MSOutgoingPacketHandler;
134 /// <summary>Keeps track of the number of 500 millisecond periods elapsed in the outgoing packet handler executed</summary>
135 private int m_elapsed500MSOutgoingPacketHandler;
136
137 /// <summary>Flag to signal when clients should check for resends</summary>
138 private bool m_resendUnacked;
139 /// <summary>Flag to signal when clients should send ACKs</summary>
140 private bool m_sendAcks;
141 /// <summary>Flag to signal when clients should send pings</summary>
142 private bool m_sendPing;
118 143
119 /// <summary>The measured resolution of Environment.TickCount</summary>
120 public float TickCountResolution { get { return m_tickCountResolution; } }
121 public Socket Server { get { return null; } } 144 public Socket Server { get { return null; } }
122 145
123 public LLUDPServer(IPAddress listenIP, ref uint port, int proxyPortOffsetParm, bool allow_alternate_port, IConfigSource configSource, AgentCircuitManager circuitManager) 146 public LLUDPServer(IPAddress listenIP, ref uint port, int proxyPortOffsetParm, bool allow_alternate_port, IConfigSource configSource, AgentCircuitManager circuitManager)
@@ -126,16 +149,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP
126 #region Environment.TickCount Measurement 149 #region Environment.TickCount Measurement
127 150
128 // Measure the resolution of Environment.TickCount 151 // Measure the resolution of Environment.TickCount
129 m_tickCountResolution = 0f; 152 TickCountResolution = 0f;
130 for (int i = 0; i < 5; i++) 153 for (int i = 0; i < 5; i++)
131 { 154 {
132 int start = Environment.TickCount; 155 int start = Environment.TickCount;
133 int now = start; 156 int now = start;
134 while (now == start) 157 while (now == start)
135 now = Environment.TickCount; 158 now = Environment.TickCount;
136 m_tickCountResolution += (float)(now - start) * 0.2f; 159 TickCountResolution += (float)(now - start) * 0.2f;
137 } 160 }
138 m_log.Info("[LLUDPSERVER]: Average Environment.TickCount resolution: " + TickCountResolution + "ms"); 161 m_log.Info("[LLUDPSERVER]: Average Environment.TickCount resolution: " + TickCountResolution + "ms");
162 TickCountResolution = (float)Math.Ceiling(TickCountResolution);
139 163
140 #endregion Environment.TickCount Measurement 164 #endregion Environment.TickCount Measurement
141 165
@@ -181,15 +205,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP
181 205
182 public void AddScene(IScene scene) 206 public void AddScene(IScene scene)
183 { 207 {
184 if (m_scene == null) 208 if (m_scene != null)
185 { 209 {
186 m_scene = scene; 210 m_log.Error("[LLUDPSERVER]: AddScene() called on an LLUDPServer that already has a scene");
187 m_location = new Location(m_scene.RegionInfo.RegionHandle); 211 return;
188 } 212 }
189 else 213
214 if (!(scene is Scene))
190 { 215 {
191 m_log.Error("[LLUDPSERVER]: AddScene() called on an LLUDPServer that already has a scene"); 216 m_log.Error("[LLUDPSERVER]: AddScene() called with an unrecognized scene type " + scene.GetType());
217 return;
192 } 218 }
219
220 m_scene = (Scene)scene;
221 m_location = new Location(m_scene.RegionInfo.RegionHandle);
193 } 222 }
194 223
195 public bool HandlesRegion(Location x) 224 public bool HandlesRegion(Location x)
@@ -267,38 +296,54 @@ namespace OpenSim.Region.ClientStack.LindenUDP
267 { 296 {
268 int dataLength = data.Length; 297 int dataLength = data.Length;
269 bool doZerocode = (data[0] & Helpers.MSG_ZEROCODED) != 0; 298 bool doZerocode = (data[0] & Helpers.MSG_ZEROCODED) != 0;
299 bool doCopy = true;
270 300
271 // Frequency analysis of outgoing packet sizes shows a large clump of packets at each end of the spectrum. 301 // Frequency analysis of outgoing packet sizes shows a large clump of packets at each end of the spectrum.
272 // The vast majority of packets are less than 200 bytes, although due to asset transfers and packet splitting 302 // The vast majority of packets are less than 200 bytes, although due to asset transfers and packet splitting
273 // there are a decent number of packets in the 1000-1140 byte range. We allocate one of two sizes of data here 303 // there are a decent number of packets in the 1000-1140 byte range. We allocate one of two sizes of data here
274 // to accomodate for both common scenarios and provide ample room for ACK appending in both 304 // to accomodate for both common scenarios and provide ample room for ACK appending in both
275 int bufferSize = (dataLength > 180) ? Packet.MTU : 200; 305 int bufferSize = (dataLength > 180) ? LLUDPServer.MTU : 200;
276 306
277 UDPPacketBuffer buffer = new UDPPacketBuffer(udpClient.RemoteEndPoint, bufferSize); 307 UDPPacketBuffer buffer = new UDPPacketBuffer(udpClient.RemoteEndPoint, bufferSize);
278 308
279 // Zerocode if needed 309 // Zerocode if needed
280 if (doZerocode) 310 if (doZerocode)
281 { 311 {
282 try { dataLength = Helpers.ZeroEncode(data, dataLength, buffer.Data); } 312 try
313 {
314 dataLength = Helpers.ZeroEncode(data, dataLength, buffer.Data);
315 doCopy = false;
316 }
283 catch (IndexOutOfRangeException) 317 catch (IndexOutOfRangeException)
284 { 318 {
285 // The packet grew larger than the bufferSize while zerocoding. 319 // The packet grew larger than the bufferSize while zerocoding.
286 // Remove the MSG_ZEROCODED flag and send the unencoded data 320 // Remove the MSG_ZEROCODED flag and send the unencoded data
287 // instead 321 // instead
288 m_log.Debug("[LLUDPSERVER]: Packet exceeded buffer size during zerocoding for " + type + ". Removing MSG_ZEROCODED flag"); 322 m_log.Debug("[LLUDPSERVER]: Packet exceeded buffer size during zerocoding for " + type + ". DataLength=" + dataLength +
323 " and BufferLength=" + buffer.Data.Length + ". Removing MSG_ZEROCODED flag");
289 data[0] = (byte)(data[0] & ~Helpers.MSG_ZEROCODED); 324 data[0] = (byte)(data[0] & ~Helpers.MSG_ZEROCODED);
290 Buffer.BlockCopy(data, 0, buffer.Data, 0, dataLength);
291 } 325 }
292 } 326 }
293 else 327
328 // If the packet data wasn't already copied during zerocoding, copy it now
329 if (doCopy)
294 { 330 {
295 Buffer.BlockCopy(data, 0, buffer.Data, 0, dataLength); 331 if (dataLength <= buffer.Data.Length)
332 {
333 Buffer.BlockCopy(data, 0, buffer.Data, 0, dataLength);
334 }
335 else
336 {
337 m_log.Error("[LLUDPSERVER]: Packet exceeded buffer size! This could be an indication of packet assembly not obeying the MTU. Type=" +
338 type + ", DataLength=" + dataLength + ", BufferLength=" + buffer.Data.Length + ". Dropping packet");
339 return;
340 }
296 } 341 }
342
297 buffer.DataLength = dataLength; 343 buffer.DataLength = dataLength;
298 344
299 #region Queue or Send 345 #region Queue or Send
300 346
301 // Look up the UDPClient this is going to
302 OutgoingPacket outgoingPacket = new OutgoingPacket(udpClient, buffer, category); 347 OutgoingPacket outgoingPacket = new OutgoingPacket(udpClient, buffer, category);
303 348
304 if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket)) 349 if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket))
@@ -338,57 +383,58 @@ namespace OpenSim.Region.ClientStack.LindenUDP
338 StartPingCheckPacket pc = (StartPingCheckPacket)PacketPool.Instance.GetPacket(PacketType.StartPingCheck); 383 StartPingCheckPacket pc = (StartPingCheckPacket)PacketPool.Instance.GetPacket(PacketType.StartPingCheck);
339 pc.Header.Reliable = false; 384 pc.Header.Reliable = false;
340 385
341 OutgoingPacket oldestPacket = udpClient.NeedAcks.GetOldest();
342
343 pc.PingID.PingID = (byte)udpClient.CurrentPingSequence++; 386 pc.PingID.PingID = (byte)udpClient.CurrentPingSequence++;
344 pc.PingID.OldestUnacked = (oldestPacket != null) ? oldestPacket.SequenceNumber : 0; 387 // We *could* get OldestUnacked, but it would hurt performance and not provide any benefit
388 pc.PingID.OldestUnacked = 0;
345 389
346 SendPacket(udpClient, pc, ThrottleOutPacketType.Unknown, false); 390 SendPacket(udpClient, pc, ThrottleOutPacketType.Unknown, false);
347 } 391 }
348 392
349 public void ResendUnacked(LLUDPClient udpClient) 393 public void ResendUnacked(LLUDPClient udpClient)
350 { 394 {
351 if (udpClient.IsConnected && udpClient.NeedAcks.Count > 0) 395 if (!udpClient.IsConnected)
396 return;
397
398 // Disconnect an agent if no packets are received for some time
399 //FIXME: Make 60 an .ini setting
400 if ((Environment.TickCount & Int32.MaxValue) - udpClient.TickLastPacketReceived > 1000 * 60)
352 { 401 {
353 // Disconnect an agent if no packets are received for some time 402 m_log.Warn("[LLUDPSERVER]: Ack timeout, disconnecting " + udpClient.AgentID);
354 //FIXME: Make 60 an .ini setting
355 if (Environment.TickCount - udpClient.TickLastPacketReceived > 1000 * 60)
356 {
357 m_log.Warn("[LLUDPSERVER]: Ack timeout, disconnecting " + udpClient.AgentID);
358 403
359 RemoveClient(udpClient); 404 RemoveClient(udpClient);
360 return; 405 return;
361 } 406 }
362 407
363 // Get a list of all of the packets that have been sitting unacked longer than udpClient.RTO 408 // Get a list of all of the packets that have been sitting unacked longer than udpClient.RTO
364 List<OutgoingPacket> expiredPackets = udpClient.NeedAcks.GetExpiredPackets(udpClient.RTO); 409 List<OutgoingPacket> expiredPackets = udpClient.NeedAcks.GetExpiredPackets(udpClient.RTO);
365 410
366 if (expiredPackets != null) 411 if (expiredPackets != null)
412 {
413 m_log.Debug("[LLUDPSERVER]: Resending " + expiredPackets.Count + " packets to " + udpClient.AgentID + ", RTO=" + udpClient.RTO);
414
415 // Resend packets
416 for (int i = 0; i < expiredPackets.Count; i++)
367 { 417 {
368 // Resend packets 418 OutgoingPacket outgoingPacket = expiredPackets[i];
369 for (int i = 0; i < expiredPackets.Count; i++)
370 {
371 OutgoingPacket outgoingPacket = expiredPackets[i];
372 419
373 //m_log.DebugFormat("[LLUDPSERVER]: Resending packet #{0} (attempt {1}), {2}ms have passed", 420 //m_log.DebugFormat("[LLUDPSERVER]: Resending packet #{0} (attempt {1}), {2}ms have passed",
374 // outgoingPacket.SequenceNumber, outgoingPacket.ResendCount, Environment.TickCount - outgoingPacket.TickCount); 421 // outgoingPacket.SequenceNumber, outgoingPacket.ResendCount, Environment.TickCount - outgoingPacket.TickCount);
375 422
376 // Set the resent flag 423 // Set the resent flag
377 outgoingPacket.Buffer.Data[0] = (byte)(outgoingPacket.Buffer.Data[0] | Helpers.MSG_RESENT); 424 outgoingPacket.Buffer.Data[0] = (byte)(outgoingPacket.Buffer.Data[0] | Helpers.MSG_RESENT);
378 outgoingPacket.Category = ThrottleOutPacketType.Resend; 425 outgoingPacket.Category = ThrottleOutPacketType.Resend;
379 426
380 // The TickCount will be set to the current time when the packet 427 // The TickCount will be set to the current time when the packet
381 // is actually sent out again 428 // is actually sent out again
382 outgoingPacket.TickCount = 0; 429 outgoingPacket.TickCount = 0;
383 430
384 // Bump up the resend count on this packet 431 // Bump up the resend count on this packet
385 Interlocked.Increment(ref outgoingPacket.ResendCount); 432 Interlocked.Increment(ref outgoingPacket.ResendCount);
386 //Interlocked.Increment(ref Stats.ResentPackets); 433 //Interlocked.Increment(ref Stats.ResentPackets);
387 434
388 // Requeue or resend the packet 435 // Requeue or resend the packet
389 if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket)) 436 if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket))
390 SendPacketFinal(outgoingPacket); 437 SendPacketFinal(outgoingPacket);
391 }
392 } 438 }
393 } 439 }
394 } 440 }
@@ -409,9 +455,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
409 if (!udpClient.IsConnected) 455 if (!udpClient.IsConnected)
410 return; 456 return;
411 457
412 // Keep track of when this packet was sent out (right now)
413 outgoingPacket.TickCount = Environment.TickCount;
414
415 #region ACK Appending 458 #region ACK Appending
416 459
417 int dataLength = buffer.DataLength; 460 int dataLength = buffer.DataLength;
@@ -464,6 +507,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
464 507
465 // Put the UDP payload on the wire 508 // Put the UDP payload on the wire
466 AsyncBeginSend(buffer); 509 AsyncBeginSend(buffer);
510
511 // Keep track of when this packet was sent out (right now)
512 outgoingPacket.TickCount = Environment.TickCount & Int32.MaxValue;
467 } 513 }
468 514
469 protected override void PacketReceived(UDPPacketBuffer buffer) 515 protected override void PacketReceived(UDPPacketBuffer buffer)
@@ -506,14 +552,26 @@ namespace OpenSim.Region.ClientStack.LindenUDP
506 // UseCircuitCode handling 552 // UseCircuitCode handling
507 if (packet.Type == PacketType.UseCircuitCode) 553 if (packet.Type == PacketType.UseCircuitCode)
508 { 554 {
509 AddNewClient((UseCircuitCodePacket)packet, (IPEndPoint)buffer.RemoteEndPoint); 555 Util.FireAndForget(
556 delegate(object o)
557 {
558 IPEndPoint remoteEndPoint = (IPEndPoint)buffer.RemoteEndPoint;
559
560 // Begin the process of adding the client to the simulator
561 AddNewClient((UseCircuitCodePacket)packet, remoteEndPoint);
562
563 // Acknowledge the UseCircuitCode packet
564 SendAckImmediate(remoteEndPoint, packet.Header.Sequence);
565 }
566 );
567 return;
510 } 568 }
511 569
512 // Determine which agent this packet came from 570 // Determine which agent this packet came from
513 IClientAPI client; 571 IClientAPI client;
514 if (!m_scene.ClientManager.TryGetValue(address, out client) || !(client is LLClientView)) 572 if (!m_scene.ClientManager.TryGetValue(address, out client) || !(client is LLClientView))
515 { 573 {
516 m_log.Warn("[LLUDPSERVER]: Received a " + packet.Type + " packet from an unrecognized source: " + address + 574 m_log.Debug("[LLUDPSERVER]: Received a " + packet.Type + " packet from an unrecognized source: " + address +
517 " in " + m_scene.RegionInfo.RegionName + ", currently tracking " + m_scene.ClientManager.Count + " clients"); 575 " in " + m_scene.RegionInfo.RegionName + ", currently tracking " + m_scene.ClientManager.Count + " clients");
518 return; 576 return;
519 } 577 }
@@ -528,19 +586,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP
528 // Stats tracking 586 // Stats tracking
529 Interlocked.Increment(ref udpClient.PacketsReceived); 587 Interlocked.Increment(ref udpClient.PacketsReceived);
530 588
531 #region ACK Receiving 589 int now = Environment.TickCount & Int32.MaxValue;
532
533 int now = Environment.TickCount;
534 udpClient.TickLastPacketReceived = now; 590 udpClient.TickLastPacketReceived = now;
535 591
592 #region ACK Receiving
593
536 // Handle appended ACKs 594 // Handle appended ACKs
537 if (packet.Header.AppendedAcks && packet.Header.AckList != null) 595 if (packet.Header.AppendedAcks && packet.Header.AckList != null)
538 { 596 {
539 lock (udpClient.NeedAcks.SyncRoot) 597 for (int i = 0; i < packet.Header.AckList.Length; i++)
540 { 598 udpClient.NeedAcks.Remove(packet.Header.AckList[i], now, packet.Header.Resent);
541 for (int i = 0; i < packet.Header.AckList.Length; i++)
542 AcknowledgePacket(udpClient, packet.Header.AckList[i], now, packet.Header.Resent);
543 }
544 } 599 }
545 600
546 // Handle PacketAck packets 601 // Handle PacketAck packets
@@ -548,11 +603,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
548 { 603 {
549 PacketAckPacket ackPacket = (PacketAckPacket)packet; 604 PacketAckPacket ackPacket = (PacketAckPacket)packet;
550 605
551 lock (udpClient.NeedAcks.SyncRoot) 606 for (int i = 0; i < ackPacket.Packets.Length; i++)
552 { 607 udpClient.NeedAcks.Remove(ackPacket.Packets[i].ID, now, packet.Header.Resent);
553 for (int i = 0; i < ackPacket.Packets.Length; i++) 608
554 AcknowledgePacket(udpClient, ackPacket.Packets[i].ID, now, packet.Header.Resent); 609 // We don't need to do anything else with PacketAck packets
555 } 610 return;
556 } 611 }
557 612
558 #endregion ACK Receiving 613 #endregion ACK Receiving
@@ -560,20 +615,22 @@ namespace OpenSim.Region.ClientStack.LindenUDP
560 #region ACK Sending 615 #region ACK Sending
561 616
562 if (packet.Header.Reliable) 617 if (packet.Header.Reliable)
618 {
563 udpClient.PendingAcks.Enqueue(packet.Header.Sequence); 619 udpClient.PendingAcks.Enqueue(packet.Header.Sequence);
564 620
565 // This is a somewhat odd sequence of steps to pull the client.BytesSinceLastACK value out, 621 // This is a somewhat odd sequence of steps to pull the client.BytesSinceLastACK value out,
566 // add the current received bytes to it, test if 2*MTU bytes have been sent, if so remove 622 // add the current received bytes to it, test if 2*MTU bytes have been sent, if so remove
567 // 2*MTU bytes from the value and send ACKs, and finally add the local value back to 623 // 2*MTU bytes from the value and send ACKs, and finally add the local value back to
568 // client.BytesSinceLastACK. Lockless thread safety 624 // client.BytesSinceLastACK. Lockless thread safety
569 int bytesSinceLastACK = Interlocked.Exchange(ref udpClient.BytesSinceLastACK, 0); 625 int bytesSinceLastACK = Interlocked.Exchange(ref udpClient.BytesSinceLastACK, 0);
570 bytesSinceLastACK += buffer.DataLength; 626 bytesSinceLastACK += buffer.DataLength;
571 if (bytesSinceLastACK > Packet.MTU * 2) 627 if (bytesSinceLastACK > LLUDPServer.MTU * 2)
572 { 628 {
573 bytesSinceLastACK -= Packet.MTU * 2; 629 bytesSinceLastACK -= LLUDPServer.MTU * 2;
574 SendAcks(udpClient); 630 SendAcks(udpClient);
631 }
632 Interlocked.Add(ref udpClient.BytesSinceLastACK, bytesSinceLastACK);
575 } 633 }
576 Interlocked.Add(ref udpClient.BytesSinceLastACK, bytesSinceLastACK);
577 634
578 #endregion ACK Sending 635 #endregion ACK Sending
579 636
@@ -593,18 +650,53 @@ namespace OpenSim.Region.ClientStack.LindenUDP
593 650
594 #endregion Incoming Packet Accounting 651 #endregion Incoming Packet Accounting
595 652
596 // Don't bother clogging up the queue with PacketAck packets that are already handled here 653 #region Ping Check Handling
597 if (packet.Type != PacketType.PacketAck) 654
655 if (packet.Type == PacketType.StartPingCheck)
598 { 656 {
599 // Inbox insertion 657 // We don't need to do anything else with ping checks
600 packetInbox.Enqueue(new IncomingPacket(udpClient, packet)); 658 StartPingCheckPacket startPing = (StartPingCheckPacket)packet;
659
660 CompletePingCheckPacket completePing = new CompletePingCheckPacket();
661 completePing.PingID.PingID = startPing.PingID.PingID;
662 SendPacket(udpClient, completePing, ThrottleOutPacketType.Unknown, false);
663 return;
664 }
665 else if (packet.Type == PacketType.CompletePingCheck)
666 {
667 // We don't currently track client ping times
668 return;
601 } 669 }
670
671 #endregion Ping Check Handling
672
673 // Inbox insertion
674 packetInbox.Enqueue(new IncomingPacket(udpClient, packet));
602 } 675 }
603 676
604 protected override void PacketSent(UDPPacketBuffer buffer, int bytesSent) 677 protected override void PacketSent(UDPPacketBuffer buffer, int bytesSent)
605 { 678 {
606 } 679 }
607 680
681 private void SendAckImmediate(IPEndPoint remoteEndpoint, uint sequenceNumber)
682 {
683 PacketAckPacket ack = new PacketAckPacket();
684 ack.Header.Reliable = false;
685 ack.Packets = new PacketAckPacket.PacketsBlock[1];
686 ack.Packets[0] = new PacketAckPacket.PacketsBlock();
687 ack.Packets[0].ID = sequenceNumber;
688
689 byte[] packetData = ack.ToBytes();
690 int length = packetData.Length;
691
692 UDPPacketBuffer buffer = new UDPPacketBuffer(remoteEndpoint, length);
693 buffer.DataLength = length;
694
695 Buffer.BlockCopy(packetData, 0, buffer.Data, 0, length);
696
697 AsyncBeginSend(buffer);
698 }
699
608 private bool IsClientAuthorized(UseCircuitCodePacket useCircuitCode, out AuthenticateResponse sessionInfo) 700 private bool IsClientAuthorized(UseCircuitCodePacket useCircuitCode, out AuthenticateResponse sessionInfo)
609 { 701 {
610 UUID agentID = useCircuitCode.CircuitCode.ID; 702 UUID agentID = useCircuitCode.CircuitCode.ID;
@@ -672,33 +764,25 @@ namespace OpenSim.Region.ClientStack.LindenUDP
672 client.Close(); 764 client.Close();
673 } 765 }
674 766
675 private void AcknowledgePacket(LLUDPClient client, uint ack, int currentTime, bool fromResend)
676 {
677 OutgoingPacket ackedPacket;
678 if (client.NeedAcks.RemoveUnsafe(ack, out ackedPacket) && !fromResend)
679 {
680 // Update stats
681 Interlocked.Add(ref client.UnackedBytes, -ackedPacket.Buffer.DataLength);
682
683 // Calculate the round-trip time for this packet and its ACK
684 int rtt = currentTime - ackedPacket.TickCount;
685 if (rtt > 0)
686 client.UpdateRoundTrip(rtt);
687 }
688 }
689
690 private void IncomingPacketHandler() 767 private void IncomingPacketHandler()
691 { 768 {
692 // Set this culture for the thread that incoming packets are received 769 // Set this culture for the thread that incoming packets are received
693 // on to en-US to avoid number parsing issues 770 // on to en-US to avoid number parsing issues
694 Culture.SetCurrentCulture(); 771 Culture.SetCurrentCulture();
695 772
696 IncomingPacket incomingPacket = null;
697
698 while (base.IsRunning) 773 while (base.IsRunning)
699 { 774 {
700 if (packetInbox.Dequeue(100, ref incomingPacket)) 775 try
701 Util.FireAndForget(ProcessInPacket, incomingPacket); 776 {
777 IncomingPacket incomingPacket = null;
778
779 if (packetInbox.Dequeue(100, ref incomingPacket))
780 Util.FireAndForget(ProcessInPacket, incomingPacket);
781 }
782 catch (Exception ex)
783 {
784 m_log.Error("[LLUDPSERVER]: Error in the incoming packet handler loop: " + ex.Message, ex);
785 }
702 } 786 }
703 787
704 if (packetInbox.Count > 0) 788 if (packetInbox.Count > 0)
@@ -712,68 +796,97 @@ namespace OpenSim.Region.ClientStack.LindenUDP
712 // on to en-US to avoid number parsing issues 796 // on to en-US to avoid number parsing issues
713 Culture.SetCurrentCulture(); 797 Culture.SetCurrentCulture();
714 798
715 int now = Environment.TickCount;
716 int elapsedMS = 0;
717 int elapsed100MS = 0;
718 int elapsed500MS = 0;
719
720 while (base.IsRunning) 799 while (base.IsRunning)
721 { 800 {
722 bool resendUnacked = false; 801 try
723 bool sendAcks = false; 802 {
724 bool sendPings = false; 803 m_packetSent = false;
725 bool packetSent = false;
726 804
727 elapsedMS += Environment.TickCount - now; 805 #region Update Timers
728 806
729 // Check for pending outgoing resends every 100ms 807 m_resendUnacked = false;
730 if (elapsedMS >= 100) 808 m_sendAcks = false;
731 { 809 m_sendPing = false;
732 resendUnacked = true; 810
733 elapsedMS -= 100; 811 // Update elapsed time
734 ++elapsed100MS; 812 int thisTick = Environment.TickCount & Int32.MaxValue;
813 if (m_tickLastOutgoingPacketHandler > thisTick)
814 m_elapsedMSOutgoingPacketHandler += ((Int32.MaxValue - m_tickLastOutgoingPacketHandler) + thisTick);
815 else
816 m_elapsedMSOutgoingPacketHandler += (thisTick - m_tickLastOutgoingPacketHandler);
817
818 m_tickLastOutgoingPacketHandler = thisTick;
819
820 // Check for pending outgoing resends every 100ms
821 if (m_elapsedMSOutgoingPacketHandler >= 100)
822 {
823 m_resendUnacked = true;
824 m_elapsedMSOutgoingPacketHandler = 0;
825 m_elapsed100MSOutgoingPacketHandler += 1;
826 }
827
828 // Check for pending outgoing ACKs every 500ms
829 if (m_elapsed100MSOutgoingPacketHandler >= 5)
830 {
831 m_sendAcks = true;
832 m_elapsed100MSOutgoingPacketHandler = 0;
833 m_elapsed500MSOutgoingPacketHandler += 1;
834 }
835
836 // Send pings to clients every 5000ms
837 if (m_elapsed500MSOutgoingPacketHandler >= 10)
838 {
839 m_sendPing = true;
840 m_elapsed500MSOutgoingPacketHandler = 0;
841 }
842
843 #endregion Update Timers
844
845 // Handle outgoing packets, resends, acknowledgements, and pings for each
846 // client. m_packetSent will be set to true if a packet is sent
847 m_scene.ClientManager.ForEachSync(ClientOutgoingPacketHandler);
848
849 // If nothing was sent, sleep for the minimum amount of time before a
850 // token bucket could get more tokens
851 if (!m_packetSent)
852 Thread.Sleep((int)TickCountResolution);
735 } 853 }
736 // Check for pending outgoing ACKs every 500ms 854 catch (Exception ex)
737 if (elapsed100MS >= 5)
738 { 855 {
739 sendAcks = true; 856 m_log.Error("[LLUDPSERVER]: OutgoingPacketHandler loop threw an exception: " + ex.Message, ex);
740 elapsed100MS = 0;
741 ++elapsed500MS;
742 } 857 }
743 // Send pings to clients every 5000ms 858 }
744 if (elapsed500MS >= 10) 859 }
860
861 private void ClientOutgoingPacketHandler(IClientAPI client)
862 {
863 try
864 {
865 if (client is LLClientView)
745 { 866 {
746 sendPings = true; 867 LLUDPClient udpClient = ((LLClientView)client).UDPClient;
747 elapsed500MS = 0;
748 }
749 868
750 m_scene.ClientManager.ForEach( 869 if (udpClient.IsConnected)
751 delegate(IClientAPI client)
752 { 870 {
753 if (client is LLClientView) 871 if (m_resendUnacked)
754 { 872 ResendUnacked(udpClient);
755 LLUDPClient udpClient = ((LLClientView)client).UDPClient; 873
756 874 if (m_sendAcks)
757 if (udpClient.IsConnected) 875 SendAcks(udpClient);
758 { 876
759 if (udpClient.DequeueOutgoing()) 877 if (m_sendPing)
760 packetSent = true; 878 SendPing(udpClient);
761 if (resendUnacked)
762 ResendUnacked(udpClient);
763 if (sendAcks)
764 {
765 SendAcks(udpClient);
766 udpClient.SendPacketStats();
767 }
768 if (sendPings)
769 SendPing(udpClient);
770 }
771 }
772 }
773 );
774 879
775 if (!packetSent) 880 // Dequeue any outgoing packets that are within the throttle limits
776 Thread.Sleep(20); 881 if (udpClient.DequeueOutgoing())
882 m_packetSent = true;
883 }
884 }
885 }
886 catch (Exception ex)
887 {
888 m_log.Error("[LLUDPSERVER]: OutgoingPacketHandler iteration for " + client.Name +
889 " threw an exception: " + ex.Message, ex);
777 } 890 }
778 } 891 }
779 892
diff --git a/OpenSim/Region/ClientStack/LindenUDP/TokenBucket.cs b/OpenSim/Region/ClientStack/LindenUDP/TokenBucket.cs
new file mode 100644
index 0000000..bdbd284
--- /dev/null
+++ b/OpenSim/Region/ClientStack/LindenUDP/TokenBucket.cs
@@ -0,0 +1,217 @@
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;
29
30namespace OpenSim.Region.ClientStack.LindenUDP
31{
32 /// <summary>
33 /// A hierarchical token bucket for bandwidth throttling. See
34 /// http://en.wikipedia.org/wiki/Token_bucket for more information
35 /// </summary>
36 public class TokenBucket
37 {
38 /// <summary>Parent bucket to this bucket, or null if this is a root
39 /// bucket</summary>
40 TokenBucket parent;
41 /// <summary>Size of the bucket in bytes. If zero, the bucket has
42 /// infinite capacity</summary>
43 int maxBurst;
44 /// <summary>Rate that the bucket fills, in bytes per millisecond. If
45 /// zero, the bucket always remains full</summary>
46 int tokensPerMS;
47 /// <summary>Number of tokens currently in the bucket</summary>
48 int content;
49 /// <summary>Time of the last drip, in system ticks</summary>
50 int lastDrip;
51
52 #region Properties
53
54 /// <summary>
55 /// The parent bucket of this bucket, or null if this bucket has no
56 /// parent. The parent bucket will limit the aggregate bandwidth of all
57 /// of its children buckets
58 /// </summary>
59 public TokenBucket Parent
60 {
61 get { return parent; }
62 }
63
64 /// <summary>
65 /// Maximum burst rate in bytes per second. This is the maximum number
66 /// of tokens that can accumulate in the bucket at any one time
67 /// </summary>
68 public int MaxBurst
69 {
70 get { return maxBurst; }
71 set { maxBurst = (value >= 0 ? value : 0); }
72 }
73
74 /// <summary>
75 /// The speed limit of this bucket in bytes per second. This is the
76 /// number of tokens that are added to the bucket per second
77 /// </summary>
78 /// <remarks>Tokens are added to the bucket any time
79 /// <seealso cref="RemoveTokens"/> is called, at the granularity of
80 /// the system tick interval (typically around 15-22ms)</remarks>
81 public int DripRate
82 {
83 get { return tokensPerMS * 1000; }
84 set
85 {
86 if (value == 0)
87 tokensPerMS = 0;
88 else
89 {
90 int bpms = (int)((float)value / 1000.0f);
91
92 if (bpms <= 0)
93 tokensPerMS = 1; // 1 byte/ms is the minimum granularity
94 else
95 tokensPerMS = bpms;
96 }
97 }
98 }
99
100 /// <summary>
101 /// The speed limit of this bucket in bytes per millisecond
102 /// </summary>
103 public int DripPerMS
104 {
105 get { return tokensPerMS; }
106 }
107
108 /// <summary>
109 /// The number of bytes that can be sent at this moment. This is the
110 /// current number of tokens in the bucket
111 /// <remarks>If this bucket has a parent bucket that does not have
112 /// enough tokens for a request, <seealso cref="RemoveTokens"/> will
113 /// return false regardless of the content of this bucket</remarks>
114 /// </summary>
115 public int Content
116 {
117 get { return content; }
118 }
119
120 #endregion Properties
121
122 /// <summary>
123 /// Default constructor
124 /// </summary>
125 /// <param name="parent">Parent bucket if this is a child bucket, or
126 /// null if this is a root bucket</param>
127 /// <param name="maxBurst">Maximum size of the bucket in bytes, or
128 /// zero if this bucket has no maximum capacity</param>
129 /// <param name="dripRate">Rate that the bucket fills, in bytes per
130 /// second. If zero, the bucket always remains full</param>
131 public TokenBucket(TokenBucket parent, int maxBurst, int dripRate)
132 {
133 this.parent = parent;
134 MaxBurst = maxBurst;
135 DripRate = dripRate;
136 lastDrip = Environment.TickCount & Int32.MaxValue;
137 }
138
139 /// <summary>
140 /// Remove a given number of tokens from the bucket
141 /// </summary>
142 /// <param name="amount">Number of tokens to remove from the bucket</param>
143 /// <returns>True if the requested number of tokens were removed from
144 /// the bucket, otherwise false</returns>
145 public bool RemoveTokens(int amount)
146 {
147 bool dummy;
148 return RemoveTokens(amount, out dummy);
149 }
150
151 /// <summary>
152 /// Remove a given number of tokens from the bucket
153 /// </summary>
154 /// <param name="amount">Number of tokens to remove from the bucket</param>
155 /// <param name="dripSucceeded">True if tokens were added to the bucket
156 /// during this call, otherwise false</param>
157 /// <returns>True if the requested number of tokens were removed from
158 /// the bucket, otherwise false</returns>
159 public bool RemoveTokens(int amount, out bool dripSucceeded)
160 {
161 if (maxBurst == 0)
162 {
163 dripSucceeded = true;
164 return true;
165 }
166
167 dripSucceeded = Drip();
168
169 if (content - amount >= 0)
170 {
171 if (parent != null && !parent.RemoveTokens(amount))
172 return false;
173
174 content -= amount;
175 return true;
176 }
177 else
178 {
179 return false;
180 }
181 }
182
183 /// <summary>
184 /// Add tokens to the bucket over time. The number of tokens added each
185 /// call depends on the length of time that has passed since the last
186 /// call to Drip
187 /// </summary>
188 /// <returns>True if tokens were added to the bucket, otherwise false</returns>
189 public bool Drip()
190 {
191 if (tokensPerMS == 0)
192 {
193 content = maxBurst;
194 return true;
195 }
196 else
197 {
198 int now = Environment.TickCount & Int32.MaxValue;
199 int deltaMS = now - lastDrip;
200
201 if (deltaMS <= 0)
202 {
203 if (deltaMS < 0)
204 lastDrip = now;
205 return false;
206 }
207
208 int dripAmount = deltaMS * tokensPerMS;
209
210 content = Math.Min(content + dripAmount, maxBurst);
211 lastDrip = now;
212
213 return true;
214 }
215 }
216 }
217}
diff --git a/OpenSim/Region/ClientStack/LindenUDP/UnackedPacketCollection.cs b/OpenSim/Region/ClientStack/LindenUDP/UnackedPacketCollection.cs
index f3242c1..016712f 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/UnackedPacketCollection.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/UnackedPacketCollection.cs
@@ -37,97 +37,59 @@ namespace OpenSim.Region.ClientStack.LindenUDP
37 /// </summary> 37 /// </summary>
38 public sealed class UnackedPacketCollection 38 public sealed class UnackedPacketCollection
39 { 39 {
40 /// <summary>Synchronization primitive. A lock must be acquired on this
41 /// object before calling any of the unsafe methods</summary>
42 public object SyncRoot = new object();
43
44 /// <summary>Holds the actual unacked packet data, sorted by sequence number</summary>
45 private SortedDictionary<uint, OutgoingPacket> packets = new SortedDictionary<uint, OutgoingPacket>();
46
47 /// <summary>Gets the total number of unacked packets</summary>
48 public int Count { get { return packets.Count; } }
49
50 /// <summary> 40 /// <summary>
51 /// Default constructor 41 /// Holds information about a pending acknowledgement
52 /// </summary> 42 /// </summary>
53 public UnackedPacketCollection() 43 private struct PendingAck
54 { 44 {
55 } 45 /// <summary>Sequence number of the packet to remove</summary>
46 public uint SequenceNumber;
47 /// <summary>Environment.TickCount value when the remove was queued.
48 /// This is used to update round-trip times for packets</summary>
49 public int RemoveTime;
50 /// <summary>Whether or not this acknowledgement was attached to a
51 /// resent packet. If so, round-trip time will not be calculated</summary>
52 public bool FromResend;
56 53
57 /// <summary> 54 public PendingAck(uint sequenceNumber, int currentTime, bool fromResend)
58 /// Add an unacked packet to the collection
59 /// </summary>
60 /// <param name="packet">Packet that is awaiting acknowledgement</param>
61 /// <returns>True if the packet was successfully added, false if the
62 /// packet already existed in the collection</returns>
63 public bool Add(OutgoingPacket packet)
64 {
65 lock (SyncRoot)
66 { 55 {
67 if (!packets.ContainsKey(packet.SequenceNumber)) 56 SequenceNumber = sequenceNumber;
68 { 57 RemoveTime = currentTime;
69 packets.Add(packet.SequenceNumber, packet); 58 FromResend = fromResend;
70 return true;
71 }
72 return false;
73 } 59 }
74 } 60 }
75 61
76 /// <summary> 62 /// <summary>Holds the actual unacked packet data, sorted by sequence number</summary>
77 /// Removes a packet from the collection without attempting to obtain a 63 private SortedDictionary<uint, OutgoingPacket> m_packets = new SortedDictionary<uint, OutgoingPacket>();
78 /// lock first 64 /// <summary>Holds packets that need to be added to the unacknowledged list</summary>
79 /// </summary> 65 private LocklessQueue<OutgoingPacket> m_pendingAdds = new LocklessQueue<OutgoingPacket>();
80 /// <param name="sequenceNumber">Sequence number of the packet to remove</param> 66 /// <summary>Holds information about pending acknowledgements</summary>
81 /// <returns>True if the packet was found and removed, otherwise false</returns> 67 private LocklessQueue<PendingAck> m_pendingRemoves = new LocklessQueue<PendingAck>();
82 public bool RemoveUnsafe(uint sequenceNumber)
83 {
84 return packets.Remove(sequenceNumber);
85 }
86
87 /// <summary>
88 /// Removes a packet from the collection without attempting to obtain a
89 /// lock first
90 /// </summary>
91 /// <param name="sequenceNumber">Sequence number of the packet to remove</param>
92 /// <param name="packet">Returns the removed packet</param>
93 /// <returns>True if the packet was found and removed, otherwise false</returns>
94 public bool RemoveUnsafe(uint sequenceNumber, out OutgoingPacket packet)
95 {
96 if (packets.TryGetValue(sequenceNumber, out packet))
97 {
98 packets.Remove(sequenceNumber);
99 return true;
100 }
101
102 return false;
103 }
104 68
105 /// <summary> 69 /// <summary>
106 /// Removes all elements from the collection 70 /// Add an unacked packet to the collection
107 /// </summary> 71 /// </summary>
108 public void Clear() 72 /// <param name="packet">Packet that is awaiting acknowledgement</param>
73 /// <returns>True if the packet was successfully added, false if the
74 /// packet already existed in the collection</returns>
75 /// <remarks>This does not immediately add the ACK to the collection,
76 /// it only queues it so it can be added in a thread-safe way later</remarks>
77 public void Add(OutgoingPacket packet)
109 { 78 {
110 lock (SyncRoot) 79 m_pendingAdds.Enqueue(packet);
111 packets.Clear();
112 } 80 }
113 81
114 /// <summary> 82 /// <summary>
115 /// Gets the packet with the lowest sequence number 83 /// Marks a packet as acknowledged
116 /// </summary> 84 /// </summary>
117 /// <returns>The packet with the lowest sequence number, or null if the 85 /// <param name="sequenceNumber">Sequence number of the packet to
118 /// collection is empty</returns> 86 /// acknowledge</param>
119 public OutgoingPacket GetOldest() 87 /// <param name="currentTime">Current value of Environment.TickCount</param>
88 /// <remarks>This does not immediately acknowledge the packet, it only
89 /// queues the ack so it can be handled in a thread-safe way later</remarks>
90 public void Remove(uint sequenceNumber, int currentTime, bool fromResend)
120 { 91 {
121 lock (SyncRoot) 92 m_pendingRemoves.Enqueue(new PendingAck(sequenceNumber, currentTime, fromResend));
122 {
123 using (SortedDictionary<uint, OutgoingPacket>.ValueCollection.Enumerator e = packets.Values.GetEnumerator())
124 {
125 if (e.MoveNext())
126 return e.Current;
127 else
128 return null;
129 }
130 }
131 } 93 }
132 94
133 /// <summary> 95 /// <summary>
@@ -138,15 +100,22 @@ namespace OpenSim.Region.ClientStack.LindenUDP
138 /// packet is considered expired</param> 100 /// packet is considered expired</param>
139 /// <returns>A list of all expired packets according to the given 101 /// <returns>A list of all expired packets according to the given
140 /// expiration timeout</returns> 102 /// expiration timeout</returns>
103 /// <remarks>This function is not thread safe, and cannot be called
104 /// multiple times concurrently</remarks>
141 public List<OutgoingPacket> GetExpiredPackets(int timeoutMS) 105 public List<OutgoingPacket> GetExpiredPackets(int timeoutMS)
142 { 106 {
107 ProcessQueues();
108
143 List<OutgoingPacket> expiredPackets = null; 109 List<OutgoingPacket> expiredPackets = null;
144 110
145 lock (SyncRoot) 111 if (m_packets.Count > 0)
146 { 112 {
147 int now = Environment.TickCount; 113 int now = Environment.TickCount & Int32.MaxValue;
148 foreach (OutgoingPacket packet in packets.Values) 114
115 foreach (OutgoingPacket packet in m_packets.Values)
149 { 116 {
117 // TickCount of zero means a packet is in the resend queue
118 // but hasn't actually been sent over the wire yet
150 if (packet.TickCount == 0) 119 if (packet.TickCount == 0)
151 continue; 120 continue;
152 121
@@ -156,14 +125,40 @@ namespace OpenSim.Region.ClientStack.LindenUDP
156 expiredPackets = new List<OutgoingPacket>(); 125 expiredPackets = new List<OutgoingPacket>();
157 expiredPackets.Add(packet); 126 expiredPackets.Add(packet);
158 } 127 }
159 else
160 {
161 break;
162 }
163 } 128 }
164 } 129 }
165 130
166 return expiredPackets; 131 return expiredPackets;
167 } 132 }
133
134 private void ProcessQueues()
135 {
136 // Process all the pending adds
137 OutgoingPacket pendingAdd;
138 while (m_pendingAdds.Dequeue(out pendingAdd))
139 m_packets[pendingAdd.SequenceNumber] = pendingAdd;
140
141 // Process all the pending removes, including updating statistics and round-trip times
142 PendingAck pendingRemove;
143 OutgoingPacket ackedPacket;
144 while (m_pendingRemoves.Dequeue(out pendingRemove))
145 {
146 if (m_packets.TryGetValue(pendingRemove.SequenceNumber, out ackedPacket))
147 {
148 m_packets.Remove(pendingRemove.SequenceNumber);
149
150 // Update stats
151 System.Threading.Interlocked.Add(ref ackedPacket.Client.UnackedBytes, -ackedPacket.Buffer.DataLength);
152
153 if (!pendingRemove.FromResend)
154 {
155 // Calculate the round-trip time for this packet and its ACK
156 int rtt = pendingRemove.RemoveTime - ackedPacket.TickCount;
157 if (rtt > 0)
158 ackedPacket.Client.UpdateRoundTrip(rtt);
159 }
160 }
161 }
162 }
168 } 163 }
169} 164}
diff --git a/OpenSim/Region/ClientStack/ThrottleSettings.cs b/OpenSim/Region/ClientStack/ThrottleSettings.cs
deleted file mode 100644
index fe4718c..0000000
--- a/OpenSim/Region/ClientStack/ThrottleSettings.cs
+++ /dev/null
@@ -1,57 +0,0 @@
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
28namespace OpenSim.Region.ClientStack
29{
30 /// <summary>
31 /// Represent throttle settings for a client stack. These settings are in bytes per second
32 /// </summary>
33 public class ThrottleSettings
34 {
35 /// <summary>
36 /// Minimum bytes per second that the throttle can be set to.
37 /// </summary>
38 public int Min;
39
40 /// <summary>
41 /// Maximum bytes per second that the throttle can be set to.
42 /// </summary>
43 public int Max;
44
45 /// <summary>
46 /// Current bytes per second that the throttle should be set to.
47 /// </summary>
48 public int Current;
49
50 public ThrottleSettings(int min, int max, int current)
51 {
52 Min = min;
53 Max = max;
54 Current = current;
55 }
56 }
57}