aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ClientStack/Linden/UDP
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/ClientStack/Linden/UDP')
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/J2KImage.cs3
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs1800
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs325
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs356
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLUDPServerCommands.cs35
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs10
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/Tests/ThrottleTests.cs17
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/ThrottleRates.cs12
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/TokenBucket.cs373
9 files changed, 1653 insertions, 1278 deletions
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/J2KImage.cs b/OpenSim/Region/ClientStack/Linden/UDP/J2KImage.cs
index 4d0568d..15d6f7f 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/J2KImage.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/J2KImage.cs
@@ -234,6 +234,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
234 m_stopPacket = TexturePacketCount(); 234 m_stopPacket = TexturePacketCount();
235 } 235 }
236 236
237 //Give them at least two packets, to play nice with some broken viewers (SL also behaves this way)
238 if (m_stopPacket == 1 && m_layers[0].End > FIRST_PACKET_SIZE) m_stopPacket++;
239
237 m_currentPacket = StartPacket; 240 m_currentPacket = StartPacket;
238 } 241 }
239 } 242 }
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
index e7dd9d3..62206e9 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
@@ -100,6 +100,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
100 public event AvatarPickerRequest OnAvatarPickerRequest; 100 public event AvatarPickerRequest OnAvatarPickerRequest;
101 public event StartAnim OnStartAnim; 101 public event StartAnim OnStartAnim;
102 public event StopAnim OnStopAnim; 102 public event StopAnim OnStopAnim;
103 public event ChangeAnim OnChangeAnim;
103 public event Action<IClientAPI> OnRequestAvatarsData; 104 public event Action<IClientAPI> OnRequestAvatarsData;
104 public event LinkObjects OnLinkObjects; 105 public event LinkObjects OnLinkObjects;
105 public event DelinkObjects OnDelinkObjects; 106 public event DelinkObjects OnDelinkObjects;
@@ -127,6 +128,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
127 public event RequestObjectPropertiesFamily OnRequestObjectPropertiesFamily; 128 public event RequestObjectPropertiesFamily OnRequestObjectPropertiesFamily;
128 public event UpdatePrimFlags OnUpdatePrimFlags; 129 public event UpdatePrimFlags OnUpdatePrimFlags;
129 public event UpdatePrimTexture OnUpdatePrimTexture; 130 public event UpdatePrimTexture OnUpdatePrimTexture;
131 public event ClientChangeObject onClientChangeObject;
130 public event UpdateVector OnUpdatePrimGroupPosition; 132 public event UpdateVector OnUpdatePrimGroupPosition;
131 public event UpdateVector OnUpdatePrimSinglePosition; 133 public event UpdateVector OnUpdatePrimSinglePosition;
132 public event UpdatePrimRotation OnUpdatePrimGroupRotation; 134 public event UpdatePrimRotation OnUpdatePrimGroupRotation;
@@ -156,6 +158,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
156 public event RequestTaskInventory OnRequestTaskInventory; 158 public event RequestTaskInventory OnRequestTaskInventory;
157 public event UpdateInventoryItem OnUpdateInventoryItem; 159 public event UpdateInventoryItem OnUpdateInventoryItem;
158 public event CopyInventoryItem OnCopyInventoryItem; 160 public event CopyInventoryItem OnCopyInventoryItem;
161 public event MoveItemsAndLeaveCopy OnMoveItemsAndLeaveCopy;
159 public event MoveInventoryItem OnMoveInventoryItem; 162 public event MoveInventoryItem OnMoveInventoryItem;
160 public event RemoveInventoryItem OnRemoveInventoryItem; 163 public event RemoveInventoryItem OnRemoveInventoryItem;
161 public event RemoveInventoryFolder OnRemoveInventoryFolder; 164 public event RemoveInventoryFolder OnRemoveInventoryFolder;
@@ -250,7 +253,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
250 public event ClassifiedInfoRequest OnClassifiedInfoRequest; 253 public event ClassifiedInfoRequest OnClassifiedInfoRequest;
251 public event ClassifiedInfoUpdate OnClassifiedInfoUpdate; 254 public event ClassifiedInfoUpdate OnClassifiedInfoUpdate;
252 public event ClassifiedDelete OnClassifiedDelete; 255 public event ClassifiedDelete OnClassifiedDelete;
253 public event ClassifiedDelete OnClassifiedGodDelete; 256 public event ClassifiedGodDelete OnClassifiedGodDelete;
254 public event EventNotificationAddRequest OnEventNotificationAddRequest; 257 public event EventNotificationAddRequest OnEventNotificationAddRequest;
255 public event EventNotificationRemoveRequest OnEventNotificationRemoveRequest; 258 public event EventNotificationRemoveRequest OnEventNotificationRemoveRequest;
256 public event EventGodDelete OnEventGodDelete; 259 public event EventGodDelete OnEventGodDelete;
@@ -281,10 +284,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
281 public event GroupVoteHistoryRequest OnGroupVoteHistoryRequest; 284 public event GroupVoteHistoryRequest OnGroupVoteHistoryRequest;
282 public event SimWideDeletesDelegate OnSimWideDeletes; 285 public event SimWideDeletesDelegate OnSimWideDeletes;
283 public event SendPostcard OnSendPostcard; 286 public event SendPostcard OnSendPostcard;
287 public event ChangeInventoryItemFlags OnChangeInventoryItemFlags;
284 public event MuteListEntryUpdate OnUpdateMuteListEntry; 288 public event MuteListEntryUpdate OnUpdateMuteListEntry;
285 public event MuteListEntryRemove OnRemoveMuteListEntry; 289 public event MuteListEntryRemove OnRemoveMuteListEntry;
286 public event GodlikeMessage onGodlikeMessage; 290 public event GodlikeMessage onGodlikeMessage;
287 public event GodUpdateRegionInfoUpdate OnGodUpdateRegionInfoUpdate; 291 public event GodUpdateRegionInfoUpdate OnGodUpdateRegionInfoUpdate;
292 public event GenericCall2 OnUpdateThrottles;
288 293
289#pragma warning disable 0067 294#pragma warning disable 0067
290 public event GenericMessage OnGenericMessage; 295 public event GenericMessage OnGenericMessage;
@@ -333,7 +338,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
333 private PriorityQueue m_entityProps; 338 private PriorityQueue m_entityProps;
334 private Prioritizer m_prioritizer; 339 private Prioritizer m_prioritizer;
335 private bool m_disableFacelights = false; 340 private bool m_disableFacelights = false;
336 private volatile bool m_justEditedTerrain = false; 341
342 private bool m_VelocityInterpolate = false;
343 private const uint MaxTransferBytesPerPacket = 600;
344
337 /// <value> 345 /// <value>
338 /// List used in construction of data blocks for an object update packet. This is to stop us having to 346 /// List used in construction of data blocks for an object update packet. This is to stop us having to
339 /// continually recreate it. 347 /// continually recreate it.
@@ -345,14 +353,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
345 /// thread servicing the m_primFullUpdates queue after a kill. If this happens the object persists as an 353 /// thread servicing the m_primFullUpdates queue after a kill. If this happens the object persists as an
346 /// ownerless phantom. 354 /// ownerless phantom.
347 /// 355 ///
348 /// All manipulation of this set has to occur under a lock 356 /// All manipulation of this set has to occur under an m_entityUpdates.SyncRoot lock
349 /// 357 ///
350 /// </value> 358 /// </value>
351 protected HashSet<uint> m_killRecord; 359// protected HashSet<uint> m_killRecord;
352 360
353// protected HashSet<uint> m_attachmentsSent; 361// protected HashSet<uint> m_attachmentsSent;
354 362
355 private int m_animationSequenceNumber = 1; 363 private bool m_deliverPackets = true;
364
356 private bool m_SendLogoutPacketWhenClosing = true; 365 private bool m_SendLogoutPacketWhenClosing = true;
357 366
358 /// <summary> 367 /// <summary>
@@ -398,6 +407,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
398 get { return m_startpos; } 407 get { return m_startpos; }
399 set { m_startpos = value; } 408 set { m_startpos = value; }
400 } 409 }
410 public bool DeliverPackets
411 {
412 get { return m_deliverPackets; }
413 set {
414 m_deliverPackets = value;
415 m_udpClient.m_deliverPackets = value;
416 }
417 }
401 public UUID AgentId { get { return m_agentId; } } 418 public UUID AgentId { get { return m_agentId; } }
402 public ISceneAgent SceneAgent { get; set; } 419 public ISceneAgent SceneAgent { get; set; }
403 public UUID ActiveGroupId { get { return m_activeGroupID; } private set { m_activeGroupID = value; } } 420 public UUID ActiveGroupId { get { return m_activeGroupID; } private set { m_activeGroupID = value; } }
@@ -405,6 +422,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP
405 public ulong ActiveGroupPowers { get { return m_activeGroupPowers; } private set { m_activeGroupPowers = value; } } 422 public ulong ActiveGroupPowers { get { return m_activeGroupPowers; } private set { m_activeGroupPowers = value; } }
406 public bool IsGroupMember(UUID groupID) { return m_groupPowers.ContainsKey(groupID); } 423 public bool IsGroupMember(UUID groupID) { return m_groupPowers.ContainsKey(groupID); }
407 424
425 public int PingTimeMS
426 {
427 get
428 {
429 if (UDPClient != null)
430 return UDPClient.PingTimeMS;
431 return 0;
432 }
433 }
434
408 /// <summary> 435 /// <summary>
409 /// Entity update queues 436 /// Entity update queues
410 /// </summary> 437 /// </summary>
@@ -426,7 +453,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
426 public string Name { get { return FirstName + " " + LastName; } } 453 public string Name { get { return FirstName + " " + LastName; } }
427 454
428 public uint CircuitCode { get { return m_circuitCode; } } 455 public uint CircuitCode { get { return m_circuitCode; } }
429 public int NextAnimationSequenceNumber { get { return m_animationSequenceNumber++; } } 456 public int NextAnimationSequenceNumber
457 {
458 get { return m_udpServer.NextAnimationSequenceNumber; }
459 }
430 460
431 /// <summary> 461 /// <summary>
432 /// As well as it's function in IClientAPI, in LLClientView we are locking on this property in order to 462 /// As well as it's function in IClientAPI, in LLClientView we are locking on this property in order to
@@ -447,7 +477,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
447 set { m_disableFacelights = value; } 477 set { m_disableFacelights = value; }
448 } 478 }
449 479
480 public List<uint> SelectedObjects {get; private set;}
481
450 public bool SendLogoutPacketWhenClosing { set { m_SendLogoutPacketWhenClosing = value; } } 482 public bool SendLogoutPacketWhenClosing { set { m_SendLogoutPacketWhenClosing = value; } }
483
451 484
452 #endregion Properties 485 #endregion Properties
453 486
@@ -465,6 +498,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
465// DebugPacketLevel = 1; 498// DebugPacketLevel = 1;
466 499
467 CloseSyncLock = new Object(); 500 CloseSyncLock = new Object();
501 SelectedObjects = new List<uint>();
468 502
469 RegisterInterface<IClientIM>(this); 503 RegisterInterface<IClientIM>(this);
470 RegisterInterface<IClientInventory>(this); 504 RegisterInterface<IClientInventory>(this);
@@ -474,7 +508,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
474 m_entityUpdates = new PriorityQueue(m_scene.Entities.Count); 508 m_entityUpdates = new PriorityQueue(m_scene.Entities.Count);
475 m_entityProps = new PriorityQueue(m_scene.Entities.Count); 509 m_entityProps = new PriorityQueue(m_scene.Entities.Count);
476 m_fullUpdateDataBlocksBuilder = new List<ObjectUpdatePacket.ObjectDataBlock>(); 510 m_fullUpdateDataBlocksBuilder = new List<ObjectUpdatePacket.ObjectDataBlock>();
477 m_killRecord = new HashSet<uint>(); 511// m_killRecord = new HashSet<uint>();
478// m_attachmentsSent = new HashSet<uint>(); 512// m_attachmentsSent = new HashSet<uint>();
479 513
480 m_assetService = m_scene.RequestModuleInterface<IAssetService>(); 514 m_assetService = m_scene.RequestModuleInterface<IAssetService>();
@@ -504,12 +538,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP
504 538
505 #region Client Methods 539 #region Client Methods
506 540
541
542 /// <summary>
543 /// Close down the client view
544 /// </summary>
507 public void Close() 545 public void Close()
508 { 546 {
509 Close(false); 547 Close(true, false);
510 } 548 }
511 549
512 public void Close(bool force) 550 public void Close(bool sendStop, bool force)
513 { 551 {
514 // We lock here to prevent race conditions between two threads calling close simultaneously (e.g. 552 // We lock here to prevent race conditions between two threads calling close simultaneously (e.g.
515 // a simultaneous relog just as a client is being closed out due to no packet ack from the old connection. 553 // a simultaneous relog just as a client is being closed out due to no packet ack from the old connection.
@@ -526,7 +564,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
526 } 564 }
527 565
528 IsActive = false; 566 IsActive = false;
529 CloseWithoutChecks(); 567 CloseWithoutChecks(sendStop);
530 } 568 }
531 } 569 }
532 570
@@ -539,12 +577,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP
539 /// 577 ///
540 /// Callers must lock ClosingSyncLock before calling. 578 /// Callers must lock ClosingSyncLock before calling.
541 /// </remarks> 579 /// </remarks>
542 public void CloseWithoutChecks() 580 public void CloseWithoutChecks(bool sendStop)
543 { 581 {
544 m_log.DebugFormat( 582 m_log.DebugFormat(
545 "[CLIENT]: Close has been called for {0} attached to scene {1}", 583 "[CLIENT]: Close has been called for {0} attached to scene {1}",
546 Name, m_scene.RegionInfo.RegionName); 584 Name, m_scene.RegionInfo.RegionName);
547 585
586 if (sendStop)
587 {
588 // Send the STOP packet
589 DisableSimulatorPacket disable = (DisableSimulatorPacket)PacketPool.Instance.GetPacket(PacketType.DisableSimulator);
590 OutPacket(disable, ThrottleOutPacketType.Unknown);
591 }
592
548 // Shutdown the image manager 593 // Shutdown the image manager
549 ImageManager.Close(); 594 ImageManager.Close();
550 595
@@ -566,7 +611,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
566 611
567 // Disable UDP handling for this client 612 // Disable UDP handling for this client
568 m_udpClient.Shutdown(); 613 m_udpClient.Shutdown();
569 614
615
570 //m_log.InfoFormat("[CLIENTVIEW] Memory pre GC {0}", System.GC.GetTotalMemory(false)); 616 //m_log.InfoFormat("[CLIENTVIEW] Memory pre GC {0}", System.GC.GetTotalMemory(false));
571 //GC.Collect(); 617 //GC.Collect();
572 //m_log.InfoFormat("[CLIENTVIEW] Memory post GC {0}", System.GC.GetTotalMemory(true)); 618 //m_log.InfoFormat("[CLIENTVIEW] Memory post GC {0}", System.GC.GetTotalMemory(true));
@@ -858,6 +904,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
858 904
859 public void MoveAgentIntoRegion(RegionInfo regInfo, Vector3 pos, Vector3 look) 905 public void MoveAgentIntoRegion(RegionInfo regInfo, Vector3 pos, Vector3 look)
860 { 906 {
907 m_thisAgentUpdateArgs.CameraAtAxis.X = float.MinValue;
908 m_thisAgentUpdateArgs.ControlFlags = uint.MaxValue;
909
861 AgentMovementCompletePacket mov = (AgentMovementCompletePacket)PacketPool.Instance.GetPacket(PacketType.AgentMovementComplete); 910 AgentMovementCompletePacket mov = (AgentMovementCompletePacket)PacketPool.Instance.GetPacket(PacketType.AgentMovementComplete);
862 mov.SimData.ChannelVersion = m_channelVersion; 911 mov.SimData.ChannelVersion = m_channelVersion;
863 mov.AgentData.SessionID = m_sessionId; 912 mov.AgentData.SessionID = m_sessionId;
@@ -893,7 +942,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
893 reply.ChatData.OwnerID = ownerID; 942 reply.ChatData.OwnerID = ownerID;
894 reply.ChatData.SourceID = fromAgentID; 943 reply.ChatData.SourceID = fromAgentID;
895 944
896 OutPacket(reply, ThrottleOutPacketType.Task); 945 OutPacket(reply, ThrottleOutPacketType.Unknown);
897 } 946 }
898 947
899 /// <summary> 948 /// <summary>
@@ -926,32 +975,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
926 msg.MessageBlock.Message = Util.StringToBytes1024(im.message); 975 msg.MessageBlock.Message = Util.StringToBytes1024(im.message);
927 msg.MessageBlock.BinaryBucket = im.binaryBucket; 976 msg.MessageBlock.BinaryBucket = im.binaryBucket;
928 977
929 if (im.message.StartsWith("[grouptest]")) 978 OutPacket(msg, ThrottleOutPacketType.Task);
930 { // this block is test code for implementing group IM - delete when group IM is finished
931 IEventQueue eq = Scene.RequestModuleInterface<IEventQueue>();
932 if (eq != null)
933 {
934 im.dialog = 17;
935
936 //eq.ChatterboxInvitation(
937 // new UUID("00000000-68f9-1111-024e-222222111123"),
938 // "OpenSimulator Testing", im.fromAgentID, im.message, im.toAgentID, im.fromAgentName, im.dialog, 0,
939 // false, 0, new Vector3(), 1, im.imSessionID, im.fromGroup, im.binaryBucket);
940
941 eq.ChatterboxInvitation(
942 new UUID("00000000-68f9-1111-024e-222222111123"),
943 "OpenSimulator Testing", new UUID(im.fromAgentID), im.message, new UUID(im.toAgentID), im.fromAgentName, im.dialog, 0,
944 false, 0, new Vector3(), 1, new UUID(im.imSessionID), im.fromGroup, Util.StringToBytes256("OpenSimulator Testing"));
945
946 eq.ChatterBoxSessionAgentListUpdates(
947 new UUID("00000000-68f9-1111-024e-222222111123"),
948 new UUID(im.fromAgentID), new UUID(im.toAgentID), false, false, false);
949 }
950
951 Console.WriteLine("SendInstantMessage: " + msg);
952 }
953 else
954 OutPacket(msg, ThrottleOutPacketType.Task);
955 } 979 }
956 } 980 }
957 981
@@ -1182,6 +1206,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1182 OutPacket(GATRP, ThrottleOutPacketType.Task); 1206 OutPacket(GATRP, ThrottleOutPacketType.Task);
1183 } 1207 }
1184 1208
1209
1210 public virtual bool CanSendLayerData()
1211 {
1212 int n = m_udpClient.GetPacketsQueuedCount(ThrottleOutPacketType.Land);
1213 if ( n > 128)
1214 return false;
1215 return true;
1216 }
1217
1185 /// <summary> 1218 /// <summary>
1186 /// Send the region heightmap to the client 1219 /// Send the region heightmap to the client
1187 /// This method is only called when not doing intellegent terrain patch sending and 1220 /// This method is only called when not doing intellegent terrain patch sending and
@@ -1192,6 +1225,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1192 public virtual void SendLayerData(float[] map) 1225 public virtual void SendLayerData(float[] map)
1193 { 1226 {
1194 Util.FireAndForget(DoSendLayerData, m_scene.Heightmap.GetTerrainData(), "LLClientView.DoSendLayerData"); 1227 Util.FireAndForget(DoSendLayerData, m_scene.Heightmap.GetTerrainData(), "LLClientView.DoSendLayerData");
1228
1229 // Send it sync, and async. It's not that much data
1230 // and it improves user experience just so much!
1231// DoSendLayerData(map);
1195 } 1232 }
1196 1233
1197 /// <summary> 1234 /// <summary>
@@ -1214,7 +1251,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1214 //} 1251 //}
1215 1252
1216 // Send LayerData in a spiral pattern. Fun! 1253 // Send LayerData in a spiral pattern. Fun!
1217 SendLayerTopRight(map, 0, 0, map.SizeX/Constants.TerrainPatchSize-1, map.SizeY/Constants.TerrainPatchSize-1); 1254 SendLayerTopRight(map, 0, 0, map.SizeX / Constants.TerrainPatchSize - 1, map.SizeY / Constants.TerrainPatchSize - 1);
1218 } 1255 }
1219 catch (Exception e) 1256 catch (Exception e)
1220 { 1257 {
@@ -1250,23 +1287,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1250 SendLayerTopRight(map, x1 + 1, y1, x2, y2 - 1); 1287 SendLayerTopRight(map, x1 + 1, y1, x2, y2 - 1);
1251 } 1288 }
1252 1289
1253 /// <summary>
1254 /// Sends a set of four patches (x, x+1, ..., x+3) to the client
1255 /// </summary>
1256 /// <param name="map">heightmap</param>
1257 /// <param name="px">X coordinate for patches 0..12</param>
1258 /// <param name="py">Y coordinate for patches 0..15</param>
1259 // private void SendLayerPacket(float[] map, int y, int x)
1260 // {
1261 // int[] patches = new int[4];
1262 // patches[0] = x + 0 + y * 16;
1263 // patches[1] = x + 1 + y * 16;
1264 // patches[2] = x + 2 + y * 16;
1265 // patches[3] = x + 3 + y * 16;
1266
1267 // Packet layerpack = LLClientView.TerrainManager.CreateLandPacket(map, patches);
1268 // OutPacket(layerpack, ThrottleOutPacketType.Land);
1269 // }
1270 1290
1271 // Legacy form of invocation that passes around a bare data array. 1291 // Legacy form of invocation that passes around a bare data array.
1272 // Just ignore what was passed and use the real terrain info that is part of the scene. 1292 // Just ignore what was passed and use the real terrain info that is part of the scene.
@@ -1316,6 +1336,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1316 } 1336 }
1317 1337
1318 /// <summary> 1338 /// <summary>
1339
1319 /// Sends a terrain packet for the point specified. 1340 /// Sends a terrain packet for the point specified.
1320 /// This is a legacy call that has refarbed the terrain into a flat map of floats. 1341 /// This is a legacy call that has refarbed the terrain into a flat map of floats.
1321 /// We just use the terrain from the region we know about. 1342 /// We just use the terrain from the region we know about.
@@ -1334,32 +1355,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1334 { 1355 {
1335 try 1356 try
1336 { 1357 {
1337 /* test code using the terrain compressor in libOpenMetaverse 1358 byte landPacketType;
1338 int[] patchInd = new int[1]; 1359 if (terrData.SizeX > Constants.RegionSize || terrData.SizeY > Constants.RegionSize)
1339 patchInd[0] = px + (py * Constants.TerrainPatchSize); 1360 landPacketType = (byte)TerrainPatch.LayerType.LandExtended;
1340 LayerDataPacket layerpack = TerrainCompressor.CreateLandPacket(terrData.GetFloatsSerialized(), patchInd); 1361 else
1341 */ 1362 landPacketType = (byte)TerrainPatch.LayerType.Land;
1342 // Many, many patches could have been passed to us. Since the patches will be compressed
1343 // into variable sized blocks, we cannot pre-compute how many will fit into one
1344 // packet. While some fancy packing algorithm is possible, 4 seems to always fit.
1345 int PatchesAssumedToFit = 4;
1346 for (int pcnt = 0; pcnt < px.Length; pcnt += PatchesAssumedToFit)
1347 {
1348 int remaining = Math.Min(px.Length - pcnt, PatchesAssumedToFit);
1349 int[] xPatches = new int[remaining];
1350 int[] yPatches = new int[remaining];
1351 for (int ii = 0; ii < remaining; ii++)
1352 {
1353 xPatches[ii] = px[pcnt + ii];
1354 yPatches[ii] = py[pcnt + ii];
1355 }
1356 LayerDataPacket layerpack = OpenSimTerrainCompressor.CreateLandPacket(terrData, xPatches, yPatches);
1357 // DebugSendingPatches("SendLayerDataInternal", xPatches, yPatches);
1358
1359 SendTheLayerPacket(layerpack);
1360 }
1361 // LayerDataPacket layerpack = OpenSimTerrainCompressor.CreateLandPacket(terrData, px, py);
1362 1363
1364 List<LayerDataPacket> packets = OpenSimTerrainCompressor.CreateLayerDataPackets(terrData, px, py, landPacketType);
1365 foreach(LayerDataPacket pkt in packets)
1366 OutPacket(pkt, ThrottleOutPacketType.Land);
1363 } 1367 }
1364 catch (Exception e) 1368 catch (Exception e)
1365 { 1369 {
@@ -1367,36 +1371,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1367 } 1371 }
1368 } 1372 }
1369 1373
1370 // When a user edits the terrain, so much data is sent, the data queues up fast and presents a
1371 // sub optimal editing experience. To alleviate this issue, when the user edits the terrain, we
1372 // start skipping the queues until they're done editing the terrain. We also make them
1373 // unreliable because it's extremely likely that multiple packets will be sent for a terrain patch
1374 // area invalidating previous packets for that area.
1375
1376 // It's possible for an editing user to flood themselves with edited packets but the majority
1377 // of use cases are such that only a tiny percentage of users will be editing the terrain.
1378 // Other, non-editing users will see the edits much slower.
1379
1380 // One last note on this topic, by the time users are going to be editing the terrain, it's
1381 // extremely likely that the sim will have rezzed already and therefore this is not likely going
1382 // to cause any additional issues with lost packets, objects or terrain patches.
1383
1384 // m_justEditedTerrain is volatile, so test once and duplicate two affected statements so we
1385 // only have one cache miss.
1386 private void SendTheLayerPacket(LayerDataPacket layerpack)
1387 {
1388 if (m_justEditedTerrain)
1389 {
1390 layerpack.Header.Reliable = false;
1391 OutPacket(layerpack, ThrottleOutPacketType.Unknown );
1392 }
1393 else
1394 {
1395 layerpack.Header.Reliable = true;
1396 OutPacket(layerpack, ThrottleOutPacketType.Land);
1397 }
1398 }
1399
1400 /// <summary> 1374 /// <summary>
1401 /// Send the wind matrix to the client 1375 /// Send the wind matrix to the client
1402 /// </summary> 1376 /// </summary>
@@ -1432,13 +1406,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1432 patches[1].Data[x] = windSpeeds[x].Y; 1406 patches[1].Data[x] = windSpeeds[x].Y;
1433 } 1407 }
1434 1408
1409 // neither we or viewers have extended wind
1435 byte layerType = (byte)TerrainPatch.LayerType.Wind; 1410 byte layerType = (byte)TerrainPatch.LayerType.Wind;
1436 if (m_scene.RegionInfo.RegionSizeX > Constants.RegionSize || m_scene.RegionInfo.RegionSizeY > Constants.RegionSize)
1437 layerType = (byte)TerrainPatch.LayerType.WindExtended;
1438 1411
1439 // LayerDataPacket layerpack = TerrainCompressor.CreateLayerDataPacket(patches, (TerrainPatch.LayerType)layerType); 1412 LayerDataPacket layerpack = OpenSimTerrainCompressor.CreateLayerDataPacketStandardSize(patches, layerType);
1440 LayerDataPacket layerpack = OpenSimTerrainCompressor.CreateLayerDataPacket(patches, layerType,
1441 (int)m_scene.RegionInfo.RegionSizeX, (int)m_scene.RegionInfo.RegionSizeY);
1442 layerpack.Header.Zerocoded = true; 1413 layerpack.Header.Zerocoded = true;
1443 OutPacket(layerpack, ThrottleOutPacketType.Wind); 1414 OutPacket(layerpack, ThrottleOutPacketType.Wind);
1444 } 1415 }
@@ -1461,14 +1432,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1461 patches[0].Data[y * 16 + x] = cloudCover[y * 16 + x]; 1432 patches[0].Data[y * 16 + x] = cloudCover[y * 16 + x];
1462 } 1433 }
1463 } 1434 }
1464 1435 // neither we or viewers have extended clouds
1465 byte layerType = (byte)TerrainPatch.LayerType.Cloud; 1436 byte layerType = (byte)TerrainPatch.LayerType.Cloud;
1466 if (m_scene.RegionInfo.RegionSizeX > Constants.RegionSize || m_scene.RegionInfo.RegionSizeY > Constants.RegionSize)
1467 layerType = (byte)TerrainPatch.LayerType.CloudExtended;
1468 1437
1469 // LayerDataPacket layerpack = TerrainCompressor.CreateLayerDataPacket(patches, (TerrainPatch.LayerType)layerType); 1438 LayerDataPacket layerpack = OpenSimTerrainCompressor.CreateLayerDataPacketStandardSize(patches, layerType);
1470 LayerDataPacket layerpack = OpenSimTerrainCompressor.CreateLayerDataPacket(patches, layerType,
1471 (int)m_scene.RegionInfo.RegionSizeX, (int)m_scene.RegionInfo.RegionSizeY);
1472 layerpack.Header.Zerocoded = true; 1439 layerpack.Header.Zerocoded = true;
1473 OutPacket(layerpack, ThrottleOutPacketType.Cloud); 1440 OutPacket(layerpack, ThrottleOutPacketType.Cloud);
1474 } 1441 }
@@ -1735,11 +1702,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1735 pc.PingID.OldestUnacked = 0; 1702 pc.PingID.OldestUnacked = 0;
1736 1703
1737 OutPacket(pc, ThrottleOutPacketType.Unknown); 1704 OutPacket(pc, ThrottleOutPacketType.Unknown);
1705 UDPClient.m_lastStartpingTimeMS = Util.EnvironmentTickCount();
1738 } 1706 }
1739 1707
1740 public void SendKillObject(List<uint> localIDs) 1708 public void SendKillObject(List<uint> localIDs)
1741 { 1709 {
1742// m_log.DebugFormat("[CLIENT]: Sending KillObjectPacket to {0} for {1} in {2}", Name, localID, regionHandle); 1710 // think we do need this
1711 // foreach (uint id in localIDs)
1712 // m_log.DebugFormat("[CLIENT]: Sending KillObjectPacket to {0} for {1} in {2}", Name, id, regionHandle);
1713
1714 // remove pending entities
1715 lock (m_entityProps.SyncRoot)
1716 m_entityProps.Remove(localIDs);
1717 lock (m_entityUpdates.SyncRoot)
1718 m_entityUpdates.Remove(localIDs);
1743 1719
1744 KillObjectPacket kill = (KillObjectPacket)PacketPool.Instance.GetPacket(PacketType.KillObject); 1720 KillObjectPacket kill = (KillObjectPacket)PacketPool.Instance.GetPacket(PacketType.KillObject);
1745 // TODO: don't create new blocks if recycling an old packet 1721 // TODO: don't create new blocks if recycling an old packet
@@ -1752,28 +1728,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1752 kill.Header.Reliable = true; 1728 kill.Header.Reliable = true;
1753 kill.Header.Zerocoded = true; 1729 kill.Header.Zerocoded = true;
1754 1730
1755 if (localIDs.Count == 1 && m_scene.GetScenePresence(localIDs[0]) != null) 1731 OutPacket(kill, ThrottleOutPacketType.Task);
1756 { 1732 }
1757 OutPacket(kill, ThrottleOutPacketType.Task);
1758 }
1759 else
1760 {
1761 // We MUST lock for both manipulating the kill record and sending the packet, in order to avoid a race
1762 // condition where a kill can be processed before an out-of-date update for the same object.
1763 // ProcessEntityUpdates() also takes the m_killRecord lock.
1764 lock (m_killRecord)
1765 {
1766 foreach (uint localID in localIDs)
1767 m_killRecord.Add(localID);
1768
1769 // The throttle queue used here must match that being used for updates. Otherwise, there is a
1770 // chance that a kill packet put on a separate queue will be sent to the client before an existing
1771 // update packet on another queue. Receiving updates after kills results in unowned and undeletable
1772 // scene objects in a viewer until that viewer is relogged in.
1773 OutPacket(kill, ThrottleOutPacketType.Task);
1774 }
1775 }
1776 }
1777 1733
1778 /// <summary> 1734 /// <summary>
1779 /// Send information about the items contained in a folder to the client. 1735 /// Send information about the items contained in a folder to the client.
@@ -1895,7 +1851,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1895 newBlock.CreationDate = item.CreationDate; 1851 newBlock.CreationDate = item.CreationDate;
1896 newBlock.SalePrice = item.SalePrice; 1852 newBlock.SalePrice = item.SalePrice;
1897 newBlock.SaleType = item.SaleType; 1853 newBlock.SaleType = item.SaleType;
1898 newBlock.Flags = item.Flags; 1854 newBlock.Flags = item.Flags & 0x2000ff;
1899 1855
1900 newBlock.CRC = 1856 newBlock.CRC =
1901 Helpers.InventoryCRC(newBlock.CreationDate, newBlock.SaleType, 1857 Helpers.InventoryCRC(newBlock.CreationDate, newBlock.SaleType,
@@ -2151,7 +2107,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2151 itemBlock.GroupID = item.GroupID; 2107 itemBlock.GroupID = item.GroupID;
2152 itemBlock.GroupOwned = item.GroupOwned; 2108 itemBlock.GroupOwned = item.GroupOwned;
2153 itemBlock.GroupMask = item.GroupPermissions; 2109 itemBlock.GroupMask = item.GroupPermissions;
2154 itemBlock.Flags = item.Flags; 2110 itemBlock.Flags = item.Flags & 0x2000ff;
2155 itemBlock.SalePrice = item.SalePrice; 2111 itemBlock.SalePrice = item.SalePrice;
2156 itemBlock.SaleType = item.SaleType; 2112 itemBlock.SaleType = item.SaleType;
2157 itemBlock.CreationDate = item.CreationDate; 2113 itemBlock.CreationDate = item.CreationDate;
@@ -2218,7 +2174,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2218 bulkUpdate.ItemData[0].GroupID = item.GroupID; 2174 bulkUpdate.ItemData[0].GroupID = item.GroupID;
2219 bulkUpdate.ItemData[0].GroupOwned = item.GroupOwned; 2175 bulkUpdate.ItemData[0].GroupOwned = item.GroupOwned;
2220 bulkUpdate.ItemData[0].GroupMask = item.GroupPermissions; 2176 bulkUpdate.ItemData[0].GroupMask = item.GroupPermissions;
2221 bulkUpdate.ItemData[0].Flags = item.Flags; 2177 bulkUpdate.ItemData[0].Flags = item.Flags & 0x2000ff;
2222 bulkUpdate.ItemData[0].SalePrice = item.SalePrice; 2178 bulkUpdate.ItemData[0].SalePrice = item.SalePrice;
2223 bulkUpdate.ItemData[0].SaleType = item.SaleType; 2179 bulkUpdate.ItemData[0].SaleType = item.SaleType;
2224 2180
@@ -2234,9 +2190,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2234 OutPacket(bulkUpdate, ThrottleOutPacketType.Asset); 2190 OutPacket(bulkUpdate, ThrottleOutPacketType.Asset);
2235 } 2191 }
2236 2192
2237 /// <see>IClientAPI.SendInventoryItemCreateUpdate(InventoryItemBase)</see>
2238 public void SendInventoryItemCreateUpdate(InventoryItemBase Item, uint callbackId) 2193 public void SendInventoryItemCreateUpdate(InventoryItemBase Item, uint callbackId)
2239 { 2194 {
2195 SendInventoryItemCreateUpdate(Item, UUID.Zero, callbackId);
2196 }
2197
2198 /// <see>IClientAPI.SendInventoryItemCreateUpdate(InventoryItemBase)</see>
2199 public void SendInventoryItemCreateUpdate(InventoryItemBase Item, UUID transactionID, uint callbackId)
2200 {
2240 const uint FULL_MASK_PERMISSIONS = (uint)0x7fffffff; 2201 const uint FULL_MASK_PERMISSIONS = (uint)0x7fffffff;
2241 2202
2242 UpdateCreateInventoryItemPacket InventoryReply 2203 UpdateCreateInventoryItemPacket InventoryReply
@@ -2246,6 +2207,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2246 // TODO: don't create new blocks if recycling an old packet 2207 // TODO: don't create new blocks if recycling an old packet
2247 InventoryReply.AgentData.AgentID = AgentId; 2208 InventoryReply.AgentData.AgentID = AgentId;
2248 InventoryReply.AgentData.SimApproved = true; 2209 InventoryReply.AgentData.SimApproved = true;
2210 InventoryReply.AgentData.TransactionID = transactionID;
2249 InventoryReply.InventoryData = new UpdateCreateInventoryItemPacket.InventoryDataBlock[1]; 2211 InventoryReply.InventoryData = new UpdateCreateInventoryItemPacket.InventoryDataBlock[1];
2250 InventoryReply.InventoryData[0] = new UpdateCreateInventoryItemPacket.InventoryDataBlock(); 2212 InventoryReply.InventoryData[0] = new UpdateCreateInventoryItemPacket.InventoryDataBlock();
2251 InventoryReply.InventoryData[0].ItemID = Item.ID; 2213 InventoryReply.InventoryData[0].ItemID = Item.ID;
@@ -2266,7 +2228,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2266 InventoryReply.InventoryData[0].GroupID = Item.GroupID; 2228 InventoryReply.InventoryData[0].GroupID = Item.GroupID;
2267 InventoryReply.InventoryData[0].GroupOwned = Item.GroupOwned; 2229 InventoryReply.InventoryData[0].GroupOwned = Item.GroupOwned;
2268 InventoryReply.InventoryData[0].GroupMask = Item.GroupPermissions; 2230 InventoryReply.InventoryData[0].GroupMask = Item.GroupPermissions;
2269 InventoryReply.InventoryData[0].Flags = Item.Flags; 2231 InventoryReply.InventoryData[0].Flags = Item.Flags & 0x2000ff;
2270 InventoryReply.InventoryData[0].SalePrice = Item.SalePrice; 2232 InventoryReply.InventoryData[0].SalePrice = Item.SalePrice;
2271 InventoryReply.InventoryData[0].SaleType = Item.SaleType; 2233 InventoryReply.InventoryData[0].SaleType = Item.SaleType;
2272 InventoryReply.InventoryData[0].CreationDate = Item.CreationDate; 2234 InventoryReply.InventoryData[0].CreationDate = Item.CreationDate;
@@ -2315,16 +2277,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2315 replytask.InventoryData.TaskID = taskID; 2277 replytask.InventoryData.TaskID = taskID;
2316 replytask.InventoryData.Serial = serial; 2278 replytask.InventoryData.Serial = serial;
2317 replytask.InventoryData.Filename = fileName; 2279 replytask.InventoryData.Filename = fileName;
2318 OutPacket(replytask, ThrottleOutPacketType.Asset); 2280 OutPacket(replytask, ThrottleOutPacketType.Task);
2319 } 2281 }
2320 2282
2321 public void SendXferPacket(ulong xferID, uint packet, byte[] data) 2283 public void SendXferPacket(ulong xferID, uint packet, byte[] data, bool isTaskInventory)
2322 { 2284 {
2285 ThrottleOutPacketType type = ThrottleOutPacketType.Asset;
2286 if (isTaskInventory)
2287 type = ThrottleOutPacketType.Task;
2288
2323 SendXferPacketPacket sendXfer = (SendXferPacketPacket)PacketPool.Instance.GetPacket(PacketType.SendXferPacket); 2289 SendXferPacketPacket sendXfer = (SendXferPacketPacket)PacketPool.Instance.GetPacket(PacketType.SendXferPacket);
2324 sendXfer.XferID.ID = xferID; 2290 sendXfer.XferID.ID = xferID;
2325 sendXfer.XferID.Packet = packet; 2291 sendXfer.XferID.Packet = packet;
2326 sendXfer.DataPacket.Data = data; 2292 sendXfer.DataPacket.Data = data;
2327 OutPacket(sendXfer, ThrottleOutPacketType.Asset); 2293 OutPacket(sendXfer, type);
2328 } 2294 }
2329 2295
2330 public void SendAbortXferPacket(ulong xferID) 2296 public void SendAbortXferPacket(ulong xferID)
@@ -2471,14 +2437,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2471 // this is the username of the *owner* 2437 // this is the username of the *owner*
2472 dialog.Data.FirstName = Util.StringToBytes256(ownerFirstName); 2438 dialog.Data.FirstName = Util.StringToBytes256(ownerFirstName);
2473 dialog.Data.LastName = Util.StringToBytes256(ownerLastName); 2439 dialog.Data.LastName = Util.StringToBytes256(ownerLastName);
2474 dialog.Data.Message = Util.StringToBytes1024(msg); 2440 dialog.Data.Message = Util.StringToBytes(msg,512);
2475 dialog.Data.ImageID = textureID; 2441 dialog.Data.ImageID = textureID;
2476 dialog.Data.ChatChannel = ch; 2442 dialog.Data.ChatChannel = ch;
2477 ScriptDialogPacket.ButtonsBlock[] buttons = new ScriptDialogPacket.ButtonsBlock[buttonlabels.Length]; 2443 ScriptDialogPacket.ButtonsBlock[] buttons = new ScriptDialogPacket.ButtonsBlock[buttonlabels.Length];
2478 for (int i = 0; i < buttonlabels.Length; i++) 2444 for (int i = 0; i < buttonlabels.Length; i++)
2479 { 2445 {
2480 buttons[i] = new ScriptDialogPacket.ButtonsBlock(); 2446 buttons[i] = new ScriptDialogPacket.ButtonsBlock();
2481 buttons[i].ButtonLabel = Util.StringToBytes256(buttonlabels[i]); 2447 buttons[i].ButtonLabel = Util.StringToBytes(buttonlabels[i],24);
2482 } 2448 }
2483 dialog.Buttons = buttons; 2449 dialog.Buttons = buttons;
2484 2450
@@ -2514,6 +2480,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2514 OutPacket(sound, ThrottleOutPacketType.Task); 2480 OutPacket(sound, ThrottleOutPacketType.Task);
2515 } 2481 }
2516 2482
2483 public void SendTransferAbort(TransferRequestPacket transferRequest)
2484 {
2485 TransferAbortPacket abort = (TransferAbortPacket)PacketPool.Instance.GetPacket(PacketType.TransferAbort);
2486 abort.TransferInfo.TransferID = transferRequest.TransferInfo.TransferID;
2487 abort.TransferInfo.ChannelType = transferRequest.TransferInfo.ChannelType;
2488 m_log.Debug("[Assets] Aborting transfer; asset request failed");
2489 OutPacket(abort, ThrottleOutPacketType.Task);
2490 }
2491
2517 public void SendTriggeredSound(UUID soundID, UUID ownerID, UUID objectID, UUID parentID, ulong handle, Vector3 position, float gain) 2492 public void SendTriggeredSound(UUID soundID, UUID ownerID, UUID objectID, UUID parentID, ulong handle, Vector3 position, float gain)
2518 { 2493 {
2519 SoundTriggerPacket sound = (SoundTriggerPacket)PacketPool.Instance.GetPacket(PacketType.SoundTrigger); 2494 SoundTriggerPacket sound = (SoundTriggerPacket)PacketPool.Instance.GetPacket(PacketType.SoundTrigger);
@@ -2730,8 +2705,24 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2730 OutPacket(offp, ThrottleOutPacketType.Task); 2705 OutPacket(offp, ThrottleOutPacketType.Task);
2731 } 2706 }
2732 2707
2733 public void SendSitResponse(UUID TargetID, Vector3 OffsetPos, Quaternion SitOrientation, bool autopilot, 2708 public void SendFindAgent(UUID HunterID, UUID PreyID, double GlobalX, double GlobalY)
2734 Vector3 CameraAtOffset, Vector3 CameraEyeOffset, bool ForceMouseLook) 2709 {
2710 FindAgentPacket fap = new FindAgentPacket();
2711 fap.AgentBlock.Hunter = HunterID;
2712 fap.AgentBlock.Prey = PreyID;
2713 fap.AgentBlock.SpaceIP = 0;
2714
2715 fap.LocationBlock = new FindAgentPacket.LocationBlockBlock[1];
2716 fap.LocationBlock[0] = new FindAgentPacket.LocationBlockBlock();
2717 fap.LocationBlock[0].GlobalX = GlobalX;
2718 fap.LocationBlock[0].GlobalY = GlobalY;
2719
2720 OutPacket(fap, ThrottleOutPacketType.Task);
2721 }
2722
2723 public void SendSitResponse(UUID TargetID, Vector3 OffsetPos,
2724 Quaternion SitOrientation, bool autopilot,
2725 Vector3 CameraAtOffset, Vector3 CameraEyeOffset, bool ForceMouseLook)
2735 { 2726 {
2736 AvatarSitResponsePacket avatarSitResponse = new AvatarSitResponsePacket(); 2727 AvatarSitResponsePacket avatarSitResponse = new AvatarSitResponsePacket();
2737 avatarSitResponse.SitObject.ID = TargetID; 2728 avatarSitResponse.SitObject.ID = TargetID;
@@ -2819,6 +2810,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2819 float friction = part.Friction; 2810 float friction = part.Friction;
2820 float bounce = part.Restitution; 2811 float bounce = part.Restitution;
2821 float gravmod = part.GravityModifier; 2812 float gravmod = part.GravityModifier;
2813
2822 eq.partPhysicsProperties(localid, physshapetype, density, friction, bounce, gravmod,AgentId); 2814 eq.partPhysicsProperties(localid, physshapetype, density, friction, bounce, gravmod,AgentId);
2823 } 2815 }
2824 } 2816 }
@@ -2889,8 +2881,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2889 LogHeader, req.AssetInf.ID, req.AssetInf.Metadata.ContentType); 2881 LogHeader, req.AssetInf.ID, req.AssetInf.Metadata.ContentType);
2890 return; 2882 return;
2891 } 2883 }
2884 int WearableOut = 0;
2885 bool isWearable = false;
2886
2887 if (req.AssetInf != null)
2888 isWearable =
2889 ((AssetType) req.AssetInf.Type ==
2890 AssetType.Bodypart || (AssetType) req.AssetInf.Type == AssetType.Clothing);
2892 2891
2893 //m_log.Debug("sending asset " + req.RequestAssetID); 2892
2893 //m_log.Debug("sending asset " + req.RequestAssetID + ", iswearable: " + isWearable);
2894
2895
2896 //if (isWearable)
2897 // m_log.Debug((AssetType)req.AssetInf.Type);
2898
2894 TransferInfoPacket Transfer = new TransferInfoPacket(); 2899 TransferInfoPacket Transfer = new TransferInfoPacket();
2895 Transfer.TransferInfo.ChannelType = 2; 2900 Transfer.TransferInfo.ChannelType = 2;
2896 Transfer.TransferInfo.Status = 0; 2901 Transfer.TransferInfo.Status = 0;
@@ -2912,7 +2917,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2912 Transfer.TransferInfo.Size = req.AssetInf.Data.Length; 2917 Transfer.TransferInfo.Size = req.AssetInf.Data.Length;
2913 Transfer.TransferInfo.TransferID = req.TransferRequestID; 2918 Transfer.TransferInfo.TransferID = req.TransferRequestID;
2914 Transfer.Header.Zerocoded = true; 2919 Transfer.Header.Zerocoded = true;
2915 OutPacket(Transfer, ThrottleOutPacketType.Asset); 2920 OutPacket(Transfer, isWearable ? ThrottleOutPacketType.Task | ThrottleOutPacketType.HighPriority : ThrottleOutPacketType.Asset);
2916 2921
2917 if (req.NumPackets == 1) 2922 if (req.NumPackets == 1)
2918 { 2923 {
@@ -2923,12 +2928,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2923 TransferPacket.TransferData.Data = req.AssetInf.Data; 2928 TransferPacket.TransferData.Data = req.AssetInf.Data;
2924 TransferPacket.TransferData.Status = 1; 2929 TransferPacket.TransferData.Status = 1;
2925 TransferPacket.Header.Zerocoded = true; 2930 TransferPacket.Header.Zerocoded = true;
2926 OutPacket(TransferPacket, ThrottleOutPacketType.Asset); 2931 OutPacket(TransferPacket, isWearable ? ThrottleOutPacketType.Task | ThrottleOutPacketType.HighPriority : ThrottleOutPacketType.Asset);
2927 } 2932 }
2928 else 2933 else
2929 { 2934 {
2930 int processedLength = 0; 2935 int processedLength = 0;
2931 int maxChunkSize = Settings.MAX_PACKET_SIZE - 100; 2936// int maxChunkSize = Settings.MAX_PACKET_SIZE - 100;
2937
2938 int maxChunkSize = (int) MaxTransferBytesPerPacket;
2932 int packetNumber = 0; 2939 int packetNumber = 0;
2933 2940
2934 while (processedLength < req.AssetInf.Data.Length) 2941 while (processedLength < req.AssetInf.Data.Length)
@@ -2954,7 +2961,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2954 TransferPacket.TransferData.Status = 1; 2961 TransferPacket.TransferData.Status = 1;
2955 } 2962 }
2956 TransferPacket.Header.Zerocoded = true; 2963 TransferPacket.Header.Zerocoded = true;
2957 OutPacket(TransferPacket, ThrottleOutPacketType.Asset); 2964 OutPacket(TransferPacket, isWearable ? ThrottleOutPacketType.Task | ThrottleOutPacketType.HighPriority : ThrottleOutPacketType.Asset);
2958 2965
2959 processedLength += chunkSize; 2966 processedLength += chunkSize;
2960 packetNumber++; 2967 packetNumber++;
@@ -2999,7 +3006,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2999 reply.Data.ParcelID = parcelID; 3006 reply.Data.ParcelID = parcelID;
3000 reply.Data.OwnerID = land.OwnerID; 3007 reply.Data.OwnerID = land.OwnerID;
3001 reply.Data.Name = Utils.StringToBytes(land.Name); 3008 reply.Data.Name = Utils.StringToBytes(land.Name);
3002 reply.Data.Desc = Utils.StringToBytes(land.Description); 3009 if (land != null && land.Description != null && land.Description != String.Empty)
3010 reply.Data.Desc = Utils.StringToBytes(land.Description.Substring(0, land.Description.Length > 254 ? 254: land.Description.Length));
3011 else
3012 reply.Data.Desc = new Byte[0];
3003 reply.Data.ActualArea = land.Area; 3013 reply.Data.ActualArea = land.Area;
3004 reply.Data.BillableArea = land.Area; // TODO: what is this? 3014 reply.Data.BillableArea = land.Area; // TODO: what is this?
3005 3015
@@ -3385,7 +3395,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3385 AgentData.Add(AgentDataMap); 3395 AgentData.Add(AgentDataMap);
3386 llsd.Add("AgentData", AgentData); 3396 llsd.Add("AgentData", AgentData);
3387 OSDArray GroupData = new OSDArray(data.Length); 3397 OSDArray GroupData = new OSDArray(data.Length);
3388 OSDArray NewGroupData = new OSDArray(data.Length); 3398// OSDArray NewGroupData = new OSDArray(data.Length);
3389 foreach (GroupMembershipData m in data) 3399 foreach (GroupMembershipData m in data)
3390 { 3400 {
3391 OSDMap GroupDataMap = new OSDMap(6); 3401 OSDMap GroupDataMap = new OSDMap(6);
@@ -3396,12 +3406,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3396 GroupDataMap.Add("GroupID", OSD.FromUUID(m.GroupID)); 3406 GroupDataMap.Add("GroupID", OSD.FromUUID(m.GroupID));
3397 GroupDataMap.Add("GroupName", OSD.FromString(m.GroupName)); 3407 GroupDataMap.Add("GroupName", OSD.FromString(m.GroupName));
3398 GroupDataMap.Add("GroupInsigniaID", OSD.FromUUID(m.GroupPicture)); 3408 GroupDataMap.Add("GroupInsigniaID", OSD.FromUUID(m.GroupPicture));
3399 NewGroupDataMap.Add("ListInProfile", OSD.FromBoolean(m.ListInProfile)); 3409// NewGroupDataMap.Add("ListInProfile", OSD.FromBoolean(m.ListInProfile));
3400 GroupData.Add(GroupDataMap); 3410 GroupData.Add(GroupDataMap);
3401 NewGroupData.Add(NewGroupDataMap); 3411// NewGroupData.Add(NewGroupDataMap);
3402 } 3412 }
3403 llsd.Add("GroupData", GroupData); 3413 llsd.Add("GroupData", GroupData);
3404 llsd.Add("NewGroupData", NewGroupData); 3414 // llsd.Add("NewGroupData", NewGroupData);
3405 3415
3406 IEventQueue eq = this.Scene.RequestModuleInterface<IEventQueue>(); 3416 IEventQueue eq = this.Scene.RequestModuleInterface<IEventQueue>();
3407 if (eq != null) 3417 if (eq != null)
@@ -3410,6 +3420,45 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3410 } 3420 }
3411 } 3421 }
3412 3422
3423 public void SendAgentGroupDataUpdate(UUID avatarID, GroupMembershipData[] data)
3424 {
3425 IEventQueue eq = this.Scene.RequestModuleInterface<IEventQueue>();
3426
3427 // use UDP if no caps
3428 if (eq == null)
3429 {
3430 SendGroupMembership(data);
3431 }
3432
3433 OSDMap llsd = new OSDMap(3);
3434 OSDArray AgentData = new OSDArray(1);
3435 OSDMap AgentDataMap = new OSDMap(1);
3436 AgentDataMap.Add("AgentID", OSD.FromUUID(this.AgentId));
3437 AgentDataMap.Add("AvatarID", OSD.FromUUID(avatarID));
3438 AgentData.Add(AgentDataMap);
3439 llsd.Add("AgentData", AgentData);
3440 OSDArray GroupData = new OSDArray(data.Length);
3441 OSDArray NewGroupData = new OSDArray(data.Length);
3442 foreach (GroupMembershipData m in data)
3443 {
3444 OSDMap GroupDataMap = new OSDMap(6);
3445 OSDMap NewGroupDataMap = new OSDMap(1);
3446 GroupDataMap.Add("GroupPowers", OSD.FromULong(m.GroupPowers));
3447 GroupDataMap.Add("AcceptNotices", OSD.FromBoolean(m.AcceptNotices));
3448 GroupDataMap.Add("GroupTitle", OSD.FromString(m.GroupTitle));
3449 GroupDataMap.Add("GroupID", OSD.FromUUID(m.GroupID));
3450 GroupDataMap.Add("GroupName", OSD.FromString(m.GroupName));
3451 GroupDataMap.Add("GroupInsigniaID", OSD.FromUUID(m.GroupPicture));
3452 NewGroupDataMap.Add("ListInProfile", OSD.FromBoolean(m.ListInProfile));
3453 GroupData.Add(GroupDataMap);
3454 NewGroupData.Add(NewGroupDataMap);
3455 }
3456 llsd.Add("GroupData", GroupData);
3457 llsd.Add("NewGroupData", NewGroupData);
3458
3459 eq.Enqueue(BuildEvent("AgentGroupDataUpdate", llsd), this.AgentId);
3460 }
3461
3413 public void SendJoinGroupReply(UUID groupID, bool success) 3462 public void SendJoinGroupReply(UUID groupID, bool success)
3414 { 3463 {
3415 JoinGroupReplyPacket p = (JoinGroupReplyPacket)PacketPool.Instance.GetPacket(PacketType.JoinGroupReply); 3464 JoinGroupReplyPacket p = (JoinGroupReplyPacket)PacketPool.Instance.GetPacket(PacketType.JoinGroupReply);
@@ -3706,24 +3755,25 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3706 aw.WearableData = new AgentWearablesUpdatePacket.WearableDataBlock[count]; 3755 aw.WearableData = new AgentWearablesUpdatePacket.WearableDataBlock[count];
3707 AgentWearablesUpdatePacket.WearableDataBlock awb; 3756 AgentWearablesUpdatePacket.WearableDataBlock awb;
3708 int idx = 0; 3757 int idx = 0;
3709 for (int i = 0; i < wearables.Length; i++) 3758
3710 { 3759 for (int i = 0; i < wearables.Length; i++)
3711 for (int j = 0; j < wearables[i].Count; j++) 3760 {
3712 { 3761 for (int j = 0; j < wearables[i].Count; j++)
3713 awb = new AgentWearablesUpdatePacket.WearableDataBlock(); 3762 {
3714 awb.WearableType = (byte)i; 3763 awb = new AgentWearablesUpdatePacket.WearableDataBlock();
3715 awb.AssetID = wearables[i][j].AssetID; 3764 awb.WearableType = (byte) i;
3716 awb.ItemID = wearables[i][j].ItemID; 3765 awb.AssetID = wearables[i][j].AssetID;
3717 aw.WearableData[idx] = awb; 3766 awb.ItemID = wearables[i][j].ItemID;
3718 idx++; 3767 aw.WearableData[idx] = awb;
3719 3768 idx++;
3720// m_log.DebugFormat( 3769
3721// "[APPEARANCE]: Sending wearable item/asset {0} {1} (index {2}) for {3}", 3770 // m_log.DebugFormat(
3722// awb.ItemID, awb.AssetID, i, Name); 3771 // "[APPEARANCE]: Sending wearable item/asset {0} {1} (index {2}) for {3}",
3723 } 3772 // awb.ItemID, awb.AssetID, i, Name);
3724 } 3773 }
3774 }
3725 3775
3726 OutPacket(aw, ThrottleOutPacketType.Task); 3776 OutPacket(aw, ThrottleOutPacketType.Task | ThrottleOutPacketType.HighPriority);
3727 } 3777 }
3728 3778
3729 public void SendAppearance(UUID agentID, byte[] visualParams, byte[] textureEntry) 3779 public void SendAppearance(UUID agentID, byte[] visualParams, byte[] textureEntry)
@@ -3749,8 +3799,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3749 avp.Sender.ID = agentID; 3799 avp.Sender.ID = agentID;
3750 avp.AppearanceData = new AvatarAppearancePacket.AppearanceDataBlock[0]; 3800 avp.AppearanceData = new AvatarAppearancePacket.AppearanceDataBlock[0];
3751 avp.AppearanceHover = new AvatarAppearancePacket.AppearanceHoverBlock[0]; 3801 avp.AppearanceHover = new AvatarAppearancePacket.AppearanceHoverBlock[0];
3802
3803// this need be use in future ?
3804// avp.AppearanceData[0].AppearanceVersion = 0;
3805// avp.AppearanceData[0].CofVersion = 0;
3806
3752 //m_log.DebugFormat("[CLIENT]: Sending appearance for {0} to {1}", agentID.ToString(), AgentId.ToString()); 3807 //m_log.DebugFormat("[CLIENT]: Sending appearance for {0} to {1}", agentID.ToString(), AgentId.ToString());
3753 OutPacket(avp, ThrottleOutPacketType.Task); 3808 OutPacket(avp, ThrottleOutPacketType.Task | ThrottleOutPacketType.HighPriority);
3754 } 3809 }
3755 3810
3756 public void SendAnimations(UUID[] animations, int[] seqs, UUID sourceAgentId, UUID[] objectIDs) 3811 public void SendAnimations(UUID[] animations, int[] seqs, UUID sourceAgentId, UUID[] objectIDs)
@@ -3778,7 +3833,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3778 ani.AnimationSourceList[i].ObjectID = objectIDs[i]; 3833 ani.AnimationSourceList[i].ObjectID = objectIDs[i];
3779 } 3834 }
3780 ani.Header.Reliable = false; 3835 ani.Header.Reliable = false;
3781 OutPacket(ani, ThrottleOutPacketType.Task); 3836 OutPacket(ani, ThrottleOutPacketType.Task | ThrottleOutPacketType.HighPriority);
3782 } 3837 }
3783 3838
3784 #endregion 3839 #endregion
@@ -3802,12 +3857,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3802 objupdate.Header.Zerocoded = true; 3857 objupdate.Header.Zerocoded = true;
3803 3858
3804 objupdate.RegionData.RegionHandle = presence.RegionHandle; 3859 objupdate.RegionData.RegionHandle = presence.RegionHandle;
3805 objupdate.RegionData.TimeDilation = ushort.MaxValue; 3860// objupdate.RegionData.TimeDilation = ushort.MaxValue;
3806 3861 objupdate.RegionData.TimeDilation = Utils.FloatToUInt16(m_scene.TimeDilation, 0.0f, 1.0f);
3807 objupdate.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[1]; 3862 objupdate.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[1];
3808 objupdate.ObjectData[0] = CreateAvatarUpdateBlock(presence); 3863 objupdate.ObjectData[0] = CreateAvatarUpdateBlock(presence);
3809 3864
3810 OutPacket(objupdate, ThrottleOutPacketType.Task); 3865 OutPacket(objupdate, ThrottleOutPacketType.Task | ThrottleOutPacketType.HighPriority);
3811 3866
3812 // We need to record the avatar local id since the root prim of an attachment points to this. 3867 // We need to record the avatar local id since the root prim of an attachment points to this.
3813// m_attachmentsSent.Add(avatar.LocalId); 3868// m_attachmentsSent.Add(avatar.LocalId);
@@ -3866,6 +3921,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3866 /// </summary> 3921 /// </summary>
3867 public void SendEntityUpdate(ISceneEntity entity, PrimUpdateFlags updateFlags) 3922 public void SendEntityUpdate(ISceneEntity entity, PrimUpdateFlags updateFlags)
3868 { 3923 {
3924/*
3869 if (entity.UUID == m_agentId && !updateFlags.HasFlag(PrimUpdateFlags.FullUpdate)) 3925 if (entity.UUID == m_agentId && !updateFlags.HasFlag(PrimUpdateFlags.FullUpdate))
3870 { 3926 {
3871 ImprovedTerseObjectUpdatePacket packet 3927 ImprovedTerseObjectUpdatePacket packet
@@ -3876,15 +3932,22 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3876 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[1]; 3932 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[1];
3877 packet.ObjectData[0] = CreateImprovedTerseBlock(entity, false); 3933 packet.ObjectData[0] = CreateImprovedTerseBlock(entity, false);
3878 OutPacket(packet, ThrottleOutPacketType.Unknown, true); 3934 OutPacket(packet, ThrottleOutPacketType.Unknown, true);
3935 return;
3879 } 3936 }
3880 else 3937*/
3938 if (entity is SceneObjectPart)
3881 { 3939 {
3882 //double priority = m_prioritizer.GetUpdatePriority(this, entity); 3940 SceneObjectPart e = (SceneObjectPart)entity;
3883 uint priority = m_prioritizer.GetUpdatePriority(this, entity); 3941 SceneObjectGroup g = e.ParentGroup;
3884 3942 if (g.HasPrivateAttachmentPoint && g.OwnerID != AgentId)
3885 lock (m_entityUpdates.SyncRoot) 3943 return; // Don't send updates for other people's HUDs
3886 m_entityUpdates.Enqueue(priority, new EntityUpdate(entity, updateFlags, m_scene.TimeDilation));
3887 } 3944 }
3945
3946 //double priority = m_prioritizer.GetUpdatePriority(this, entity);
3947 uint priority = m_prioritizer.GetUpdatePriority(this, entity);
3948
3949 lock (m_entityUpdates.SyncRoot)
3950 m_entityUpdates.Enqueue(priority, new EntityUpdate(entity, updateFlags, m_scene.TimeDilation));
3888 } 3951 }
3889 3952
3890 /// <summary> 3953 /// <summary>
@@ -3894,8 +3957,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3894 /// The original update time is used for the merged update. 3957 /// The original update time is used for the merged update.
3895 /// </summary> 3958 /// </summary>
3896 private void ResendPrimUpdate(EntityUpdate update) 3959 private void ResendPrimUpdate(EntityUpdate update)
3897 { 3960 {
3898 // If the update exists in priority queue, it will be updated. 3961 // If the update exists in priority queue, it will be updated.
3899 // If it does not exist then it will be added with the current (rather than its original) priority 3962 // If it does not exist then it will be added with the current (rather than its original) priority
3900 uint priority = m_prioritizer.GetUpdatePriority(this, update.Entity); 3963 uint priority = m_prioritizer.GetUpdatePriority(this, update.Entity);
3901 3964
@@ -3919,7 +3982,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3919 m_udpClient.NeedAcks.Remove(oPacket.SequenceNumber); 3982 m_udpClient.NeedAcks.Remove(oPacket.SequenceNumber);
3920 3983
3921 // Count this as a resent packet since we are going to requeue all of the updates contained in it 3984 // Count this as a resent packet since we are going to requeue all of the updates contained in it
3922 Interlocked.Increment(ref m_udpClient.PacketsResent); 3985 Interlocked.Increment(ref m_udpClient.PacketsResent);
3923 3986
3924 // We're not going to worry about interlock yet since its not currently critical that this total count 3987 // We're not going to worry about interlock yet since its not currently critical that this total count
3925 // is 100% correct 3988 // is 100% correct
@@ -3928,18 +3991,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3928 foreach (EntityUpdate update in updates) 3991 foreach (EntityUpdate update in updates)
3929 ResendPrimUpdate(update); 3992 ResendPrimUpdate(update);
3930 } 3993 }
3931 3994
3932// OpenSim.Framework.Lazy<List<ObjectUpdatePacket.ObjectDataBlock>> objectUpdateBlocks = new OpenSim.Framework.Lazy<List<ObjectUpdatePacket.ObjectDataBlock>>();
3933// OpenSim.Framework.Lazy<List<ObjectUpdateCompressedPacket.ObjectDataBlock>> compressedUpdateBlocks = new OpenSim.Framework.Lazy<List<ObjectUpdateCompressedPacket.ObjectDataBlock>>();
3934// OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>> terseUpdateBlocks = new OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>>();
3935// OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>> terseAgentUpdateBlocks = new OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>>();
3936//
3937// OpenSim.Framework.Lazy<List<EntityUpdate>> objectUpdates = new OpenSim.Framework.Lazy<List<EntityUpdate>>();
3938// OpenSim.Framework.Lazy<List<EntityUpdate>> compressedUpdates = new OpenSim.Framework.Lazy<List<EntityUpdate>>();
3939// OpenSim.Framework.Lazy<List<EntityUpdate>> terseUpdates = new OpenSim.Framework.Lazy<List<EntityUpdate>>();
3940// OpenSim.Framework.Lazy<List<EntityUpdate>> terseAgentUpdates = new OpenSim.Framework.Lazy<List<EntityUpdate>>();
3941
3942
3943 private void ProcessEntityUpdates(int maxUpdates) 3995 private void ProcessEntityUpdates(int maxUpdates)
3944 { 3996 {
3945 OpenSim.Framework.Lazy<List<ObjectUpdatePacket.ObjectDataBlock>> objectUpdateBlocks = new OpenSim.Framework.Lazy<List<ObjectUpdatePacket.ObjectDataBlock>>(); 3997 OpenSim.Framework.Lazy<List<ObjectUpdatePacket.ObjectDataBlock>> objectUpdateBlocks = new OpenSim.Framework.Lazy<List<ObjectUpdatePacket.ObjectDataBlock>>();
@@ -3952,15 +4004,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3952 OpenSim.Framework.Lazy<List<EntityUpdate>> terseUpdates = new OpenSim.Framework.Lazy<List<EntityUpdate>>(); 4004 OpenSim.Framework.Lazy<List<EntityUpdate>> terseUpdates = new OpenSim.Framework.Lazy<List<EntityUpdate>>();
3953 OpenSim.Framework.Lazy<List<EntityUpdate>> terseAgentUpdates = new OpenSim.Framework.Lazy<List<EntityUpdate>>(); 4005 OpenSim.Framework.Lazy<List<EntityUpdate>> terseAgentUpdates = new OpenSim.Framework.Lazy<List<EntityUpdate>>();
3954 4006
3955// objectUpdateBlocks.Value.Clear();
3956// compressedUpdateBlocks.Value.Clear();
3957// terseUpdateBlocks.Value.Clear();
3958// terseAgentUpdateBlocks.Value.Clear();
3959// objectUpdates.Value.Clear();
3960// compressedUpdates.Value.Clear();
3961// terseUpdates.Value.Clear();
3962// terseAgentUpdates.Value.Clear();
3963
3964 // Check to see if this is a flush 4007 // Check to see if this is a flush
3965 if (maxUpdates <= 0) 4008 if (maxUpdates <= 0)
3966 { 4009 {
@@ -3971,54 +4014,71 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3971 4014
3972 // We must lock for both manipulating the kill record and sending the packet, in order to avoid a race 4015 // We must lock for both manipulating the kill record and sending the packet, in order to avoid a race
3973 // condition where a kill can be processed before an out-of-date update for the same object. 4016 // condition where a kill can be processed before an out-of-date update for the same object.
3974 lock (m_killRecord) 4017// float avgTimeDilation = 0.0f;
4018 IEntityUpdate iupdate;
4019 Int32 timeinqueue; // this is just debugging code & can be dropped later
4020
4021 while (updatesThisCall < maxUpdates)
3975 { 4022 {
3976 float avgTimeDilation = 1.0f; 4023 lock (m_entityUpdates.SyncRoot)
3977 IEntityUpdate iupdate; 4024 if (!m_entityUpdates.TryDequeue(out iupdate, out timeinqueue))
3978 Int32 timeinqueue; // this is just debugging code & can be dropped later 4025 break;
3979 4026
3980 while (updatesThisCall < maxUpdates) 4027 EntityUpdate update = (EntityUpdate)iupdate;
4028
4029// avgTimeDilation += update.TimeDilation;
4030
4031 if (update.Entity is SceneObjectPart)
3981 { 4032 {
3982 lock (m_entityUpdates.SyncRoot) 4033 SceneObjectPart part = (SceneObjectPart)update.Entity;
3983 if (!m_entityUpdates.TryDequeue(out iupdate, out timeinqueue))
3984 break;
3985 4034
3986 EntityUpdate update = (EntityUpdate)iupdate; 4035 if (part.ParentGroup.IsDeleted || part.ParentGroup.inTransit)
3987 4036 continue;
3988 avgTimeDilation += update.TimeDilation;
3989 avgTimeDilation *= 0.5f;
3990 4037
3991 if (update.Entity is SceneObjectPart) 4038 if (part.ParentGroup.IsAttachment)
3992 { 4039 { // Someone else's HUD, why are we getting these?
3993 SceneObjectPart part = (SceneObjectPart)update.Entity; 4040 if (part.ParentGroup.OwnerID != AgentId && part.ParentGroup.HasPrivateAttachmentPoint)
3994
3995 // Please do not remove this unless you can demonstrate on the OpenSim mailing list that a client
3996 // will never receive an update after a prim kill. Even then, keeping the kill record may be a good
3997 // safety measure.
3998 //
3999 // If a Linden Lab 1.23.5 client (and possibly later and earlier) receives an object update
4000 // after a kill, it will keep displaying the deleted object until relog. OpenSim currently performs
4001 // updates and kills on different threads with different scheduling strategies, hence this protection.
4002 //
4003 // This doesn't appear to apply to child prims - a client will happily ignore these updates
4004 // after the root prim has been deleted.
4005 if (m_killRecord.Contains(part.LocalId))
4006 {
4007 // m_log.WarnFormat(
4008 // "[CLIENT]: Preventing update for prim with local id {0} after client for user {1} told it was deleted",
4009 // part.LocalId, Name);
4010 continue; 4041 continue;
4011 } 4042 ScenePresence sp;
4012 4043 // Owner is not in the sim, don't update it to
4013 if (part.ParentGroup.IsAttachment && m_disableFacelights) 4044 // anyone
4045 if (!m_scene.TryGetScenePresence(part.OwnerID, out sp))
4046 continue;
4047
4048 List<SceneObjectGroup> atts = sp.GetAttachments();
4049 bool found = false;
4050 foreach (SceneObjectGroup att in atts)
4014 { 4051 {
4015 if (part.ParentGroup.RootPart.Shape.State != (byte)AttachmentPoint.LeftHand && 4052 if (att == part.ParentGroup)
4016 part.ParentGroup.RootPart.Shape.State != (byte)AttachmentPoint.RightHand)
4017 { 4053 {
4018 part.Shape.LightEntry = false; 4054 found = true;
4055 break;
4019 } 4056 }
4020 } 4057 }
4021 4058
4059 // It's an attachment of a valid avatar, but
4060 // doesn't seem to be attached, skip
4061 if (!found)
4062 continue;
4063
4064 // On vehicle crossing, the attachments are received
4065 // while the avatar is still a child. Don't send
4066 // updates here because the LocalId has not yet
4067 // been updated and the viewer will derender the
4068 // attachments until the avatar becomes root.
4069 if (sp.IsChildAgent)
4070 continue;
4071
4072 }
4073
4074 if (part.ParentGroup.IsAttachment && m_disableFacelights)
4075 {
4076 if (part.ParentGroup.RootPart.Shape.State != (byte)AttachmentPoint.LeftHand &&
4077 part.ParentGroup.RootPart.Shape.State != (byte)AttachmentPoint.RightHand)
4078 {
4079 part.Shape.LightEntry = false;
4080 }
4081
4022 if (part.Shape != null && (part.Shape.SculptType == (byte)SculptType.Mesh)) 4082 if (part.Shape != null && (part.Shape.SculptType == (byte)SculptType.Mesh))
4023 { 4083 {
4024 // Ensure that mesh has at least 8 valid faces 4084 // Ensure that mesh has at least 8 valid faces
@@ -4027,233 +4087,218 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4027 part.Shape.ProfileHollow = 27500; 4087 part.Shape.ProfileHollow = 27500;
4028 } 4088 }
4029 } 4089 }
4030 4090
4031 #region UpdateFlags to packet type conversion 4091 if (part.Shape != null && (part.Shape.SculptType == (byte)SculptType.Mesh))
4032
4033 PrimUpdateFlags updateFlags = (PrimUpdateFlags)update.Flags;
4034
4035 bool canUseCompressed = true;
4036 bool canUseImproved = true;
4037
4038 // Compressed object updates only make sense for LL primitives
4039 if (!(update.Entity is SceneObjectPart))
4040 { 4092 {
4041 canUseCompressed = false; 4093 // Ensure that mesh has at least 8 valid faces
4094 part.Shape.ProfileBegin = 12500;
4095 part.Shape.ProfileEnd = 0;
4096 part.Shape.ProfileHollow = 27500;
4042 } 4097 }
4043 4098 }
4044 if (updateFlags.HasFlag(PrimUpdateFlags.FullUpdate)) 4099 else if (update.Entity is ScenePresence)
4100 {
4101 ScenePresence presence = (ScenePresence)update.Entity;
4102 if (presence.IsDeleted)
4103 continue;
4104 // If ParentUUID is not UUID.Zero and ParentID is 0, this
4105 // avatar is in the process of crossing regions while
4106 // sat on an object. In this state, we don't want any
4107 // updates because they will visually orbit the avatar.
4108 // Update will be forced once crossing is completed anyway.
4109 if (presence.ParentUUID != UUID.Zero && presence.ParentID == 0)
4110 continue;
4111 }
4112
4113 ++updatesThisCall;
4114
4115 #region UpdateFlags to packet type conversion
4116
4117 PrimUpdateFlags updateFlags = (PrimUpdateFlags)update.Flags;
4118
4119 bool canUseCompressed = true;
4120 bool canUseImproved = true;
4121
4122 // Compressed object updates only make sense for LL primitives
4123 if (!(update.Entity is SceneObjectPart))
4124 {
4125 canUseCompressed = false;
4126 }
4127
4128 if (updateFlags.HasFlag(PrimUpdateFlags.FullUpdate))
4129 {
4130 canUseCompressed = false;
4131 canUseImproved = false;
4132 }
4133 else
4134 {
4135 if (updateFlags.HasFlag(PrimUpdateFlags.Velocity) ||
4136 updateFlags.HasFlag(PrimUpdateFlags.Acceleration) ||
4137 updateFlags.HasFlag(PrimUpdateFlags.CollisionPlane) ||
4138 updateFlags.HasFlag(PrimUpdateFlags.Joint))
4045 { 4139 {
4046 canUseCompressed = false; 4140 canUseCompressed = false;
4047 canUseImproved = false;
4048 } 4141 }
4049 else 4142
4143 if (updateFlags.HasFlag(PrimUpdateFlags.PrimFlags) ||
4144 updateFlags.HasFlag(PrimUpdateFlags.ParentID) ||
4145 updateFlags.HasFlag(PrimUpdateFlags.Scale) ||
4146 updateFlags.HasFlag(PrimUpdateFlags.PrimData) ||
4147 updateFlags.HasFlag(PrimUpdateFlags.Text) ||
4148 updateFlags.HasFlag(PrimUpdateFlags.NameValue) ||
4149 updateFlags.HasFlag(PrimUpdateFlags.ExtraData) ||
4150 updateFlags.HasFlag(PrimUpdateFlags.TextureAnim) ||
4151 updateFlags.HasFlag(PrimUpdateFlags.Sound) ||
4152 updateFlags.HasFlag(PrimUpdateFlags.Particles) ||
4153 updateFlags.HasFlag(PrimUpdateFlags.Material) ||
4154 updateFlags.HasFlag(PrimUpdateFlags.ClickAction) ||
4155 updateFlags.HasFlag(PrimUpdateFlags.MediaURL) ||
4156 updateFlags.HasFlag(PrimUpdateFlags.Joint))
4050 { 4157 {
4051 if (updateFlags.HasFlag(PrimUpdateFlags.Velocity) || 4158 canUseImproved = false;
4052 updateFlags.HasFlag(PrimUpdateFlags.Acceleration) ||
4053 updateFlags.HasFlag(PrimUpdateFlags.CollisionPlane) ||
4054 updateFlags.HasFlag(PrimUpdateFlags.Joint))
4055 {
4056 canUseCompressed = false;
4057 }
4058
4059 if (updateFlags.HasFlag(PrimUpdateFlags.PrimFlags) ||
4060 updateFlags.HasFlag(PrimUpdateFlags.ParentID) ||
4061 updateFlags.HasFlag(PrimUpdateFlags.Scale) ||
4062 updateFlags.HasFlag(PrimUpdateFlags.PrimData) ||
4063 updateFlags.HasFlag(PrimUpdateFlags.Text) ||
4064 updateFlags.HasFlag(PrimUpdateFlags.NameValue) ||
4065 updateFlags.HasFlag(PrimUpdateFlags.ExtraData) ||
4066 updateFlags.HasFlag(PrimUpdateFlags.TextureAnim) ||
4067 updateFlags.HasFlag(PrimUpdateFlags.Sound) ||
4068 updateFlags.HasFlag(PrimUpdateFlags.Particles) ||
4069 updateFlags.HasFlag(PrimUpdateFlags.Material) ||
4070 updateFlags.HasFlag(PrimUpdateFlags.ClickAction) ||
4071 updateFlags.HasFlag(PrimUpdateFlags.MediaURL) ||
4072 updateFlags.HasFlag(PrimUpdateFlags.Joint))
4073 {
4074 canUseImproved = false;
4075 }
4076 } 4159 }
4160 }
4077 4161
4078 #endregion UpdateFlags to packet type conversion 4162 #endregion UpdateFlags to packet type conversion
4079
4080 #region Block Construction
4081
4082 // TODO: Remove this once we can build compressed updates
4083 canUseCompressed = false;
4084
4085 if (!canUseImproved && !canUseCompressed)
4086 {
4087 ObjectUpdatePacket.ObjectDataBlock updateBlock;
4088 4163
4089 if (update.Entity is ScenePresence) 4164 #region Block Construction
4090 {
4091 updateBlock = CreateAvatarUpdateBlock((ScenePresence)update.Entity);
4092 }
4093 else
4094 {
4095 SceneObjectPart part = (SceneObjectPart)update.Entity;
4096 updateBlock = CreatePrimUpdateBlock(part, AgentId);
4097
4098 // If the part has become a private hud since the update was scheduled then we do not
4099 // want to send it to other avatars.
4100 if (part.ParentGroup.IsAttachment
4101 && part.ParentGroup.HasPrivateAttachmentPoint
4102 && part.ParentGroup.AttachedAvatar != AgentId)
4103 continue;
4104
4105 // If the part has since been deleted, then drop the update. In the case of attachments,
4106 // this is to avoid spurious updates to other viewers since post-processing of attachments
4107 // has to change the IsAttachment flag for various reasons (which will end up in a pass
4108 // of the test above).
4109 //
4110 // Actual deletions (kills) happen in another method.
4111 if (part.ParentGroup.IsDeleted)
4112 continue;
4113 }
4114 4165
4115 objectUpdateBlocks.Value.Add(updateBlock); 4166 // TODO: Remove this once we can build compressed updates
4116 objectUpdates.Value.Add(update); 4167 canUseCompressed = false;
4117 }
4118 else if (!canUseImproved)
4119 {
4120 SceneObjectPart part = (SceneObjectPart)update.Entity;
4121 ObjectUpdateCompressedPacket.ObjectDataBlock compressedBlock
4122 = CreateCompressedUpdateBlock(part, updateFlags);
4123
4124 // If the part has since been deleted, then drop the update. In the case of attachments,
4125 // this is to avoid spurious updates to other viewers since post-processing of attachments
4126 // has to change the IsAttachment flag for various reasons (which will end up in a pass
4127 // of the test above).
4128 //
4129 // Actual deletions (kills) happen in another method.
4130 if (part.ParentGroup.IsDeleted)
4131 continue;
4132 4168
4133 compressedUpdateBlocks.Value.Add(compressedBlock); 4169 if (!canUseImproved && !canUseCompressed)
4134 compressedUpdates.Value.Add(update); 4170 {
4171 if (update.Entity is ScenePresence)
4172 {
4173 objectUpdateBlocks.Value.Add(CreateAvatarUpdateBlock((ScenePresence)update.Entity));
4135 } 4174 }
4136 else 4175 else
4137 { 4176 {
4138 if (update.Entity is ScenePresence && ((ScenePresence)update.Entity).UUID == AgentId) 4177 objectUpdateBlocks.Value.Add(CreatePrimUpdateBlock((SceneObjectPart)update.Entity, this.m_agentId));
4139 { 4178 }
4140 // Self updates go into a special list 4179 }
4141 terseAgentUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures))); 4180 else if (!canUseImproved)
4142 terseAgentUpdates.Value.Add(update); 4181 {
4143 } 4182 compressedUpdateBlocks.Value.Add(CreateCompressedUpdateBlock((SceneObjectPart)update.Entity, updateFlags));
4144 else 4183 }
4145 { 4184 else
4146 ImprovedTerseObjectUpdatePacket.ObjectDataBlock terseUpdateBlock 4185 {
4147 = CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures)); 4186 if (update.Entity is ScenePresence)
4187 // ALL presence updates go into a special list
4188 terseAgentUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures)));
4189 else
4190 // Everything else goes here
4191 terseUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures)));
4192 }
4148 4193
4149 // Everything else goes here 4194 #endregion Block Construction
4150 if (update.Entity is SceneObjectPart) 4195 }
4151 {
4152 SceneObjectPart part = (SceneObjectPart)update.Entity;
4153
4154 // If the part has become a private hud since the update was scheduled then we do not
4155 // want to send it to other avatars.
4156 if (part.ParentGroup.IsAttachment
4157 && part.ParentGroup.HasPrivateAttachmentPoint
4158 && part.ParentGroup.AttachedAvatar != AgentId)
4159 continue;
4160
4161 // If the part has since been deleted, then drop the update. In the case of attachments,
4162 // this is to avoid spurious updates to other viewers since post-processing of attachments
4163 // has to change the IsAttachment flag for various reasons (which will end up in a pass
4164 // of the test above).
4165 //
4166 // Actual deletions (kills) happen in another method.
4167 if (part.ParentGroup.IsDeleted)
4168 continue;
4169 }
4170 4196
4171 terseUpdateBlocks.Value.Add(terseUpdateBlock); 4197 #region Packet Sending
4172 terseUpdates.Value.Add(update); 4198
4173 } 4199// const float TIME_DILATION = 1.0f;
4174 } 4200 ushort timeDilation;
4201// if(updatesThisCall > 0)
4202// timeDilation = Utils.FloatToUInt16(avgTimeDilation/updatesThisCall, 0.0f, 1.0f);
4203// else
4204// timeDilation = ushort.MaxValue; // 1.0;
4205
4206 timeDilation = Utils.FloatToUInt16(m_scene.TimeDilation, 0.0f, 1.0f);
4175 4207
4176 ++updatesThisCall; 4208 if (terseAgentUpdateBlocks.IsValueCreated)
4209 {
4210 List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseAgentUpdateBlocks.Value;
4211
4212 ImprovedTerseObjectUpdatePacket packet
4213 = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ImprovedTerseObjectUpdate);
4214 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
4215 packet.RegionData.TimeDilation = timeDilation;
4216 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count];
4217
4218 for (int i = 0; i < blocks.Count; i++)
4219 packet.ObjectData[i] = blocks[i];
4220
4221 OutPacket(packet, ThrottleOutPacketType.Unknown, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(terseUpdates.Value, oPacket); });
4222 }
4223
4224 if (objectUpdateBlocks.IsValueCreated)
4225 {
4226 List<ObjectUpdatePacket.ObjectDataBlock> blocks = objectUpdateBlocks.Value;
4177 4227
4178 #endregion Block Construction 4228 ObjectUpdatePacket packet = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate);
4179 } 4229 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
4230 packet.RegionData.TimeDilation = timeDilation;
4231 packet.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[blocks.Count];
4232
4233 for (int i = 0; i < blocks.Count; i++)
4234 packet.ObjectData[i] = blocks[i];
4180 4235
4181 #region Packet Sending 4236 OutPacket(packet, ThrottleOutPacketType.Task, true);
4182 ushort timeDilation = Utils.FloatToUInt16(avgTimeDilation, 0.0f, 1.0f); 4237 }
4238
4239 if (compressedUpdateBlocks.IsValueCreated)
4240 {
4241 List<ObjectUpdateCompressedPacket.ObjectDataBlock> blocks = compressedUpdateBlocks.Value;
4242
4243 ObjectUpdateCompressedPacket packet = (ObjectUpdateCompressedPacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdateCompressed);
4244 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
4245 packet.RegionData.TimeDilation = timeDilation;
4246 packet.ObjectData = new ObjectUpdateCompressedPacket.ObjectDataBlock[blocks.Count];
4183 4247
4184 if (terseAgentUpdateBlocks.IsValueCreated) 4248 for (int i = 0; i < blocks.Count; i++)
4185 { 4249 packet.ObjectData[i] = blocks[i];
4186 List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseAgentUpdateBlocks.Value; 4250
4251 OutPacket(packet, ThrottleOutPacketType.Task, true);
4252 }
4253
4254 if (terseUpdateBlocks.IsValueCreated)
4255 {
4256 List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseUpdateBlocks.Value;
4257
4258 ImprovedTerseObjectUpdatePacket packet
4259 = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(
4260 PacketType.ImprovedTerseObjectUpdate);
4261 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
4262 packet.RegionData.TimeDilation = timeDilation;
4263 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count];
4264
4265 for (int i = 0; i < blocks.Count; i++)
4266 packet.ObjectData[i] = blocks[i];
4187 4267
4188 ImprovedTerseObjectUpdatePacket packet 4268 OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(terseUpdates.Value, oPacket); });
4189 = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ImprovedTerseObjectUpdate); 4269 }
4190 4270
4191 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; 4271 #endregion Packet Sending
4192 packet.RegionData.TimeDilation = timeDilation; 4272 }
4193 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count];
4194 4273
4195 for (int i = 0; i < blocks.Count; i++) 4274 // hack.. dont use
4196 packet.ObjectData[i] = blocks[i]; 4275 public void SendPartFullUpdate(ISceneEntity ent, uint? parentID)
4197 // If any of the packets created from this call go unacknowledged, all of the updates will be resent 4276 {
4198 OutPacket(packet, ThrottleOutPacketType.Unknown, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(terseAgentUpdates.Value, oPacket); }); 4277 if (ent is SceneObjectPart)
4199 } 4278 {
4279 SceneObjectPart part = (SceneObjectPart)ent;
4280 ObjectUpdatePacket packet = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate);
4281 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
4282 packet.RegionData.TimeDilation = Utils.FloatToUInt16(m_scene.TimeDilation, 0.0f, 1.0f);
4283 packet.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[1];
4200 4284
4201 if (objectUpdateBlocks.IsValueCreated) 4285 ObjectUpdatePacket.ObjectDataBlock blk = CreatePrimUpdateBlock(part, this.m_agentId);
4202 { 4286 if (parentID.HasValue)
4203 List<ObjectUpdatePacket.ObjectDataBlock> blocks = objectUpdateBlocks.Value;
4204
4205 ObjectUpdatePacket packet = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate);
4206 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
4207 packet.RegionData.TimeDilation = timeDilation;
4208 packet.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[blocks.Count];
4209
4210 for (int i = 0; i < blocks.Count; i++)
4211 packet.ObjectData[i] = blocks[i];
4212 // If any of the packets created from this call go unacknowledged, all of the updates will be resent
4213 OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(objectUpdates.Value, oPacket); });
4214 }
4215
4216 if (compressedUpdateBlocks.IsValueCreated)
4217 { 4287 {
4218 List<ObjectUpdateCompressedPacket.ObjectDataBlock> blocks = compressedUpdateBlocks.Value; 4288 blk.ParentID = parentID.Value;
4219
4220 ObjectUpdateCompressedPacket packet = (ObjectUpdateCompressedPacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdateCompressed);
4221 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
4222 packet.RegionData.TimeDilation = timeDilation;
4223 packet.ObjectData = new ObjectUpdateCompressedPacket.ObjectDataBlock[blocks.Count];
4224
4225 for (int i = 0; i < blocks.Count; i++)
4226 packet.ObjectData[i] = blocks[i];
4227 // If any of the packets created from this call go unacknowledged, all of the updates will be resent
4228 OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(compressedUpdates.Value, oPacket); });
4229 } 4289 }
4230 4290
4231 if (terseUpdateBlocks.IsValueCreated) 4291 packet.ObjectData[0] = blk;
4232 {
4233 List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseUpdateBlocks.Value;
4234
4235 ImprovedTerseObjectUpdatePacket packet
4236 = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(
4237 PacketType.ImprovedTerseObjectUpdate);
4238 4292
4239 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; 4293 OutPacket(packet, ThrottleOutPacketType.Task, true);
4240 packet.RegionData.TimeDilation = timeDilation;
4241 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count];
4242
4243 for (int i = 0; i < blocks.Count; i++)
4244 packet.ObjectData[i] = blocks[i];
4245 // If any of the packets created from this call go unacknowledged, all of the updates will be resent
4246 OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(terseUpdates.Value, oPacket); });
4247 }
4248 } 4294 }
4249 4295
4250// m_log.DebugFormat( 4296// m_log.DebugFormat(
4251// "[LLCLIENTVIEW]: Sent {0} updates in ProcessEntityUpdates() for {1} {2} in {3}", 4297// "[LLCLIENTVIEW]: Sent {0} updates in ProcessEntityUpdates() for {1} {2} in {3}",
4252// updatesThisCall, Name, SceneAgent.IsChildAgent ? "child" : "root", Scene.Name); 4298// updatesThisCall, Name, SceneAgent.IsChildAgent ? "child" : "root", Scene.Name);
4253// 4299//
4254 #endregion Packet Sending
4255 } 4300 }
4256 4301
4257 public void ReprioritizeUpdates() 4302 public void ReprioritizeUpdates()
4258 { 4303 {
4259 lock (m_entityUpdates.SyncRoot) 4304 lock (m_entityUpdates.SyncRoot)
@@ -4572,11 +4617,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4572 4617
4573 // Pass in the delegate so that if this packet needs to be resent, we send the current properties 4618 // Pass in the delegate so that if this packet needs to be resent, we send the current properties
4574 // of the object rather than the properties when the packet was created 4619 // of the object rather than the properties when the packet was created
4575 OutPacket(packet, ThrottleOutPacketType.Task, true, 4620 // HACK : Remove intelligent resending until it's fixed in core
4576 delegate(OutgoingPacket oPacket) 4621 //OutPacket(packet, ThrottleOutPacketType.Task, true,
4577 { 4622 // delegate(OutgoingPacket oPacket)
4578 ResendPropertyUpdates(updates, oPacket); 4623 // {
4579 }); 4624 // ResendPropertyUpdates(updates, oPacket);
4625 // });
4626 OutPacket(packet, ThrottleOutPacketType.Task, true);
4580 4627
4581 // pbcnt += blocks.Count; 4628 // pbcnt += blocks.Count;
4582 // ppcnt++; 4629 // ppcnt++;
@@ -4602,11 +4649,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4602 // of the object rather than the properties when the packet was created 4649 // of the object rather than the properties when the packet was created
4603 List<ObjectPropertyUpdate> updates = new List<ObjectPropertyUpdate>(); 4650 List<ObjectPropertyUpdate> updates = new List<ObjectPropertyUpdate>();
4604 updates.Add(familyUpdates.Value[i]); 4651 updates.Add(familyUpdates.Value[i]);
4605 OutPacket(packet, ThrottleOutPacketType.Task, true, 4652 // HACK : Remove intelligent resending until it's fixed in core
4606 delegate(OutgoingPacket oPacket) 4653 //OutPacket(packet, ThrottleOutPacketType.Task, true,
4607 { 4654 // delegate(OutgoingPacket oPacket)
4608 ResendPropertyUpdates(updates, oPacket); 4655 // {
4609 }); 4656 // ResendPropertyUpdates(updates, oPacket);
4657 // });
4658 OutPacket(packet, ThrottleOutPacketType.Task, true);
4610 4659
4611 // fpcnt++; 4660 // fpcnt++;
4612 // fbcnt++; 4661 // fbcnt++;
@@ -4939,7 +4988,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4939 packet.ParcelData.Data = data; 4988 packet.ParcelData.Data = data;
4940 packet.ParcelData.SequenceID = sequence_id; 4989 packet.ParcelData.SequenceID = sequence_id;
4941 packet.Header.Zerocoded = true; 4990 packet.Header.Zerocoded = true;
4942 OutPacket(packet, ThrottleOutPacketType.Task); 4991// OutPacket(packet, ThrottleOutPacketType.Task);
4992 OutPacket(packet, ThrottleOutPacketType.Land);
4943 } 4993 }
4944 4994
4945 public void SendLandProperties( 4995 public void SendLandProperties(
@@ -5004,7 +5054,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5004 5054
5005 if (landData.SimwideArea > 0) 5055 if (landData.SimwideArea > 0)
5006 { 5056 {
5007 int simulatorCapacity = (int)(((float)landData.SimwideArea / 65536.0f) * (float)m_scene.RegionInfo.ObjectCapacity * (float)m_scene.RegionInfo.RegionSettings.ObjectBonus); 5057 int simulatorCapacity = (int)((long)landData.SimwideArea * (long)m_scene.RegionInfo.ObjectCapacity * (long)m_scene.RegionInfo.RegionSettings.ObjectBonus / 65536L);
5058 // Never report more than sim total capacity
5059 if (simulatorCapacity > m_scene.RegionInfo.ObjectCapacity)
5060 simulatorCapacity = m_scene.RegionInfo.ObjectCapacity;
5008 updateMessage.SimWideMaxPrims = simulatorCapacity; 5061 updateMessage.SimWideMaxPrims = simulatorCapacity;
5009 } 5062 }
5010 else 5063 else
@@ -5039,7 +5092,22 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5039 IEventQueue eq = Scene.RequestModuleInterface<IEventQueue>(); 5092 IEventQueue eq = Scene.RequestModuleInterface<IEventQueue>();
5040 if (eq != null) 5093 if (eq != null)
5041 { 5094 {
5042 eq.ParcelProperties(updateMessage, this.AgentId); 5095
5096 OSD message_body = updateMessage.Serialize();
5097 // Add new fields here until OMV has them
5098 OSDMap bodyMap = (OSDMap)message_body;
5099 OSDArray parcelDataArray = (OSDArray)bodyMap["ParcelData"];
5100 OSDMap parcelData = (OSDMap)parcelDataArray[0];
5101 parcelData["SeeAVs"] = OSD.FromBoolean(landData.SeeAVs);
5102 parcelData["AnyAVSounds"] = OSD.FromBoolean(landData.AnyAVSounds);
5103 parcelData["GroupAVSounds"] = OSD.FromBoolean(landData.GroupAVSounds);
5104 OSDMap message = new OSDMap();
5105 message.Add("message", OSD.FromString("ParcelProperties"));
5106 message.Add("body", message_body);
5107
5108 eq.Enqueue (message, this.AgentId);
5109
5110// eq.ParcelProperties(updateMessage, this.AgentId);
5043 } 5111 }
5044 else 5112 else
5045 { 5113 {
@@ -5133,14 +5201,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5133 5201
5134 if (notifyCount > 0) 5202 if (notifyCount > 0)
5135 { 5203 {
5136 if (notifyCount > 32) 5204// if (notifyCount > 32)
5137 { 5205// {
5138 m_log.InfoFormat( 5206// m_log.InfoFormat(
5139 "[LAND]: More than {0} avatars own prims on this parcel. Only sending back details of first {0}" 5207// "[LAND]: More than {0} avatars own prims on this parcel. Only sending back details of first {0}"
5140 + " - a developer might want to investigate whether this is a hard limit", 32); 5208// + " - a developer might want to investigate whether this is a hard limit", 32);
5141 5209//
5142 notifyCount = 32; 5210// notifyCount = 32;
5143 } 5211// }
5144 5212
5145 ParcelObjectOwnersReplyPacket.DataBlock[] dataBlock 5213 ParcelObjectOwnersReplyPacket.DataBlock[] dataBlock
5146 = new ParcelObjectOwnersReplyPacket.DataBlock[notifyCount]; 5214 = new ParcelObjectOwnersReplyPacket.DataBlock[notifyCount];
@@ -5195,41 +5263,24 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5195 { 5263 {
5196 ScenePresence presence = (ScenePresence)entity; 5264 ScenePresence presence = (ScenePresence)entity;
5197 5265
5198// m_log.DebugFormat(
5199// "[LLCLIENTVIEW]: Sending terse update to {0} with pos {1}, vel {2} in {3}",
5200// Name, presence.OffsetPosition, presence.Velocity, m_scene.Name);
5201
5202 attachPoint = presence.State;
5203 collisionPlane = presence.CollisionPlane;
5204 position = presence.OffsetPosition; 5266 position = presence.OffsetPosition;
5205 velocity = presence.Velocity; 5267 rotation = presence.Rotation;
5206 acceleration = Vector3.Zero;
5207
5208 // Interestingly, sending this to non-zero will cause the client's avatar to start moving & accelerating
5209 // in that direction, even though we don't model this on the server. Implementing this in the future
5210 // may improve movement smoothness.
5211// acceleration = new Vector3(1, 0, 0);
5212
5213 angularVelocity = presence.AngularVelocity; 5268 angularVelocity = presence.AngularVelocity;
5214
5215 // Whilst not in mouselook, an avatar will transmit only the Z rotation as this is the only axis
5216 // it rotates around.
5217 // In mouselook, X and Y co-ordinate will also be sent but when used in Rotation, these cause unwanted
5218 // excessive up and down movements of the camera when looking up and down.
5219 // See http://opensimulator.org/mantis/view.php?id=3274
5220 // This does not affect head movement, since this is controlled entirely by camera movement rather than
5221 // body rotation. We still need to transmit X and Y for sitting avatars but mouselook does not change
5222 // the rotation in this case.
5223 rotation = presence.Rotation; 5269 rotation = presence.Rotation;
5224 5270
5225 if (!presence.IsSatOnObject) 5271 attachPoint = 0;
5226 { 5272// m_log.DebugFormat(
5227 rotation.X = 0; 5273// "[LLCLIENTVIEW]: Sending terse update to {0} with position {1} in {2}", Name, presence.OffsetPosition, m_scene.Name);
5228 rotation.Y = 0; 5274
5229 } 5275 // attachPoint = presence.State; // Core: commented
5276 collisionPlane = presence.CollisionPlane;
5277 velocity = presence.Velocity;
5278 acceleration = Vector3.Zero;
5230 5279
5231 if (sendTexture) 5280 if (sendTexture)
5281 {
5232 textureEntry = presence.Appearance.Texture.GetBytes(); 5282 textureEntry = presence.Appearance.Texture.GetBytes();
5283 }
5233 else 5284 else
5234 textureEntry = null; 5285 textureEntry = null;
5235 } 5286 }
@@ -5333,34 +5384,25 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5333 5384
5334 protected ObjectUpdatePacket.ObjectDataBlock CreateAvatarUpdateBlock(ScenePresence data) 5385 protected ObjectUpdatePacket.ObjectDataBlock CreateAvatarUpdateBlock(ScenePresence data)
5335 { 5386 {
5387 Vector3 offsetPosition = data.OffsetPosition;
5388 Quaternion rotation = data.Rotation;
5389 uint parentID = data.ParentID;
5390
5336// m_log.DebugFormat( 5391// m_log.DebugFormat(
5337// "[LLCLIENTVIEW]: Sending full update to {0} with pos {1}, vel {2} in {3}", Name, data.OffsetPosition, data.Velocity, m_scene.Name); 5392// "[LLCLIENTVIEW]: Sending full update to {0} with pos {1}, vel {2} in {3}", Name, data.OffsetPosition, data.Velocity, m_scene.Name);
5338 5393
5339 byte[] objectData = new byte[76]; 5394 byte[] objectData = new byte[76];
5340 5395
5341 data.CollisionPlane.ToBytes(objectData, 0); 5396 Vector3 velocity = new Vector3(0, 0, 0);
5342 data.OffsetPosition.ToBytes(objectData, 16); 5397 Vector3 acceleration = new Vector3(0, 0, 0);
5343 data.Velocity.ToBytes(objectData, 28); 5398 rotation.Normalize();
5344// data.Acceleration.ToBytes(objectData, 40);
5345
5346 // Whilst not in mouselook, an avatar will transmit only the Z rotation as this is the only axis
5347 // it rotates around.
5348 // In mouselook, X and Y co-ordinate will also be sent but when used in Rotation, these cause unwanted
5349 // excessive up and down movements of the camera when looking up and down.
5350 // See http://opensimulator.org/mantis/view.php?id=3274
5351 // This does not affect head movement, since this is controlled entirely by camera movement rather than
5352 // body rotation. We still need to transmit X and Y for sitting avatars but mouselook does not change
5353 // the rotation in this case.
5354 Quaternion rot = data.Rotation;
5355
5356 if (!data.IsSatOnObject)
5357 {
5358 rot.X = 0;
5359 rot.Y = 0;
5360 }
5361 5399
5362 rot.ToBytes(objectData, 52); 5400 data.CollisionPlane.ToBytes(objectData, 0);
5363 //data.AngularVelocity.ToBytes(objectData, 64); 5401 offsetPosition.ToBytes(objectData, 16);
5402 velocity.ToBytes(objectData, 28);
5403 acceleration.ToBytes(objectData, 40);
5404 rotation.ToBytes(objectData, 52);
5405 data.AngularVelocity.ToBytes(objectData, 64);
5364 5406
5365 ObjectUpdatePacket.ObjectDataBlock update = new ObjectUpdatePacket.ObjectDataBlock(); 5407 ObjectUpdatePacket.ObjectDataBlock update = new ObjectUpdatePacket.ObjectDataBlock();
5366 5408
@@ -5386,7 +5428,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5386 update.PCode = (byte)PCode.Avatar; 5428 update.PCode = (byte)PCode.Avatar;
5387 update.ProfileCurve = 1; 5429 update.ProfileCurve = 1;
5388 update.PSBlock = Utils.EmptyBytes; 5430 update.PSBlock = Utils.EmptyBytes;
5389 update.Scale = new Vector3(0.45f, 0.6f, 1.9f); 5431 update.Scale = data.Appearance.AvatarSize;
5432// update.Scale.Z -= 0.2f;
5433
5390 update.Text = Utils.EmptyBytes; 5434 update.Text = Utils.EmptyBytes;
5391 update.TextColor = new byte[4]; 5435 update.TextColor = new byte[4];
5392 5436
@@ -5397,10 +5441,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5397 update.TextureEntry = Utils.EmptyBytes; 5441 update.TextureEntry = Utils.EmptyBytes;
5398// update.TextureEntry = (data.Appearance.Texture != null) ? data.Appearance.Texture.GetBytes() : Utils.EmptyBytes; 5442// update.TextureEntry = (data.Appearance.Texture != null) ? data.Appearance.Texture.GetBytes() : Utils.EmptyBytes;
5399 5443
5444/* all this flags seem related to prims and not avatars. This allow for wrong viewer side move of a avatar in prim edition mode (anv mantis 854)
5400 update.UpdateFlags = (uint)( 5445 update.UpdateFlags = (uint)(
5401 PrimFlags.Physics | PrimFlags.ObjectModify | PrimFlags.ObjectCopy | PrimFlags.ObjectAnyOwner | 5446 PrimFlags.Physics | PrimFlags.ObjectModify | PrimFlags.ObjectCopy | PrimFlags.ObjectAnyOwner |
5402 PrimFlags.ObjectYouOwner | PrimFlags.ObjectMove | PrimFlags.InventoryEmpty | PrimFlags.ObjectTransfer | 5447 PrimFlags.ObjectYouOwner | PrimFlags.ObjectMove | PrimFlags.InventoryEmpty | PrimFlags.ObjectTransfer |
5403 PrimFlags.ObjectOwnerModify); 5448 PrimFlags.ObjectOwnerModify);
5449*/
5450 update.UpdateFlags = 0;
5404 5451
5405 return update; 5452 return update;
5406 } 5453 }
@@ -5411,15 +5458,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5411 data.RelativePosition.ToBytes(objectData, 0); 5458 data.RelativePosition.ToBytes(objectData, 0);
5412 data.Velocity.ToBytes(objectData, 12); 5459 data.Velocity.ToBytes(objectData, 12);
5413 data.Acceleration.ToBytes(objectData, 24); 5460 data.Acceleration.ToBytes(objectData, 24);
5414 try 5461
5415 { 5462 Quaternion rotation = data.RotationOffset;
5416 data.RotationOffset.ToBytes(objectData, 36); 5463 rotation.Normalize();
5417 } 5464 rotation.ToBytes(objectData, 36);
5418 catch (Exception e)
5419 {
5420 m_log.Warn("[LLClientView]: exception converting quaternion to bytes, using Quaternion.Identity. Exception: " + e.ToString());
5421 OpenMetaverse.Quaternion.Identity.ToBytes(objectData, 36);
5422 }
5423 data.AngularVelocity.ToBytes(objectData, 48); 5465 data.AngularVelocity.ToBytes(objectData, 48);
5424 5466
5425 ObjectUpdatePacket.ObjectDataBlock update = new ObjectUpdatePacket.ObjectDataBlock(); 5467 ObjectUpdatePacket.ObjectDataBlock update = new ObjectUpdatePacket.ObjectDataBlock();
@@ -5433,7 +5475,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5433 //update.JointType = 0; 5475 //update.JointType = 0;
5434 update.Material = data.Material; 5476 update.Material = data.Material;
5435 update.MediaURL = Utils.EmptyBytes; // FIXME: Support this in OpenSim 5477 update.MediaURL = Utils.EmptyBytes; // FIXME: Support this in OpenSim
5436 5478/*
5437 if (data.ParentGroup.IsAttachment) 5479 if (data.ParentGroup.IsAttachment)
5438 { 5480 {
5439 update.NameValue 5481 update.NameValue
@@ -5458,6 +5500,26 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5458 // case for attachments may contain conflicting values that can end up crashing the viewer. 5500 // case for attachments may contain conflicting values that can end up crashing the viewer.
5459 update.State = data.ParentGroup.RootPart.Shape.State; 5501 update.State = data.ParentGroup.RootPart.Shape.State;
5460 } 5502 }
5503*/
5504
5505 if (data.ParentGroup.IsAttachment)
5506 {
5507 if (data.IsRoot)
5508 {
5509 update.NameValue = Util.StringToBytes256("AttachItemID STRING RW SV " + data.ParentGroup.FromItemID);
5510 }
5511 else
5512 update.NameValue = Utils.EmptyBytes;
5513
5514 int st = (int)data.ParentGroup.AttachmentPoint;
5515 update.State = (byte)(((st & 0xf0) >> 4) + ((st & 0x0f) << 4)); ;
5516 }
5517 else
5518 {
5519 update.NameValue = Utils.EmptyBytes;
5520 update.State = data.Shape.State; // not sure about this
5521 }
5522
5461 5523
5462 update.ObjectData = objectData; 5524 update.ObjectData = objectData;
5463 update.ParentID = data.ParentID; 5525 update.ParentID = data.ParentID;
@@ -5579,8 +5641,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5579 // If AgentUpdate is ever handled asynchronously, then we will also need to construct a new AgentUpdateArgs 5641 // If AgentUpdate is ever handled asynchronously, then we will also need to construct a new AgentUpdateArgs
5580 // for each AgentUpdate packet. 5642 // for each AgentUpdate packet.
5581 AddLocalPacketHandler(PacketType.AgentUpdate, HandleAgentUpdate, false); 5643 AddLocalPacketHandler(PacketType.AgentUpdate, HandleAgentUpdate, false);
5582 5644
5583 AddLocalPacketHandler(PacketType.ViewerEffect, HandleViewerEffect, false); 5645 AddLocalPacketHandler(PacketType.ViewerEffect, HandleViewerEffect, false);
5646 AddLocalPacketHandler(PacketType.VelocityInterpolateOff, HandleVelocityInterpolateOff, false);
5647 AddLocalPacketHandler(PacketType.VelocityInterpolateOn, HandleVelocityInterpolateOn, false);
5584 AddLocalPacketHandler(PacketType.AgentCachedTexture, HandleAgentTextureCached, false); 5648 AddLocalPacketHandler(PacketType.AgentCachedTexture, HandleAgentTextureCached, false);
5585 AddLocalPacketHandler(PacketType.MultipleObjectUpdate, HandleMultipleObjUpdate, false); 5649 AddLocalPacketHandler(PacketType.MultipleObjectUpdate, HandleMultipleObjUpdate, false);
5586 AddLocalPacketHandler(PacketType.MoneyTransferRequest, HandleMoneyTransferRequest, false); 5650 AddLocalPacketHandler(PacketType.MoneyTransferRequest, HandleMoneyTransferRequest, false);
@@ -5732,6 +5796,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5732 AddLocalPacketHandler(PacketType.TransferAbort, HandleTransferAbort, false); 5796 AddLocalPacketHandler(PacketType.TransferAbort, HandleTransferAbort, false);
5733 AddLocalPacketHandler(PacketType.MuteListRequest, HandleMuteListRequest, false); 5797 AddLocalPacketHandler(PacketType.MuteListRequest, HandleMuteListRequest, false);
5734 AddLocalPacketHandler(PacketType.UseCircuitCode, HandleUseCircuitCode); 5798 AddLocalPacketHandler(PacketType.UseCircuitCode, HandleUseCircuitCode);
5799 AddLocalPacketHandler(PacketType.CreateNewOutfitAttachments, HandleCreateNewOutfitAttachments);
5735 AddLocalPacketHandler(PacketType.AgentHeightWidth, HandleAgentHeightWidth, false); 5800 AddLocalPacketHandler(PacketType.AgentHeightWidth, HandleAgentHeightWidth, false);
5736 AddLocalPacketHandler(PacketType.InventoryDescendents, HandleInventoryDescendents); 5801 AddLocalPacketHandler(PacketType.InventoryDescendents, HandleInventoryDescendents);
5737 AddLocalPacketHandler(PacketType.DirPlacesQuery, HandleDirPlacesQuery); 5802 AddLocalPacketHandler(PacketType.DirPlacesQuery, HandleDirPlacesQuery);
@@ -5798,6 +5863,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5798 AddLocalPacketHandler(PacketType.GroupVoteHistoryRequest, HandleGroupVoteHistoryRequest); 5863 AddLocalPacketHandler(PacketType.GroupVoteHistoryRequest, HandleGroupVoteHistoryRequest);
5799 AddLocalPacketHandler(PacketType.SimWideDeletes, HandleSimWideDeletes); 5864 AddLocalPacketHandler(PacketType.SimWideDeletes, HandleSimWideDeletes);
5800 AddLocalPacketHandler(PacketType.SendPostcard, HandleSendPostcard); 5865 AddLocalPacketHandler(PacketType.SendPostcard, HandleSendPostcard);
5866 AddLocalPacketHandler(PacketType.ChangeInventoryItemFlags, HandleChangeInventoryItemFlags);
5801 5867
5802 AddGenericPacketHandler("autopilot", HandleAutopilot); 5868 AddGenericPacketHandler("autopilot", HandleAutopilot);
5803 } 5869 }
@@ -5809,7 +5875,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5809 #region Scene/Avatar 5875 #region Scene/Avatar
5810 5876
5811 // Threshold for body rotation to be a significant agent update 5877 // Threshold for body rotation to be a significant agent update
5812 private const float QDELTA = 0.000001f; 5878 // use the abs of cos
5879 private const float QDELTABody = 1.0f - 0.0001f;
5880 private const float QDELTAHead = 1.0f - 0.0001f;
5813 // Threshold for camera rotation to be a significant agent update 5881 // Threshold for camera rotation to be a significant agent update
5814 private const float VDELTA = 0.01f; 5882 private const float VDELTA = 0.01f;
5815 5883
@@ -5832,18 +5900,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5832 /// <param name='x'></param> 5900 /// <param name='x'></param>
5833 private bool CheckAgentMovementUpdateSignificance(AgentUpdatePacket.AgentDataBlock x) 5901 private bool CheckAgentMovementUpdateSignificance(AgentUpdatePacket.AgentDataBlock x)
5834 { 5902 {
5835 float qdelta1 = 1 - (float)Math.Pow(Quaternion.Dot(x.BodyRotation, m_thisAgentUpdateArgs.BodyRotation), 2); 5903 float qdelta1 = Math.Abs(Quaternion.Dot(x.BodyRotation, m_thisAgentUpdateArgs.BodyRotation));
5836 //qdelta2 = 1 - (float)Math.Pow(Quaternion.Dot(x.HeadRotation, m_thisAgentUpdateArgs.HeadRotation), 2); 5904 //qdelta2 = Math.Abs(Quaternion.Dot(x.HeadRotation, m_thisAgentUpdateArgs.HeadRotation));
5837 5905
5838 bool movementSignificant = 5906 bool movementSignificant =
5839 (qdelta1 > QDELTA) // significant if body rotation above threshold 5907 (x.ControlFlags != m_thisAgentUpdateArgs.ControlFlags) // significant if control flags changed
5840 // Ignoring head rotation altogether, because it's not being used for anything interesting up the stack
5841 // || (qdelta2 > QDELTA * 10) // significant if head rotation above threshold
5842 || (x.ControlFlags != m_thisAgentUpdateArgs.ControlFlags) // significant if control flags changed
5843 || (x.ControlFlags != (byte)AgentManager.ControlFlags.NONE) // significant if user supplying any movement update commands 5908 || (x.ControlFlags != (byte)AgentManager.ControlFlags.NONE) // significant if user supplying any movement update commands
5844 || (x.Far != m_thisAgentUpdateArgs.Far) // significant if far distance changed
5845 || (x.Flags != m_thisAgentUpdateArgs.Flags) // significant if Flags changed 5909 || (x.Flags != m_thisAgentUpdateArgs.Flags) // significant if Flags changed
5846 || (x.State != m_thisAgentUpdateArgs.State) // significant if Stats changed 5910 || (x.State != m_thisAgentUpdateArgs.State) // significant if Stats changed
5911 || (qdelta1 < QDELTABody) // significant if body rotation above(below cos) threshold
5912 // Ignoring head rotation altogether, because it's not being used for anything interesting up the stack
5913 // || (qdelta2 < QDELTAHead) // significant if head rotation above(below cos) threshold
5914 || (Math.Abs(x.Far - m_thisAgentUpdateArgs.Far) >= 32) // significant if far distance changed
5847 ; 5915 ;
5848 //if (movementSignificant) 5916 //if (movementSignificant)
5849 //{ 5917 //{
@@ -5886,55 +5954,63 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5886 return cameraSignificant; 5954 return cameraSignificant;
5887 } 5955 }
5888 5956
5889 private bool HandleAgentUpdate(IClientAPI sener, Packet packet) 5957 private bool HandleAgentUpdate(IClientAPI sender, Packet packet)
5890 { 5958 {
5891 // We got here, which means that something in agent update was significant 5959 // We got here, which means that something in agent update was significant
5892 5960
5893 AgentUpdatePacket agentUpdate = (AgentUpdatePacket)packet; 5961 AgentUpdatePacket agentUpdate = (AgentUpdatePacket)packet;
5894 AgentUpdatePacket.AgentDataBlock x = agentUpdate.AgentData; 5962 AgentUpdatePacket.AgentDataBlock x = agentUpdate.AgentData;
5895 5963
5896 if (x.AgentID != AgentId || x.SessionID != SessionId) 5964 if (x.AgentID != AgentId || x.SessionID != SessionId)
5965 {
5966 PacketPool.Instance.ReturnPacket(packet);
5897 return false; 5967 return false;
5968 }
5969
5970 TotalAgentUpdates++;
5898 5971
5899 // Before we update the current m_thisAgentUpdateArgs, let's check this again
5900 // to see what exactly changed
5901 bool movement = CheckAgentMovementUpdateSignificance(x); 5972 bool movement = CheckAgentMovementUpdateSignificance(x);
5902 bool camera = CheckAgentCameraUpdateSignificance(x); 5973 bool camera = CheckAgentCameraUpdateSignificance(x);
5903 5974
5904 m_thisAgentUpdateArgs.AgentID = x.AgentID;
5905 m_thisAgentUpdateArgs.BodyRotation = x.BodyRotation;
5906 m_thisAgentUpdateArgs.CameraAtAxis = x.CameraAtAxis;
5907 m_thisAgentUpdateArgs.CameraCenter = x.CameraCenter;
5908 m_thisAgentUpdateArgs.CameraLeftAxis = x.CameraLeftAxis;
5909 m_thisAgentUpdateArgs.CameraUpAxis = x.CameraUpAxis;
5910 m_thisAgentUpdateArgs.ControlFlags = x.ControlFlags;
5911 m_thisAgentUpdateArgs.Far = x.Far;
5912 m_thisAgentUpdateArgs.Flags = x.Flags;
5913 m_thisAgentUpdateArgs.HeadRotation = x.HeadRotation;
5914 m_thisAgentUpdateArgs.SessionID = x.SessionID;
5915 m_thisAgentUpdateArgs.State = x.State;
5916
5917 UpdateAgent handlerAgentUpdate = OnAgentUpdate;
5918 UpdateAgent handlerPreAgentUpdate = OnPreAgentUpdate;
5919 UpdateAgent handlerAgentCameraUpdate = OnAgentCameraUpdate;
5920
5921 // Was there a significant movement/state change? 5975 // Was there a significant movement/state change?
5922 if (movement) 5976 if (movement)
5923 { 5977 {
5978 m_thisAgentUpdateArgs.BodyRotation = x.BodyRotation;
5979 m_thisAgentUpdateArgs.ControlFlags = x.ControlFlags;
5980 m_thisAgentUpdateArgs.Far = x.Far;
5981 m_thisAgentUpdateArgs.Flags = x.Flags;
5982 m_thisAgentUpdateArgs.HeadRotation = x.HeadRotation;
5983// m_thisAgentUpdateArgs.SessionID = x.SessionID;
5984 m_thisAgentUpdateArgs.State = x.State;
5985
5986 UpdateAgent handlerAgentUpdate = OnAgentUpdate;
5987 UpdateAgent handlerPreAgentUpdate = OnPreAgentUpdate;
5988
5924 if (handlerPreAgentUpdate != null) 5989 if (handlerPreAgentUpdate != null)
5925 OnPreAgentUpdate(this, m_thisAgentUpdateArgs); 5990 OnPreAgentUpdate(this, m_thisAgentUpdateArgs);
5926 5991
5927 if (handlerAgentUpdate != null) 5992 if (handlerAgentUpdate != null)
5928 OnAgentUpdate(this, m_thisAgentUpdateArgs); 5993 OnAgentUpdate(this, m_thisAgentUpdateArgs);
5994
5995 handlerAgentUpdate = null;
5996 handlerPreAgentUpdate = null;
5929 } 5997 }
5998
5930 // Was there a significant camera(s) change? 5999 // Was there a significant camera(s) change?
5931 if (camera) 6000 if (camera)
6001 {
6002 m_thisAgentUpdateArgs.CameraAtAxis = x.CameraAtAxis;
6003 m_thisAgentUpdateArgs.CameraCenter = x.CameraCenter;
6004 m_thisAgentUpdateArgs.CameraLeftAxis = x.CameraLeftAxis;
6005 m_thisAgentUpdateArgs.CameraUpAxis = x.CameraUpAxis;
6006
6007 UpdateAgent handlerAgentCameraUpdate = OnAgentCameraUpdate;
6008
5932 if (handlerAgentCameraUpdate != null) 6009 if (handlerAgentCameraUpdate != null)
5933 handlerAgentCameraUpdate(this, m_thisAgentUpdateArgs); 6010 handlerAgentCameraUpdate(this, m_thisAgentUpdateArgs);
5934 6011
5935 handlerAgentUpdate = null; 6012 handlerAgentCameraUpdate = null;
5936 handlerPreAgentUpdate = null; 6013 }
5937 handlerAgentCameraUpdate = null;
5938 6014
5939 PacketPool.Instance.ReturnPacket(packet); 6015 PacketPool.Instance.ReturnPacket(packet);
5940 6016
@@ -6150,6 +6226,29 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6150 return true; 6226 return true;
6151 } 6227 }
6152 6228
6229 private bool HandleVelocityInterpolateOff(IClientAPI sender, Packet Pack)
6230 {
6231 VelocityInterpolateOffPacket p = (VelocityInterpolateOffPacket)Pack;
6232 if (p.AgentData.SessionID != SessionId ||
6233 p.AgentData.AgentID != AgentId)
6234 return true;
6235
6236 m_VelocityInterpolate = false;
6237 return true;
6238 }
6239
6240 private bool HandleVelocityInterpolateOn(IClientAPI sender, Packet Pack)
6241 {
6242 VelocityInterpolateOnPacket p = (VelocityInterpolateOnPacket)Pack;
6243 if (p.AgentData.SessionID != SessionId ||
6244 p.AgentData.AgentID != AgentId)
6245 return true;
6246
6247 m_VelocityInterpolate = true;
6248 return true;
6249 }
6250
6251
6153 private bool HandleAvatarPropertiesRequest(IClientAPI sender, Packet Pack) 6252 private bool HandleAvatarPropertiesRequest(IClientAPI sender, Packet Pack)
6154 { 6253 {
6155 AvatarPropertiesRequestPacket avatarProperties = (AvatarPropertiesRequestPacket)Pack; 6254 AvatarPropertiesRequestPacket avatarProperties = (AvatarPropertiesRequestPacket)Pack;
@@ -6503,7 +6602,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6503 { 6602 {
6504 // Note: the ModifyTerrain event handler sends out updated packets before the end of this event. Therefore, 6603 // Note: the ModifyTerrain event handler sends out updated packets before the end of this event. Therefore,
6505 // a simple boolean value should work and perhaps queue up just a few terrain patch packets at the end of the edit. 6604 // a simple boolean value should work and perhaps queue up just a few terrain patch packets at the end of the edit.
6506 m_justEditedTerrain = true; // Prevent terrain packet (Land layer) from being queued, make it unreliable
6507 if (OnModifyTerrain != null) 6605 if (OnModifyTerrain != null)
6508 { 6606 {
6509 for (int i = 0; i < modify.ParcelData.Length; i++) 6607 for (int i = 0; i < modify.ParcelData.Length; i++)
@@ -6519,7 +6617,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6519 } 6617 }
6520 } 6618 }
6521 } 6619 }
6522 m_justEditedTerrain = false; // Queue terrain packet (Land layer) if necessary, make it reliable again
6523 } 6620 }
6524 6621
6525 return true; 6622 return true;
@@ -6581,16 +6678,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6581 for (int i = 0; i < appear.VisualParam.Length; i++) 6678 for (int i = 0; i < appear.VisualParam.Length; i++)
6582 visualparams[i] = appear.VisualParam[i].ParamValue; 6679 visualparams[i] = appear.VisualParam[i].ParamValue;
6583 //var b = appear.WearableData[0]; 6680 //var b = appear.WearableData[0];
6584 6681
6585 Primitive.TextureEntry te = null; 6682 Primitive.TextureEntry te = null;
6586 if (appear.ObjectData.TextureEntry.Length > 1) 6683 if (appear.ObjectData.TextureEntry.Length > 1)
6587 te = new Primitive.TextureEntry(appear.ObjectData.TextureEntry, 0, appear.ObjectData.TextureEntry.Length); 6684 te = new Primitive.TextureEntry(appear.ObjectData.TextureEntry, 0, appear.ObjectData.TextureEntry.Length);
6588 6685
6589 WearableCacheItem[] cacheitems = new WearableCacheItem[appear.WearableData.Length]; 6686 WearableCacheItem[] cacheitems = new WearableCacheItem[appear.WearableData.Length];
6590 for (int i=0; i<appear.WearableData.Length;i++) 6687 for (int i=0; i<appear.WearableData.Length;i++)
6591 cacheitems[i] = new WearableCacheItem(){CacheId = appear.WearableData[i].CacheID,TextureIndex=Convert.ToUInt32(appear.WearableData[i].TextureIndex)}; 6688 cacheitems[i] = new WearableCacheItem(){
6592 6689 CacheId = appear.WearableData[i].CacheID,
6690 TextureIndex=Convert.ToUInt32(appear.WearableData[i].TextureIndex)
6691 };
6593 6692
6693
6594 6694
6595 handlerSetAppearance(sender, te, visualparams,avSize, cacheitems); 6695 handlerSetAppearance(sender, te, visualparams,avSize, cacheitems);
6596 } 6696 }
@@ -6794,13 +6894,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6794 return true; 6894 return true;
6795 } 6895 }
6796 6896
6797 private bool HandleCompleteAgentMovement(IClientAPI sender, Packet Pack) 6897 private bool HandleCompleteAgentMovement(IClientAPI sender, Packet Pack)
6798 { 6898 {
6899 m_log.DebugFormat("[LLClientView] HandleCompleteAgentMovement");
6900
6799 Action<IClientAPI, bool> handlerCompleteMovementToRegion = OnCompleteMovementToRegion; 6901 Action<IClientAPI, bool> handlerCompleteMovementToRegion = OnCompleteMovementToRegion;
6800 if (handlerCompleteMovementToRegion != null) 6902 if (handlerCompleteMovementToRegion != null)
6801 { 6903 {
6802 handlerCompleteMovementToRegion(sender, true); 6904 handlerCompleteMovementToRegion(sender, true);
6803 } 6905 }
6906 else
6907 m_log.Debug("HandleCompleteAgentMovement NULL handler");
6908
6804 handlerCompleteMovementToRegion = null; 6909 handlerCompleteMovementToRegion = null;
6805 6910
6806 return true; 6911 return true;
@@ -6818,7 +6923,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6818 return true; 6923 return true;
6819 } 6924 }
6820 #endregion 6925 #endregion
6821 6926/*
6822 StartAnim handlerStartAnim = null; 6927 StartAnim handlerStartAnim = null;
6823 StopAnim handlerStopAnim = null; 6928 StopAnim handlerStopAnim = null;
6824 6929
@@ -6842,6 +6947,25 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6842 } 6947 }
6843 } 6948 }
6844 return true; 6949 return true;
6950*/
6951 ChangeAnim handlerChangeAnim = null;
6952
6953 for (int i = 0; i < AgentAni.AnimationList.Length; i++)
6954 {
6955 handlerChangeAnim = OnChangeAnim;
6956 if (handlerChangeAnim != null)
6957 {
6958 handlerChangeAnim(AgentAni.AnimationList[i].AnimID, AgentAni.AnimationList[i].StartAnim, false);
6959 }
6960 }
6961
6962 handlerChangeAnim = OnChangeAnim;
6963 if (handlerChangeAnim != null)
6964 {
6965 handlerChangeAnim(UUID.Zero, false, true);
6966 }
6967
6968 return true;
6845 } 6969 }
6846 6970
6847 private bool HandleAgentRequestSit(IClientAPI sender, Packet Pack) 6971 private bool HandleAgentRequestSit(IClientAPI sender, Packet Pack)
@@ -7087,6 +7211,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
7087 #endregion 7211 #endregion
7088 7212
7089 m_udpClient.SetThrottles(atpack.Throttle.Throttles); 7213 m_udpClient.SetThrottles(atpack.Throttle.Throttles);
7214 GenericCall2 handler = OnUpdateThrottles;
7215 if (handler != null)
7216 {
7217 handler();
7218 }
7090 return true; 7219 return true;
7091 } 7220 }
7092 7221
@@ -7359,6 +7488,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
7359 7488
7360 for (int i = 0; i < incomingselect.ObjectData.Length; i++) 7489 for (int i = 0; i < incomingselect.ObjectData.Length; i++)
7361 { 7490 {
7491 if (!SelectedObjects.Contains(incomingselect.ObjectData[i].ObjectLocalID))
7492 SelectedObjects.Add(incomingselect.ObjectData[i].ObjectLocalID);
7362 handlerObjectSelect = OnObjectSelect; 7493 handlerObjectSelect = OnObjectSelect;
7363 if (handlerObjectSelect != null) 7494 if (handlerObjectSelect != null)
7364 { 7495 {
@@ -7385,6 +7516,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
7385 7516
7386 for (int i = 0; i < incomingdeselect.ObjectData.Length; i++) 7517 for (int i = 0; i < incomingdeselect.ObjectData.Length; i++)
7387 { 7518 {
7519 if (!SelectedObjects.Contains(incomingdeselect.ObjectData[i].ObjectLocalID))
7520 SelectedObjects.Add(incomingdeselect.ObjectData[i].ObjectLocalID);
7388 handlerObjectDeselect = OnObjectDeselect; 7521 handlerObjectDeselect = OnObjectDeselect;
7389 if (handlerObjectDeselect != null) 7522 if (handlerObjectDeselect != null)
7390 { 7523 {
@@ -7511,7 +7644,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
7511 physdata.Bounce = phsblock.Restitution; 7644 physdata.Bounce = phsblock.Restitution;
7512 physdata.Density = phsblock.Density; 7645 physdata.Density = phsblock.Density;
7513 physdata.Friction = phsblock.Friction; 7646 physdata.Friction = phsblock.Friction;
7514 physdata.GravitationModifier = phsblock.GravityMultiplier; 7647 physdata.GravitationModifier = phsblock.GravityMultiplier;
7515 } 7648 }
7516 7649
7517 handlerUpdatePrimFlags(flags.AgentData.ObjectLocalID, UsePhysics, IsTemporary, IsPhantom, physdata, this); 7650 handlerUpdatePrimFlags(flags.AgentData.ObjectLocalID, UsePhysics, IsTemporary, IsPhantom, physdata, this);
@@ -8097,6 +8230,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
8097 // surrounding scene 8230 // surrounding scene
8098 if ((ImageType)block.Type == ImageType.Baked) 8231 if ((ImageType)block.Type == ImageType.Baked)
8099 args.Priority *= 2.0f; 8232 args.Priority *= 2.0f;
8233 int wearableout = 0;
8100 8234
8101 ImageManager.EnqueueReq(args); 8235 ImageManager.EnqueueReq(args);
8102 } 8236 }
@@ -9106,7 +9240,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
9106 if ((locX >= m_scene.RegionInfo.WorldLocX) 9240 if ((locX >= m_scene.RegionInfo.WorldLocX)
9107 && (locX < (m_scene.RegionInfo.WorldLocX + m_scene.RegionInfo.RegionSizeX)) 9241 && (locX < (m_scene.RegionInfo.WorldLocX + m_scene.RegionInfo.RegionSizeX))
9108 && (locY >= m_scene.RegionInfo.WorldLocY) 9242 && (locY >= m_scene.RegionInfo.WorldLocY)
9109 && (locY < (m_scene.RegionInfo.WorldLocY + m_scene.RegionInfo.RegionSizeY)) ) 9243 && (locY < (m_scene.RegionInfo.WorldLocY + m_scene.RegionInfo.RegionSizeY)))
9110 { 9244 {
9111 tpLocReq.Info.RegionHandle = m_scene.RegionInfo.RegionHandle; 9245 tpLocReq.Info.RegionHandle = m_scene.RegionInfo.RegionHandle;
9112 tpLocReq.Info.Position.X += locX - m_scene.RegionInfo.WorldLocX; 9246 tpLocReq.Info.Position.X += locX - m_scene.RegionInfo.WorldLocX;
@@ -9146,16 +9280,61 @@ namespace OpenSim.Region.ClientStack.LindenUDP
9146 9280
9147 #region Parcel related packets 9281 #region Parcel related packets
9148 9282
9283 // acumulate several HandleRegionHandleRequest consecutive overlaping requests
9284 // to be done with minimal resources as possible
9285 // variables temporary here while in test
9286
9287 Queue<UUID> RegionHandleRequests = new Queue<UUID>();
9288 bool RegionHandleRequestsInService = false;
9289
9149 private bool HandleRegionHandleRequest(IClientAPI sender, Packet Pack) 9290 private bool HandleRegionHandleRequest(IClientAPI sender, Packet Pack)
9150 { 9291 {
9151 RegionHandleRequestPacket rhrPack = (RegionHandleRequestPacket)Pack; 9292 UUID currentUUID;
9152 9293
9153 RegionHandleRequest handlerRegionHandleRequest = OnRegionHandleRequest; 9294 RegionHandleRequest handlerRegionHandleRequest = OnRegionHandleRequest;
9154 if (handlerRegionHandleRequest != null) 9295
9296 if (handlerRegionHandleRequest == null)
9297 return true;
9298
9299 RegionHandleRequestPacket rhrPack = (RegionHandleRequestPacket)Pack;
9300
9301 lock (RegionHandleRequests)
9155 { 9302 {
9156 handlerRegionHandleRequest(this, rhrPack.RequestBlock.RegionID); 9303 if (RegionHandleRequestsInService)
9304 {
9305 // we are already busy doing a previus request
9306 // so enqueue it
9307 RegionHandleRequests.Enqueue(rhrPack.RequestBlock.RegionID);
9308 return true;
9309 }
9310
9311 // else do it
9312 currentUUID = rhrPack.RequestBlock.RegionID;
9313 RegionHandleRequestsInService = true;
9157 } 9314 }
9158 return true; 9315
9316 while (true)
9317 {
9318 handlerRegionHandleRequest(this, currentUUID);
9319
9320 lock (RegionHandleRequests)
9321 {
9322 // exit condition, nothing to do or closed
9323 // current code seems to assume we may loose the handler at anytime,
9324 // so keep checking it
9325 handlerRegionHandleRequest = OnRegionHandleRequest;
9326
9327 if (RegionHandleRequests.Count == 0 || !IsActive || handlerRegionHandleRequest == null)
9328 {
9329 RegionHandleRequests.Clear();
9330 RegionHandleRequestsInService = false;
9331 return true;
9332 }
9333 currentUUID = RegionHandleRequests.Dequeue();
9334 }
9335 }
9336
9337 return true; // actually unreached
9159 } 9338 }
9160 9339
9161 private bool HandleParcelInfoRequest(IClientAPI sender, Packet Pack) 9340 private bool HandleParcelInfoRequest(IClientAPI sender, Packet Pack)
@@ -10425,7 +10604,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
10425 handlerUpdateMuteListEntry(this, UpdateMuteListEntry.MuteData.MuteID, 10604 handlerUpdateMuteListEntry(this, UpdateMuteListEntry.MuteData.MuteID,
10426 Utils.BytesToString(UpdateMuteListEntry.MuteData.MuteName), 10605 Utils.BytesToString(UpdateMuteListEntry.MuteData.MuteName),
10427 UpdateMuteListEntry.MuteData.MuteType, 10606 UpdateMuteListEntry.MuteData.MuteType,
10428 UpdateMuteListEntry.AgentData.AgentID); 10607 UpdateMuteListEntry.MuteData.MuteFlags);
10429 return true; 10608 return true;
10430 } 10609 }
10431 return false; 10610 return false;
@@ -10440,8 +10619,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
10440 { 10619 {
10441 handlerRemoveMuteListEntry(this, 10620 handlerRemoveMuteListEntry(this,
10442 RemoveMuteListEntry.MuteData.MuteID, 10621 RemoveMuteListEntry.MuteData.MuteID,
10443 Utils.BytesToString(RemoveMuteListEntry.MuteData.MuteName), 10622 Utils.BytesToString(RemoveMuteListEntry.MuteData.MuteName));
10444 RemoveMuteListEntry.AgentData.AgentID);
10445 return true; 10623 return true;
10446 } 10624 }
10447 return false; 10625 return false;
@@ -10485,10 +10663,55 @@ namespace OpenSim.Region.ClientStack.LindenUDP
10485 return false; 10663 return false;
10486 } 10664 }
10487 10665
10666 private bool HandleChangeInventoryItemFlags(IClientAPI client, Packet packet)
10667 {
10668 ChangeInventoryItemFlagsPacket ChangeInventoryItemFlags =
10669 (ChangeInventoryItemFlagsPacket)packet;
10670 ChangeInventoryItemFlags handlerChangeInventoryItemFlags = OnChangeInventoryItemFlags;
10671 if (handlerChangeInventoryItemFlags != null)
10672 {
10673 foreach(ChangeInventoryItemFlagsPacket.InventoryDataBlock b in ChangeInventoryItemFlags.InventoryData)
10674 handlerChangeInventoryItemFlags(this, b.ItemID, b.Flags);
10675 return true;
10676 }
10677 return false;
10678 }
10679
10488 private bool HandleUseCircuitCode(IClientAPI sender, Packet Pack) 10680 private bool HandleUseCircuitCode(IClientAPI sender, Packet Pack)
10489 { 10681 {
10490 return true; 10682 return true;
10491 } 10683 }
10684
10685 private bool HandleCreateNewOutfitAttachments(IClientAPI sender, Packet Pack)
10686 {
10687 CreateNewOutfitAttachmentsPacket packet = (CreateNewOutfitAttachmentsPacket)Pack;
10688
10689 #region Packet Session and User Check
10690 if (m_checkPackets)
10691 {
10692 if (packet.AgentData.SessionID != SessionId ||
10693 packet.AgentData.AgentID != AgentId)
10694 return true;
10695 }
10696 #endregion
10697 MoveItemsAndLeaveCopy handlerMoveItemsAndLeaveCopy = null;
10698 List<InventoryItemBase> items = new List<InventoryItemBase>();
10699 foreach (CreateNewOutfitAttachmentsPacket.ObjectDataBlock n in packet.ObjectData)
10700 {
10701 InventoryItemBase b = new InventoryItemBase();
10702 b.ID = n.OldItemID;
10703 b.Folder = n.OldFolderID;
10704 items.Add(b);
10705 }
10706
10707 handlerMoveItemsAndLeaveCopy = OnMoveItemsAndLeaveCopy;
10708 if (handlerMoveItemsAndLeaveCopy != null)
10709 {
10710 handlerMoveItemsAndLeaveCopy(this, items, packet.HeaderData.NewFolderID);
10711 }
10712
10713 return true;
10714 }
10492 10715
10493 private bool HandleAgentHeightWidth(IClientAPI sender, Packet Pack) 10716 private bool HandleAgentHeightWidth(IClientAPI sender, Packet Pack)
10494 { 10717 {
@@ -10915,6 +11138,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP
10915 groupProfileReply.GroupData.MaturePublish = d.MaturePublish; 11138 groupProfileReply.GroupData.MaturePublish = d.MaturePublish;
10916 groupProfileReply.GroupData.OwnerRole = d.OwnerRole; 11139 groupProfileReply.GroupData.OwnerRole = d.OwnerRole;
10917 11140
11141 Scene scene = (Scene)m_scene;
11142 if (scene.Permissions.IsGod(sender.AgentId) && (!sender.IsGroupMember(groupProfileRequest.GroupData.GroupID)))
11143 {
11144 ScenePresence p;
11145 if (scene.TryGetScenePresence(sender.AgentId, out p))
11146 {
11147 if (p.GodLevel >= 200)
11148 {
11149 groupProfileReply.GroupData.OpenEnrollment = true;
11150 groupProfileReply.GroupData.MembershipFee = 0;
11151 }
11152 }
11153 }
11154
10918 OutPacket(groupProfileReply, ThrottleOutPacketType.Task); 11155 OutPacket(groupProfileReply, ThrottleOutPacketType.Task);
10919 } 11156 }
10920 return true; 11157 return true;
@@ -11488,11 +11725,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11488 11725
11489 StartLure handlerStartLure = OnStartLure; 11726 StartLure handlerStartLure = OnStartLure;
11490 if (handlerStartLure != null) 11727 if (handlerStartLure != null)
11491 handlerStartLure(startLureRequest.Info.LureType, 11728 {
11492 Utils.BytesToString( 11729 for (int i = 0 ; i < startLureRequest.TargetData.Length ; i++)
11493 startLureRequest.Info.Message), 11730 {
11494 startLureRequest.TargetData[0].TargetID, 11731 handlerStartLure(startLureRequest.Info.LureType,
11495 this); 11732 Utils.BytesToString(
11733 startLureRequest.Info.Message),
11734 startLureRequest.TargetData[i].TargetID,
11735 this);
11736 }
11737 }
11496 return true; 11738 return true;
11497 } 11739 }
11498 private bool HandleTeleportLureRequest(IClientAPI sender, Packet Pack) 11740 private bool HandleTeleportLureRequest(IClientAPI sender, Packet Pack)
@@ -11606,10 +11848,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11606 } 11848 }
11607 #endregion 11849 #endregion
11608 11850
11609 ClassifiedDelete handlerClassifiedGodDelete = OnClassifiedGodDelete; 11851 ClassifiedGodDelete handlerClassifiedGodDelete = OnClassifiedGodDelete;
11610 if (handlerClassifiedGodDelete != null) 11852 if (handlerClassifiedGodDelete != null)
11611 handlerClassifiedGodDelete( 11853 handlerClassifiedGodDelete(
11612 classifiedGodDelete.Data.ClassifiedID, 11854 classifiedGodDelete.Data.ClassifiedID,
11855 classifiedGodDelete.Data.QueryID,
11613 this); 11856 this);
11614 return true; 11857 return true;
11615 } 11858 }
@@ -11912,6 +12155,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11912 /// <param name="simclient"></param> 12155 /// <param name="simclient"></param>
11913 /// <param name="packet"></param> 12156 /// <param name="packet"></param>
11914 /// <returns></returns> 12157 /// <returns></returns>
12158 // TODO: Convert old handler to use new method
12159/*
11915 protected bool HandleAgentTextureCached(IClientAPI simclient, Packet packet) 12160 protected bool HandleAgentTextureCached(IClientAPI simclient, Packet packet)
11916 { 12161 {
11917 AgentCachedTexturePacket cachedtex = (AgentCachedTexturePacket)packet; 12162 AgentCachedTexturePacket cachedtex = (AgentCachedTexturePacket)packet;
@@ -11919,6 +12164,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11919 12164
11920 if (cachedtex.AgentData.SessionID != SessionId) 12165 if (cachedtex.AgentData.SessionID != SessionId)
11921 return false; 12166 return false;
12167
11922 12168
11923 12169
11924 // TODO: don't create new blocks if recycling an old packet 12170 // TODO: don't create new blocks if recycling an old packet
@@ -11966,32 +12212,61 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11966 } 12212 }
11967 } 12213 }
11968 12214
11969 if (cacheItems != null) 12215 CachedTextureRequest handlerCachedTextureRequest = OnCachedTextureRequest;
12216 if (handlerCachedTextureRequest != null)
11970 { 12217 {
11971 // We need to make sure the asset stored in the bake is available on this server also by its assetid before we map it to a Cacheid. 12218 handlerCachedTextureRequest(simclient,cachedtex.AgentData.SerialNum,requestArgs);
11972 // Copy the baked textures to the sim's assets cache (local only). 12219 }
11973 foreach (WearableCacheItem item in cacheItems) 12220
11974 { 12221 return true;
11975 if (cache.GetCached(item.TextureID.ToString()) == null) 12222 }
11976 { 12223*/
11977 item.TextureAsset.Temporary = true; 12224
11978 item.TextureAsset.Local = true; 12225 protected bool HandleAgentTextureCached(IClientAPI simclient, Packet packet)
11979 cache.Store(item.TextureAsset); 12226 {
11980 } 12227 //m_log.Debug("texture cached: " + packet.ToString());
11981 } 12228 AgentCachedTexturePacket cachedtex = (AgentCachedTexturePacket)packet;
12229 AgentCachedTextureResponsePacket cachedresp = (AgentCachedTextureResponsePacket)PacketPool.Instance.GetPacket(PacketType.AgentCachedTextureResponse);
12230
12231 if (cachedtex.AgentData.SessionID != SessionId)
12232 return false;
12233
12234 // TODO: don't create new blocks if recycling an old packet
12235 cachedresp.AgentData.AgentID = AgentId;
12236 cachedresp.AgentData.SessionID = m_sessionId;
12237 cachedresp.AgentData.SerialNum = cachedtex.AgentData.SerialNum;
12238 cachedresp.WearableData =
12239 new AgentCachedTextureResponsePacket.WearableDataBlock[cachedtex.WearableData.Length];
12240
12241 int cacheHits = 0;
12242
12243 // We need to make sure the asset stored in the bake is available on this server also by it's assetid before we map it to a Cacheid
12244
12245 WearableCacheItem[] cacheItems = null;
11982 12246
11983 // Return the cached textures 12247 ScenePresence p = m_scene.GetScenePresence(AgentId);
12248
12249 if (p != null && p.Appearance != null)
12250 {
12251 cacheItems = p.Appearance.WearableCacheItems;
12252 }
12253
12254 int maxWearablesLoop = cachedtex.WearableData.Length;
12255 if (maxWearablesLoop > cacheItems.Length)
12256 maxWearablesLoop = cacheItems.Length;
12257
12258 if (cacheItems != null)
12259 {
11984 for (int i = 0; i < maxWearablesLoop; i++) 12260 for (int i = 0; i < maxWearablesLoop; i++)
11985 { 12261 {
11986 WearableCacheItem item = 12262 int idx = cachedtex.WearableData[i].TextureIndex;
11987 WearableCacheItem.SearchTextureIndex(cachedtex.WearableData[i].TextureIndex, cacheItems);
11988
11989 cachedresp.WearableData[i] = new AgentCachedTextureResponsePacket.WearableDataBlock(); 12263 cachedresp.WearableData[i] = new AgentCachedTextureResponsePacket.WearableDataBlock();
11990 cachedresp.WearableData[i].TextureIndex = cachedtex.WearableData[i].TextureIndex; 12264 cachedresp.WearableData[i].TextureIndex = cachedtex.WearableData[i].TextureIndex;
11991 cachedresp.WearableData[i].HostName = new byte[0]; 12265 cachedresp.WearableData[i].HostName = new byte[0];
11992 if (item != null && cachedtex.WearableData[i].ID == item.CacheId) 12266 if (cachedtex.WearableData[i].ID == cacheItems[idx].CacheId)
11993 { 12267 {
11994 cachedresp.WearableData[i].TextureID = item.TextureID; 12268 cachedresp.WearableData[i].TextureID = cacheItems[idx].TextureID;
12269 cacheHits++;
11995 } 12270 }
11996 else 12271 else
11997 { 12272 {
@@ -12001,7 +12276,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
12001 } 12276 }
12002 else 12277 else
12003 { 12278 {
12004 // Cached textures not available
12005 for (int i = 0; i < maxWearablesLoop; i++) 12279 for (int i = 0; i < maxWearablesLoop; i++)
12006 { 12280 {
12007 cachedresp.WearableData[i] = new AgentCachedTextureResponsePacket.WearableDataBlock(); 12281 cachedresp.WearableData[i] = new AgentCachedTextureResponsePacket.WearableDataBlock();
@@ -12010,13 +12284,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
12010 cachedresp.WearableData[i].HostName = new byte[0]; 12284 cachedresp.WearableData[i].HostName = new byte[0];
12011 } 12285 }
12012 } 12286 }
12013 12287
12288 m_log.DebugFormat("texture cached: hits {0}", cacheHits);
12289
12014 cachedresp.Header.Zerocoded = true; 12290 cachedresp.Header.Zerocoded = true;
12015 OutPacket(cachedresp, ThrottleOutPacketType.Task); 12291 OutPacket(cachedresp, ThrottleOutPacketType.Task);
12016 12292
12017 return true; 12293 return true;
12018 } 12294 }
12019 12295
12020 /// <summary> 12296 /// <summary>
12021 /// Send a response back to a client when it asks the asset server (via the region server) if it has 12297 /// Send a response back to a client when it asks the asset server (via the region server) if it has
12022 /// its appearance texture cached. 12298 /// its appearance texture cached.
@@ -12080,209 +12356,147 @@ namespace OpenSim.Region.ClientStack.LindenUDP
12080 } 12356 }
12081 else 12357 else
12082 { 12358 {
12083// m_log.DebugFormat( 12359 ClientChangeObject updatehandler = onClientChangeObject;
12084// "[CLIENT]: Processing block {0} type {1} for {2} {3}",
12085// i, block.Type, part.Name, part.LocalId);
12086 12360
12087// // Do this once since fetch parts creates a new array. 12361 if (updatehandler != null)
12088// SceneObjectPart[] parts = part.ParentGroup.Parts; 12362 {
12089// for (int j = 0; j < parts.Length; j++) 12363 ObjectChangeData udata = new ObjectChangeData();
12090// {
12091// part.StoreUndoState();
12092// parts[j].IgnoreUndoUpdate = true;
12093// }
12094 12364
12095 UpdatePrimGroupRotation handlerUpdatePrimGroupRotation; 12365 /*ubit from ll JIRA:
12366 * 0x01 position
12367 * 0x02 rotation
12368 * 0x04 scale
12369
12370 * 0x08 LINK_SET
12371 * 0x10 UNIFORM for scale
12372 */
12096 12373
12097 switch (block.Type) 12374 // translate to internal changes
12098 { 12375 // not all cases .. just the ones older code did
12099 case 1:
12100 Vector3 pos1 = new Vector3(block.Data, 0);
12101 12376
12102 UpdateVector handlerUpdatePrimSinglePosition = OnUpdatePrimSinglePosition; 12377 switch (block.Type)
12103 if (handlerUpdatePrimSinglePosition != null) 12378 {
12104 { 12379 case 1: //change position sp
12105 // m_log.Debug("new movement position is " + pos.X + " , " + pos.Y + " , " + pos.Z); 12380 udata.position = new Vector3(block.Data, 0);
12106 handlerUpdatePrimSinglePosition(localId, pos1, this);
12107 }
12108 break;
12109 12381
12110 case 2: 12382 udata.change = ObjectChangeType.primP;
12111 Quaternion rot1 = new Quaternion(block.Data, 0, true); 12383 updatehandler(localId, udata, this);
12384 break;
12112 12385
12113 UpdatePrimSingleRotation handlerUpdatePrimSingleRotation = OnUpdatePrimSingleRotation; 12386 case 2: // rotation sp
12114 if (handlerUpdatePrimSingleRotation != null) 12387 udata.rotation = new Quaternion(block.Data, 0, true);
12115 {
12116 // m_log.Info("new tab rotation is " + rot1.X + " , " + rot1.Y + " , " + rot1.Z + " , " + rot1.W);
12117 handlerUpdatePrimSingleRotation(localId, rot1, this);
12118 }
12119 break;
12120 12388
12121 case 3: 12389 udata.change = ObjectChangeType.primR;
12122 Vector3 rotPos = new Vector3(block.Data, 0); 12390 updatehandler(localId, udata, this);
12123 Quaternion rot2 = new Quaternion(block.Data, 12, true); 12391 break;
12124 12392
12125 UpdatePrimSingleRotationPosition handlerUpdatePrimSingleRotationPosition = OnUpdatePrimSingleRotationPosition; 12393 case 3: // position plus rotation
12126 if (handlerUpdatePrimSingleRotationPosition != null) 12394 udata.position = new Vector3(block.Data, 0);
12127 { 12395 udata.rotation = new Quaternion(block.Data, 12, true);
12128 // m_log.Debug("new mouse rotation position is " + rotPos.X + " , " + rotPos.Y + " , " + rotPos.Z);
12129 // m_log.Info("new mouse rotation is " + rot2.X + " , " + rot2.Y + " , " + rot2.Z + " , " + rot2.W);
12130 handlerUpdatePrimSingleRotationPosition(localId, rot2, rotPos, this);
12131 }
12132 break;
12133 12396
12134 case 4: 12397 udata.change = ObjectChangeType.primPR;
12135 case 20: 12398 updatehandler(localId, udata, this);
12136 Vector3 scale4 = new Vector3(block.Data, 0); 12399 break;
12137 12400
12138 UpdateVector handlerUpdatePrimScale = OnUpdatePrimScale; 12401 case 4: // scale sp
12139 if (handlerUpdatePrimScale != null) 12402 udata.scale = new Vector3(block.Data, 0);
12140 { 12403 udata.change = ObjectChangeType.primS;
12141 // m_log.Debug("new scale is " + scale4.X + " , " + scale4.Y + " , " + scale4.Z);
12142 handlerUpdatePrimScale(localId, scale4, this);
12143 }
12144 break;
12145 12404
12146 case 5: 12405 updatehandler(localId, udata, this);
12147 Vector3 scale1 = new Vector3(block.Data, 12); 12406 break;
12148 Vector3 pos11 = new Vector3(block.Data, 0);
12149 12407
12150 handlerUpdatePrimScale = OnUpdatePrimScale; 12408 case 0x14: // uniform scale sp
12151 if (handlerUpdatePrimScale != null) 12409 udata.scale = new Vector3(block.Data, 0);
12152 {
12153 // m_log.Debug("new scale is " + scale.X + " , " + scale.Y + " , " + scale.Z);
12154 handlerUpdatePrimScale(localId, scale1, this);
12155 12410
12156 handlerUpdatePrimSinglePosition = OnUpdatePrimSinglePosition; 12411 udata.change = ObjectChangeType.primUS;
12157 if (handlerUpdatePrimSinglePosition != null) 12412 updatehandler(localId, udata, this);
12158 { 12413 break;
12159 handlerUpdatePrimSinglePosition(localId, pos11, this);
12160 }
12161 }
12162 break;
12163 12414
12164 case 9: 12415 case 5: // scale and position sp
12165 Vector3 pos2 = new Vector3(block.Data, 0); 12416 udata.position = new Vector3(block.Data, 0);
12417 udata.scale = new Vector3(block.Data, 12);
12166 12418
12167 UpdateVector handlerUpdateVector = OnUpdatePrimGroupPosition; 12419 udata.change = ObjectChangeType.primPS;
12420 updatehandler(localId, udata, this);
12421 break;
12168 12422
12169 if (handlerUpdateVector != null) 12423 case 0x15: //uniform scale and position
12170 { 12424 udata.position = new Vector3(block.Data, 0);
12171 handlerUpdateVector(localId, pos2, this); 12425 udata.scale = new Vector3(block.Data, 12);
12172 }
12173 break;
12174 12426
12175 case 10: 12427 udata.change = ObjectChangeType.primPUS;
12176 Quaternion rot3 = new Quaternion(block.Data, 0, true); 12428 updatehandler(localId, udata, this);
12429 break;
12177 12430
12178 UpdatePrimRotation handlerUpdatePrimRotation = OnUpdatePrimGroupRotation; 12431 // now group related (bit 4)
12179 if (handlerUpdatePrimRotation != null) 12432 case 9: //( 8 + 1 )group position
12180 { 12433 udata.position = new Vector3(block.Data, 0);
12181 // Console.WriteLine("new rotation is " + rot3.X + " , " + rot3.Y + " , " + rot3.Z + " , " + rot3.W);
12182 handlerUpdatePrimRotation(localId, rot3, this);
12183 }
12184 break;
12185 12434
12186 case 11: 12435 udata.change = ObjectChangeType.groupP;
12187 Vector3 pos3 = new Vector3(block.Data, 0); 12436 updatehandler(localId, udata, this);
12188 Quaternion rot4 = new Quaternion(block.Data, 12, true); 12437 break;
12189 12438
12190 handlerUpdatePrimGroupRotation = OnUpdatePrimGroupMouseRotation; 12439 case 0x0A: // (8 + 2) group rotation
12191 if (handlerUpdatePrimGroupRotation != null) 12440 udata.rotation = new Quaternion(block.Data, 0, true);
12192 {
12193 // m_log.Debug("new rotation position is " + pos.X + " , " + pos.Y + " , " + pos.Z);
12194 // m_log.Debug("new group mouse rotation is " + rot4.X + " , " + rot4.Y + " , " + rot4.Z + " , " + rot4.W);
12195 handlerUpdatePrimGroupRotation(localId, pos3, rot4, this);
12196 }
12197 break;
12198 case 12:
12199 case 28:
12200 Vector3 scale7 = new Vector3(block.Data, 0);
12201 12441
12202 UpdateVector handlerUpdatePrimGroupScale = OnUpdatePrimGroupScale; 12442 udata.change = ObjectChangeType.groupR;
12203 if (handlerUpdatePrimGroupScale != null) 12443 updatehandler(localId, udata, this);
12204 { 12444 break;
12205 // m_log.Debug("new scale is " + scale7.X + " , " + scale7.Y + " , " + scale7.Z);
12206 handlerUpdatePrimGroupScale(localId, scale7, this);
12207 }
12208 break;
12209 12445
12210 case 13: 12446 case 0x0B: //( 8 + 2 + 1) group rotation and position
12211 Vector3 scale2 = new Vector3(block.Data, 12); 12447 udata.position = new Vector3(block.Data, 0);
12212 Vector3 pos4 = new Vector3(block.Data, 0); 12448 udata.rotation = new Quaternion(block.Data, 12, true);
12213 12449
12214 handlerUpdatePrimScale = OnUpdatePrimScale; 12450 udata.change = ObjectChangeType.groupPR;
12215 if (handlerUpdatePrimScale != null) 12451 updatehandler(localId, udata, this);
12216 { 12452 break;
12217 //m_log.Debug("new scale is " + scale.X + " , " + scale.Y + " , " + scale.Z);
12218 handlerUpdatePrimScale(localId, scale2, this);
12219 12453
12220 // Change the position based on scale (for bug number 246) 12454 case 0x0C: // (8 + 4) group scale
12221 handlerUpdatePrimSinglePosition = OnUpdatePrimSinglePosition; 12455 // only afects root prim and only sent by viewer editor object tab scaling
12222 // m_log.Debug("new movement position is " + pos.X + " , " + pos.Y + " , " + pos.Z); 12456 // mouse edition only allows uniform scaling
12223 if (handlerUpdatePrimSinglePosition != null) 12457 // SL MAY CHANGE THIS in viewers
12224 {
12225 handlerUpdatePrimSinglePosition(localId, pos4, this);
12226 }
12227 }
12228 break;
12229 12458
12230 case 29: 12459 udata.scale = new Vector3(block.Data, 0);
12231 Vector3 scale5 = new Vector3(block.Data, 12);
12232 Vector3 pos5 = new Vector3(block.Data, 0);
12233 12460
12234 handlerUpdatePrimGroupScale = OnUpdatePrimGroupScale; 12461 udata.change = ObjectChangeType.groupS;
12235 if (handlerUpdatePrimGroupScale != null) 12462 updatehandler(localId, udata, this);
12236 {
12237 // m_log.Debug("new scale is " + scale.X + " , " + scale.Y + " , " + scale.Z);
12238 part.StoreUndoState(true);
12239 part.IgnoreUndoUpdate = true;
12240 handlerUpdatePrimGroupScale(localId, scale5, this);
12241 handlerUpdateVector = OnUpdatePrimGroupPosition;
12242 12463
12243 if (handlerUpdateVector != null) 12464 break;
12244 {
12245 handlerUpdateVector(localId, pos5, this);
12246 }
12247 12465
12248 part.IgnoreUndoUpdate = false; 12466 case 0x0D: //(8 + 4 + 1) group scale and position
12249 } 12467 // exception as above
12250 12468
12251 break; 12469 udata.position = new Vector3(block.Data, 0);
12470 udata.scale = new Vector3(block.Data, 12);
12252 12471
12253 case 21: 12472 udata.change = ObjectChangeType.groupPS;
12254 Vector3 scale6 = new Vector3(block.Data, 12); 12473 updatehandler(localId, udata, this);
12255 Vector3 pos6 = new Vector3(block.Data, 0); 12474 break;
12256 12475
12257 handlerUpdatePrimScale = OnUpdatePrimScale; 12476 case 0x1C: // (0x10 + 8 + 4 ) group scale UNIFORM
12258 if (handlerUpdatePrimScale != null) 12477 udata.scale = new Vector3(block.Data, 0);
12259 {
12260 part.StoreUndoState(false);
12261 part.IgnoreUndoUpdate = true;
12262 12478
12263 // m_log.Debug("new scale is " + scale.X + " , " + scale.Y + " , " + scale.Z); 12479 udata.change = ObjectChangeType.groupUS;
12264 handlerUpdatePrimScale(localId, scale6, this); 12480 updatehandler(localId, udata, this);
12265 handlerUpdatePrimSinglePosition = OnUpdatePrimSinglePosition; 12481 break;
12266 if (handlerUpdatePrimSinglePosition != null)
12267 {
12268 handlerUpdatePrimSinglePosition(localId, pos6, this);
12269 }
12270 12482
12271 part.IgnoreUndoUpdate = false; 12483 case 0x1D: // (UNIFORM + GROUP + SCALE + POS)
12272 } 12484 udata.position = new Vector3(block.Data, 0);
12273 break; 12485 udata.scale = new Vector3(block.Data, 12);
12274 12486
12275 default: 12487 udata.change = ObjectChangeType.groupPUS;
12276 m_log.Debug("[CLIENT]: MultipleObjUpdate recieved an unknown packet type: " + (block.Type)); 12488 updatehandler(localId, udata, this);
12277 break; 12489 break;
12490
12491 default:
12492 m_log.Debug("[CLIENT]: MultipleObjUpdate recieved an unknown packet type: " + (block.Type));
12493 break;
12494 }
12278 } 12495 }
12279 12496
12280// for (int j = 0; j < parts.Length; j++)
12281// parts[j].IgnoreUndoUpdate = false;
12282 } 12497 }
12283 } 12498 }
12284 } 12499 }
12285
12286 return true; 12500 return true;
12287 } 12501 }
12288 12502
@@ -12342,7 +12556,31 @@ namespace OpenSim.Region.ClientStack.LindenUDP
12342 /// <param name="throttles"></param> 12556 /// <param name="throttles"></param>
12343 public void SetChildAgentThrottle(byte[] throttles) 12557 public void SetChildAgentThrottle(byte[] throttles)
12344 { 12558 {
12345 m_udpClient.SetThrottles(throttles); 12559 SetChildAgentThrottle(throttles, 1.0f);
12560 }
12561
12562 public void SetChildAgentThrottle(byte[] throttles,float factor)
12563 {
12564 m_udpClient.SetThrottles(throttles, factor);
12565 GenericCall2 handler = OnUpdateThrottles;
12566 if (handler != null)
12567 {
12568 handler();
12569 }
12570 }
12571
12572 /// <summary>
12573 /// Sets the throttles from values supplied caller
12574 /// </summary>
12575 /// <param name="throttles"></param>
12576 public void SetAgentThrottleSilent(int throttle, int setting)
12577 {
12578 m_udpClient.ForceThrottleSetting(throttle,setting);
12579 }
12580
12581 public int GetAgentThrottleSilent(int throttle)
12582 {
12583 return m_udpClient.GetThrottleSetting(throttle);
12346 } 12584 }
12347 12585
12348 /// <summary> 12586 /// <summary>
@@ -12450,8 +12688,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
12450 uint regionY = 0; 12688 uint regionY = 0;
12451 12689
12452 Utils.LongToUInts(m_scene.RegionInfo.RegionHandle, out regionX, out regionY); 12690 Utils.LongToUInts(m_scene.RegionInfo.RegionHandle, out regionX, out regionY);
12453 locx = Convert.ToSingle(args[0]) - (float)regionX; 12691 locx = (float)(Convert.ToDouble(args[0]) - (double)regionX);
12454 locy = Convert.ToSingle(args[1]) - (float)regionY; 12692 locy = (float)(Convert.ToDouble(args[1]) - (double)regionY);
12455 locz = Convert.ToSingle(args[2]); 12693 locz = Convert.ToSingle(args[2]);
12456 12694
12457 Action<Vector3, bool, bool> handlerAutoPilotGo = OnAutoPilotGo; 12695 Action<Vector3, bool, bool> handlerAutoPilotGo = OnAutoPilotGo;
@@ -12736,7 +12974,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
12736// "[LLCLIENTVIEW]: Received transfer request for {0} in {1} type {2} by {3}", 12974// "[LLCLIENTVIEW]: Received transfer request for {0} in {1} type {2} by {3}",
12737// requestID, taskID, (SourceType)sourceType, Name); 12975// requestID, taskID, (SourceType)sourceType, Name);
12738 12976
12977
12978 //Note, the bool returned from the below function is useless since it is always false.
12739 m_assetService.Get(requestID.ToString(), transferRequest, AssetReceived); 12979 m_assetService.Get(requestID.ToString(), transferRequest, AssetReceived);
12980
12740 } 12981 }
12741 12982
12742 /// <summary> 12983 /// <summary>
@@ -12819,7 +13060,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
12819 /// <returns></returns> 13060 /// <returns></returns>
12820 private static int CalculateNumPackets(byte[] data) 13061 private static int CalculateNumPackets(byte[] data)
12821 { 13062 {
12822 const uint m_maxPacketSize = 600; 13063// const uint m_maxPacketSize = 600;
13064 uint m_maxPacketSize = MaxTransferBytesPerPacket;
12823 int numPackets = 1; 13065 int numPackets = 1;
12824 13066
12825 if (data == null) 13067 if (data == null)
@@ -12930,7 +13172,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
12930 // this is the username of the *owner* 13172 // this is the username of the *owner*
12931 dialog.Data.FirstName = Util.StringToBytes256(ownerFirstName); 13173 dialog.Data.FirstName = Util.StringToBytes256(ownerFirstName);
12932 dialog.Data.LastName = Util.StringToBytes256(ownerLastName); 13174 dialog.Data.LastName = Util.StringToBytes256(ownerLastName);
12933 dialog.Data.Message = Util.StringToBytes256(message); 13175 dialog.Data.Message = Util.StringToBytes(message,512);
12934 13176
12935 ScriptDialogPacket.ButtonsBlock[] buttons = new ScriptDialogPacket.ButtonsBlock[1]; 13177 ScriptDialogPacket.ButtonsBlock[] buttons = new ScriptDialogPacket.ButtonsBlock[1];
12936 buttons[0] = new ScriptDialogPacket.ButtonsBlock(); 13178 buttons[0] = new ScriptDialogPacket.ButtonsBlock();
@@ -12962,8 +13204,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
12962 ImprovedTerseObjectUpdatePacket.ObjectDataBlock block = 13204 ImprovedTerseObjectUpdatePacket.ObjectDataBlock block =
12963 CreateImprovedTerseBlock(p, false); 13205 CreateImprovedTerseBlock(p, false);
12964 13206
12965 const float TIME_DILATION = 1.0f; 13207// const float TIME_DILATION = 1.0f;
12966 ushort timeDilation = Utils.FloatToUInt16(TIME_DILATION, 0.0f, 1.0f); 13208 ushort timeDilation = Utils.FloatToUInt16(m_scene.TimeDilation, 0.0f, 1.0f);;
12967 13209
12968 ImprovedTerseObjectUpdatePacket packet 13210 ImprovedTerseObjectUpdatePacket packet
12969 = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket( 13211 = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs
index 0394e54..36e0a0e 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs
@@ -96,9 +96,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
96 set 96 set
97 { 97 {
98 m_throttleDebugLevel = value; 98 m_throttleDebugLevel = value;
99/*
99 m_throttleClient.DebugLevel = m_throttleDebugLevel; 100 m_throttleClient.DebugLevel = m_throttleDebugLevel;
100 foreach (TokenBucket tb in m_throttleCategories) 101 foreach (TokenBucket tb in m_throttleCategories)
101 tb.DebugLevel = m_throttleDebugLevel; 102 tb.DebugLevel = m_throttleDebugLevel;
103 */
102 } 104 }
103 } 105 }
104 private int m_throttleDebugLevel; 106 private int m_throttleDebugLevel;
@@ -120,16 +122,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
120 /// <summary>Sequence numbers of packets we've received (for duplicate checking)</summary> 122 /// <summary>Sequence numbers of packets we've received (for duplicate checking)</summary>
121 public readonly IncomingPacketHistoryCollection PacketArchive = new IncomingPacketHistoryCollection(200); 123 public readonly IncomingPacketHistoryCollection PacketArchive = new IncomingPacketHistoryCollection(200);
122 124
123 /// <summary>
124 /// If true then we take action in response to unacked reliably sent packets such as resending the packet.
125 /// </summary>
126 public bool ProcessUnackedSends { get; set; }
127
128 /// <summary>Packets we have sent that need to be ACKed by the client</summary> 125 /// <summary>Packets we have sent that need to be ACKed by the client</summary>
129 public readonly UnackedPacketCollection NeedAcks = new UnackedPacketCollection(); 126 public readonly UnackedPacketCollection NeedAcks = new UnackedPacketCollection();
130 127
131 /// <summary>ACKs that are queued up, waiting to be sent to the client</summary> 128 /// <summary>ACKs that are queued up, waiting to be sent to the client</summary>
132 public readonly OpenSim.Framework.LocklessQueue<uint> PendingAcks = new OpenSim.Framework.LocklessQueue<uint>(); 129 public readonly DoubleLocklessQueue<uint> PendingAcks = new DoubleLocklessQueue<uint>();
133 130
134 /// <summary>Current packet sequence number</summary> 131 /// <summary>Current packet sequence number</summary>
135 public int CurrentSequence; 132 public int CurrentSequence;
@@ -181,7 +178,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
181 /// <summary>Throttle buckets for each packet category</summary> 178 /// <summary>Throttle buckets for each packet category</summary>
182 private readonly TokenBucket[] m_throttleCategories; 179 private readonly TokenBucket[] m_throttleCategories;
183 /// <summary>Outgoing queues for throttled packets</summary> 180 /// <summary>Outgoing queues for throttled packets</summary>
184 private readonly OpenSim.Framework.LocklessQueue<OutgoingPacket>[] m_packetOutboxes = new OpenSim.Framework.LocklessQueue<OutgoingPacket>[THROTTLE_CATEGORY_COUNT]; 181 private readonly DoubleLocklessQueue<OutgoingPacket>[] m_packetOutboxes = new DoubleLocklessQueue<OutgoingPacket>[THROTTLE_CATEGORY_COUNT];
185 /// <summary>A container that can hold one packet for each outbox, used to store 182 /// <summary>A container that can hold one packet for each outbox, used to store
186 /// dequeued packets that are being held for throttling</summary> 183 /// dequeued packets that are being held for throttling</summary>
187 private readonly OutgoingPacket[] m_nextPackets = new OutgoingPacket[THROTTLE_CATEGORY_COUNT]; 184 private readonly OutgoingPacket[] m_nextPackets = new OutgoingPacket[THROTTLE_CATEGORY_COUNT];
@@ -193,6 +190,24 @@ namespace OpenSim.Region.ClientStack.LindenUDP
193 190
194 private int m_defaultRTO = 1000; // 1sec is the recommendation in the RFC 191 private int m_defaultRTO = 1000; // 1sec is the recommendation in the RFC
195 private int m_maxRTO = 60000; 192 private int m_maxRTO = 60000;
193 public bool m_deliverPackets = true;
194
195 private float m_burstTime;
196
197 public int m_lastStartpingTimeMS;
198 public int m_pingMS;
199
200 public int PingTimeMS
201 {
202 get
203 {
204 if (m_pingMS < 10)
205 return 10;
206 if(m_pingMS > 2000)
207 return 2000;
208 return m_pingMS;
209 }
210 }
196 211
197 /// <summary> 212 /// <summary>
198 /// This is the percentage of the udp texture queue to add to the task queue since 213 /// This is the percentage of the udp texture queue to add to the task queue since
@@ -232,31 +247,27 @@ namespace OpenSim.Region.ClientStack.LindenUDP
232 if (maxRTO != 0) 247 if (maxRTO != 0)
233 m_maxRTO = maxRTO; 248 m_maxRTO = maxRTO;
234 249
235 ProcessUnackedSends = true; 250 m_burstTime = rates.BrustTime;
251 float m_burst = rates.ClientMaxRate * m_burstTime;
236 252
237 // Create a token bucket throttle for this client that has the scene token bucket as a parent 253 // Create a token bucket throttle for this client that has the scene token bucket as a parent
238 m_throttleClient 254 m_throttleClient = new AdaptiveTokenBucket(parentThrottle, rates.ClientMaxRate, m_burst, rates.AdaptiveThrottlesEnabled);
239 = new AdaptiveTokenBucket(
240 string.Format("adaptive throttle for {0} in {1}", AgentID, server.Scene.Name),
241 parentThrottle, 0, rates.Total, rates.MinimumAdaptiveThrottleRate, rates.AdaptiveThrottlesEnabled);
242 255
243 // Create an array of token buckets for this clients different throttle categories 256 // Create an array of token buckets for this clients different throttle categories
244 m_throttleCategories = new TokenBucket[THROTTLE_CATEGORY_COUNT]; 257 m_throttleCategories = new TokenBucket[THROTTLE_CATEGORY_COUNT];
245 258
246 m_cannibalrate = rates.CannibalizeTextureRate; 259 m_cannibalrate = rates.CannibalizeTextureRate;
247 260
261 m_burst = rates.Total * rates.BrustTime;
262
248 for (int i = 0; i < THROTTLE_CATEGORY_COUNT; i++) 263 for (int i = 0; i < THROTTLE_CATEGORY_COUNT; i++)
249 { 264 {
250 ThrottleOutPacketType type = (ThrottleOutPacketType)i; 265 ThrottleOutPacketType type = (ThrottleOutPacketType)i;
251 266
252 // Initialize the packet outboxes, where packets sit while they are waiting for tokens 267 // Initialize the packet outboxes, where packets sit while they are waiting for tokens
253 m_packetOutboxes[i] = new OpenSim.Framework.LocklessQueue<OutgoingPacket>(); 268 m_packetOutboxes[i] = new DoubleLocklessQueue<OutgoingPacket>();
254
255 // Initialize the token buckets that control the throttling for each category 269 // Initialize the token buckets that control the throttling for each category
256 m_throttleCategories[i] 270 m_throttleCategories[i] = new TokenBucket(m_throttleClient, rates.GetRate(type), m_burst);
257 = new TokenBucket(
258 string.Format("{0} throttle for {1} in {2}", type, AgentID, server.Scene.Name),
259 m_throttleClient, rates.GetRate(type), 0);
260 } 271 }
261 272
262 // Default the retransmission timeout to one second 273 // Default the retransmission timeout to one second
@@ -264,6 +275,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
264 275
265 // Initialize this to a sane value to prevent early disconnects 276 // Initialize this to a sane value to prevent early disconnects
266 TickLastPacketReceived = Environment.TickCount & Int32.MaxValue; 277 TickLastPacketReceived = Environment.TickCount & Int32.MaxValue;
278 m_pingMS = (int)(3.0 * server.TickCountResolution); // so filter doesnt start at 0;
267 } 279 }
268 280
269 /// <summary> 281 /// <summary>
@@ -302,9 +314,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
302 m_info.assetThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Asset].DripRate; 314 m_info.assetThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Asset].DripRate;
303 m_info.textureThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Texture].DripRate; 315 m_info.textureThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Texture].DripRate;
304 m_info.totalThrottle = (int)m_throttleClient.DripRate; 316 m_info.totalThrottle = (int)m_throttleClient.DripRate;
305 m_info.targetThrottle = (int)m_throttleClient.TargetDripRate;
306 m_info.maxThrottle = (int)m_throttleClient.MaxDripRate;
307
308 return m_info; 317 return m_info;
309 } 318 }
310 319
@@ -341,8 +350,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
341 /// <param name="throttleType"></param> 350 /// <param name="throttleType"></param>
342 public int GetPacketsQueuedCount(ThrottleOutPacketType throttleType) 351 public int GetPacketsQueuedCount(ThrottleOutPacketType throttleType)
343 { 352 {
344 if ((int)throttleType > 0) 353 int icat = (int)throttleType;
345 return m_packetOutboxes[(int)throttleType].Count; 354 if (icat > 0 && icat < THROTTLE_CATEGORY_COUNT)
355 return m_packetOutboxes[icat].Count;
346 else 356 else
347 return 0; 357 return 0;
348 } 358 }
@@ -389,6 +399,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
389 399
390 public void SetThrottles(byte[] throttleData) 400 public void SetThrottles(byte[] throttleData)
391 { 401 {
402 SetThrottles(throttleData, 1.0f);
403 }
404
405 public void SetThrottles(byte[] throttleData, float factor)
406 {
392 byte[] adjData; 407 byte[] adjData;
393 int pos = 0; 408 int pos = 0;
394 409
@@ -408,24 +423,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP
408 } 423 }
409 424
410 // 0.125f converts from bits to bytes 425 // 0.125f converts from bits to bytes
411 int resend = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4; 426 float scale = 0.125f * factor;
412 int land = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4; 427 int resend = (int)(BitConverter.ToSingle(adjData, pos) * scale); pos += 4;
413 int wind = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4; 428 int land = (int)(BitConverter.ToSingle(adjData, pos) * scale); pos += 4;
414 int cloud = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4; 429 int wind = (int)(BitConverter.ToSingle(adjData, pos) * scale); pos += 4;
415 int task = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4; 430 int cloud = (int)(BitConverter.ToSingle(adjData, pos) * scale); pos += 4;
416 int texture = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4; 431 int task = (int)(BitConverter.ToSingle(adjData, pos) * scale); pos += 4;
417 int asset = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); 432 int texture = (int)(BitConverter.ToSingle(adjData, pos) * scale); pos += 4;
433 int asset = (int)(BitConverter.ToSingle(adjData, pos) * scale);
434
418 435
419 if (ThrottleDebugLevel > 0)
420 {
421 long total = resend + land + wind + cloud + task + texture + asset;
422 m_log.DebugFormat(
423 "[LLUDPCLIENT]: {0} is setting throttles in {1} to Resend={2}, Land={3}, Wind={4}, Cloud={5}, Task={6}, Texture={7}, Asset={8}, TOTAL = {9}",
424 AgentID, m_udpServer.Scene.Name, resend, land, wind, cloud, task, texture, asset, total);
425 }
426 436
427 // Make sure none of the throttles are set below our packet MTU, 437 // Make sure none of the throttles are set below our packet MTU,
428 // otherwise a throttle could become permanently clogged 438 // otherwise a throttle could become permanently clogged
439
440/* now using floats
429 resend = Math.Max(resend, LLUDPServer.MTU); 441 resend = Math.Max(resend, LLUDPServer.MTU);
430 land = Math.Max(land, LLUDPServer.MTU); 442 land = Math.Max(land, LLUDPServer.MTU);
431 wind = Math.Max(wind, LLUDPServer.MTU); 443 wind = Math.Max(wind, LLUDPServer.MTU);
@@ -433,52 +445,54 @@ namespace OpenSim.Region.ClientStack.LindenUDP
433 task = Math.Max(task, LLUDPServer.MTU); 445 task = Math.Max(task, LLUDPServer.MTU);
434 texture = Math.Max(texture, LLUDPServer.MTU); 446 texture = Math.Max(texture, LLUDPServer.MTU);
435 asset = Math.Max(asset, LLUDPServer.MTU); 447 asset = Math.Max(asset, LLUDPServer.MTU);
448*/
436 449
437 // Since most textures are now delivered through http, make it possible 450 // Since most textures are now delivered through http, make it possible
438 // to cannibalize some of the bw from the texture throttle to use for 451 // to cannibalize some of the bw from the texture throttle to use for
439 // the task queue (e.g. object updates) 452 // the task queue (e.g. object updates)
440 task = task + (int)(m_cannibalrate * texture); 453 task = task + (int)(m_cannibalrate * texture);
441 texture = (int)((1 - m_cannibalrate) * texture); 454 texture = (int)((1 - m_cannibalrate) * texture);
442 455
443 //int total = resend + land + wind + cloud + task + texture + asset; 456 int total = resend + land + wind + cloud + task + texture + asset;
457
458 float m_burst = total * m_burstTime;
444 459
445 if (ThrottleDebugLevel > 0) 460 if (ThrottleDebugLevel > 0)
446 { 461 {
447 long total = resend + land + wind + cloud + task + texture + asset;
448 m_log.DebugFormat( 462 m_log.DebugFormat(
449 "[LLUDPCLIENT]: {0} is setting throttles in {1} to Resend={2}, Land={3}, Wind={4}, Cloud={5}, Task={6}, Texture={7}, Asset={8}, TOTAL = {9}", 463 "[LLUDPCLIENT]: {0} is setting throttles in {1} to Resend={2}, Land={3}, Wind={4}, Cloud={5}, Task={6}, Texture={7}, Asset={8}, TOTAL = {9}",
450 AgentID, m_udpServer.Scene.Name, resend, land, wind, cloud, task, texture, asset, total); 464 AgentID, m_udpServer.Scene.Name, resend, land, wind, cloud, task, texture, asset, total);
451 } 465 }
452 466
453 // Update the token buckets with new throttle values
454 if (m_throttleClient.AdaptiveEnabled)
455 {
456 long total = resend + land + wind + cloud + task + texture + asset;
457 m_throttleClient.TargetDripRate = total;
458 }
459
460 TokenBucket bucket; 467 TokenBucket bucket;
461 468
462 bucket = m_throttleCategories[(int)ThrottleOutPacketType.Resend]; 469 bucket = m_throttleCategories[(int)ThrottleOutPacketType.Resend];
463 bucket.RequestedDripRate = resend; 470 bucket.RequestedDripRate = resend;
471 bucket.RequestedBurst = m_burst;
464 472
465 bucket = m_throttleCategories[(int)ThrottleOutPacketType.Land]; 473 bucket = m_throttleCategories[(int)ThrottleOutPacketType.Land];
466 bucket.RequestedDripRate = land; 474 bucket.RequestedDripRate = land;
475 bucket.RequestedBurst = m_burst;
467 476
468 bucket = m_throttleCategories[(int)ThrottleOutPacketType.Wind]; 477 bucket = m_throttleCategories[(int)ThrottleOutPacketType.Wind];
469 bucket.RequestedDripRate = wind; 478 bucket.RequestedDripRate = wind;
479 bucket.RequestedBurst = m_burst;
470 480
471 bucket = m_throttleCategories[(int)ThrottleOutPacketType.Cloud]; 481 bucket = m_throttleCategories[(int)ThrottleOutPacketType.Cloud];
472 bucket.RequestedDripRate = cloud; 482 bucket.RequestedDripRate = cloud;
483 bucket.RequestedBurst = m_burst;
473 484
474 bucket = m_throttleCategories[(int)ThrottleOutPacketType.Asset]; 485 bucket = m_throttleCategories[(int)ThrottleOutPacketType.Asset];
475 bucket.RequestedDripRate = asset; 486 bucket.RequestedDripRate = asset;
487 bucket.RequestedBurst = m_burst;
476 488
477 bucket = m_throttleCategories[(int)ThrottleOutPacketType.Task]; 489 bucket = m_throttleCategories[(int)ThrottleOutPacketType.Task];
478 bucket.RequestedDripRate = task; 490 bucket.RequestedDripRate = task;
491 bucket.RequestedBurst = m_burst;
479 492
480 bucket = m_throttleCategories[(int)ThrottleOutPacketType.Texture]; 493 bucket = m_throttleCategories[(int)ThrottleOutPacketType.Texture];
481 bucket.RequestedDripRate = texture; 494 bucket.RequestedDripRate = texture;
495 bucket.RequestedBurst = m_burst;
482 496
483 // Reset the packed throttles cached data 497 // Reset the packed throttles cached data
484 m_packedThrottles = null; 498 m_packedThrottles = null;
@@ -496,25 +510,27 @@ namespace OpenSim.Region.ClientStack.LindenUDP
496 int i = 0; 510 int i = 0;
497 511
498 // multiply by 8 to convert bytes back to bits 512 // multiply by 8 to convert bytes back to bits
499 rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Resend].RequestedDripRate * 8 * multiplier; 513 multiplier *= 8;
514
515 rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Resend].RequestedDripRate * multiplier;
500 Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4; 516 Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4;
501 517
502 rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Land].RequestedDripRate * 8 * multiplier; 518 rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Land].RequestedDripRate * multiplier;
503 Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4; 519 Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4;
504 520
505 rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Wind].RequestedDripRate * 8 * multiplier; 521 rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Wind].RequestedDripRate * multiplier;
506 Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4; 522 Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4;
507 523
508 rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Cloud].RequestedDripRate * 8 * multiplier; 524 rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Cloud].RequestedDripRate * multiplier;
509 Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4; 525 Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4;
510 526
511 rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Task].RequestedDripRate * 8 * multiplier; 527 rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Task].RequestedDripRate * multiplier;
512 Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4; 528 Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4;
513 529
514 rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Texture].RequestedDripRate * 8 * multiplier; 530 rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Texture].RequestedDripRate * multiplier;
515 Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4; 531 Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4;
516 532
517 rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Asset].RequestedDripRate * 8 * multiplier; 533 rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Asset].RequestedDripRate * multiplier;
518 Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4; 534 Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4;
519 535
520 m_packedThrottles = data; 536 m_packedThrottles = data;
@@ -522,6 +538,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP
522 538
523 return data; 539 return data;
524 } 540 }
541
542 public int GetCatBytesCanSend(ThrottleOutPacketType cat, int timeMS)
543 {
544 int icat = (int)cat;
545 if (icat > 0 && icat < THROTTLE_CATEGORY_COUNT)
546 {
547 TokenBucket bucket = m_throttleCategories[icat];
548 return bucket.GetCatBytesCanSend(timeMS);
549 }
550 else
551 return 0;
552 }
525 553
526 /// <summary> 554 /// <summary>
527 /// Queue an outgoing packet if appropriate. 555 /// Queue an outgoing packet if appropriate.
@@ -534,32 +562,42 @@ namespace OpenSim.Region.ClientStack.LindenUDP
534 /// </returns> 562 /// </returns>
535 public bool EnqueueOutgoing(OutgoingPacket packet, bool forceQueue) 563 public bool EnqueueOutgoing(OutgoingPacket packet, bool forceQueue)
536 { 564 {
565 return EnqueueOutgoing(packet, forceQueue, false);
566 }
567
568 public bool EnqueueOutgoing(OutgoingPacket packet, bool forceQueue, bool highPriority)
569 {
537 int category = (int)packet.Category; 570 int category = (int)packet.Category;
538 571
539 if (category >= 0 && category < m_packetOutboxes.Length) 572 if (category >= 0 && category < m_packetOutboxes.Length)
540 { 573 {
541 OpenSim.Framework.LocklessQueue<OutgoingPacket> queue = m_packetOutboxes[category]; 574 DoubleLocklessQueue<OutgoingPacket> queue = m_packetOutboxes[category];
575
576 if (m_deliverPackets == false)
577 {
578 queue.Enqueue(packet, highPriority);
579 return true;
580 }
581
542 TokenBucket bucket = m_throttleCategories[category]; 582 TokenBucket bucket = m_throttleCategories[category];
543 583
544 // Don't send this packet if there is already a packet waiting in the queue 584 // Don't send this packet if queue is not empty
545 // even if we have the tokens to send it, tokens should go to the already 585 if (queue.Count > 0 || m_nextPackets[category] != null)
546 // queued packets
547 if (queue.Count > 0)
548 { 586 {
549 queue.Enqueue(packet); 587 queue.Enqueue(packet, highPriority);
550 return true; 588 return true;
551 } 589 }
552 590
553 591 if (!forceQueue && bucket.CheckTokens(packet.Buffer.DataLength))
554 if (!forceQueue && bucket.RemoveTokens(packet.Buffer.DataLength))
555 { 592 {
556 // Enough tokens were removed from the bucket, the packet will not be queued 593 // enough tokens so it can be sent imediatly by caller
594 bucket.RemoveTokens(packet.Buffer.DataLength);
557 return false; 595 return false;
558 } 596 }
559 else 597 else
560 { 598 {
561 // Force queue specified or not enough tokens in the bucket, queue this packet 599 // Force queue specified or not enough tokens in the bucket, queue this packet
562 queue.Enqueue(packet); 600 queue.Enqueue(packet, highPriority);
563 return true; 601 return true;
564 } 602 }
565 } 603 }
@@ -568,6 +606,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
568 // We don't have a token bucket for this category, so it will not be queued 606 // We don't have a token bucket for this category, so it will not be queued
569 return false; 607 return false;
570 } 608 }
609
571 } 610 }
572 611
573 /// <summary> 612 /// <summary>
@@ -588,8 +627,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
588 /// <returns>True if any packets were sent, otherwise false</returns> 627 /// <returns>True if any packets were sent, otherwise false</returns>
589 public bool DequeueOutgoing() 628 public bool DequeueOutgoing()
590 { 629 {
591 OutgoingPacket packet; 630// if (m_deliverPackets == false) return false;
592 OpenSim.Framework.LocklessQueue<OutgoingPacket> queue; 631
632 OutgoingPacket packet = null;
633 DoubleLocklessQueue<OutgoingPacket> queue;
593 TokenBucket bucket; 634 TokenBucket bucket;
594 bool packetSent = false; 635 bool packetSent = false;
595 ThrottleOutPacketTypeFlags emptyCategories = 0; 636 ThrottleOutPacketTypeFlags emptyCategories = 0;
@@ -613,6 +654,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
613 m_udpServer.SendPacketFinal(nextPacket); 654 m_udpServer.SendPacketFinal(nextPacket);
614 m_nextPackets[i] = null; 655 m_nextPackets[i] = null;
615 packetSent = true; 656 packetSent = true;
657
658 if (m_packetOutboxes[i].Count < 5)
659 emptyCategories |= CategoryToFlag(i);
616 } 660 }
617 } 661 }
618 else 662 else
@@ -620,32 +664,47 @@ namespace OpenSim.Region.ClientStack.LindenUDP
620 // No dequeued packet waiting to be sent, try to pull one off 664 // No dequeued packet waiting to be sent, try to pull one off
621 // this queue 665 // this queue
622 queue = m_packetOutboxes[i]; 666 queue = m_packetOutboxes[i];
623 if (queue.Dequeue(out packet)) 667 if (queue != null)
624 { 668 {
625 // A packet was pulled off the queue. See if we have 669 bool success = false;
626 // enough tokens in the bucket to send it out 670 try
627 if (bucket.RemoveTokens(packet.Buffer.DataLength))
628 { 671 {
629 // Send the packet 672 success = queue.Dequeue(out packet);
630 m_udpServer.SendPacketFinal(packet);
631 packetSent = true;
632 } 673 }
633 else 674 catch
634 { 675 {
635 // Save the dequeued packet for the next iteration 676 m_packetOutboxes[i] = new DoubleLocklessQueue<OutgoingPacket>();
636 m_nextPackets[i] = packet;
637 } 677 }
678 if (success)
679 {
680 // A packet was pulled off the queue. See if we have
681 // enough tokens in the bucket to send it out
682 if (bucket.RemoveTokens(packet.Buffer.DataLength))
683 {
684 // Send the packet
685 m_udpServer.SendPacketFinal(packet);
686 packetSent = true;
687
688 if (queue.Count < 5)
689 emptyCategories |= CategoryToFlag(i);
690 }
691 else
692 {
693 // Save the dequeued packet for the next iteration
694 m_nextPackets[i] = packet;
695 }
638 696
639 // If the queue is empty after this dequeue, fire the queue 697 }
640 // empty callback now so it has a chance to fill before we 698 else
641 // get back here 699 {
642 if (queue.Count == 0) 700 // No packets in this queue. Fire the queue empty callback
701 // if it has not been called recently
643 emptyCategories |= CategoryToFlag(i); 702 emptyCategories |= CategoryToFlag(i);
703 }
644 } 704 }
645 else 705 else
646 { 706 {
647 // No packets in this queue. Fire the queue empty callback 707 m_packetOutboxes[i] = new DoubleLocklessQueue<OutgoingPacket>();
648 // if it has not been called recently
649 emptyCategories |= CategoryToFlag(i); 708 emptyCategories |= CategoryToFlag(i);
650 } 709 }
651 } 710 }
@@ -712,6 +771,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
712 RTO = Math.Min(RTO * 2, m_maxRTO); 771 RTO = Math.Min(RTO * 2, m_maxRTO);
713 } 772 }
714 773
774
775 const int MIN_CALLBACK_MS = 10;
776
715 /// <summary> 777 /// <summary>
716 /// Does an early check to see if this queue empty callback is already 778 /// Does an early check to see if this queue empty callback is already
717 /// running, then asynchronously firing the event 779 /// running, then asynchronously firing the event
@@ -719,24 +781,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP
719 /// <param name="categories">Throttle categories to fire the callback for</param> 781 /// <param name="categories">Throttle categories to fire the callback for</param>
720 private void BeginFireQueueEmpty(ThrottleOutPacketTypeFlags categories) 782 private void BeginFireQueueEmpty(ThrottleOutPacketTypeFlags categories)
721 { 783 {
722// if (m_nextOnQueueEmpty != 0 && (Environment.TickCount & Int32.MaxValue) >= m_nextOnQueueEmpty) 784 if (!m_isQueueEmptyRunning)
723 if (!m_isQueueEmptyRunning && (Environment.TickCount & Int32.MaxValue) >= m_nextOnQueueEmpty)
724 { 785 {
725 m_isQueueEmptyRunning = true;
726
727 int start = Environment.TickCount & Int32.MaxValue; 786 int start = Environment.TickCount & Int32.MaxValue;
728 const int MIN_CALLBACK_MS = 30; 787
788 if (start < m_nextOnQueueEmpty)
789 return;
790
791 m_isQueueEmptyRunning = true;
729 792
730 m_nextOnQueueEmpty = start + MIN_CALLBACK_MS; 793 m_nextOnQueueEmpty = start + MIN_CALLBACK_MS;
731 if (m_nextOnQueueEmpty == 0) 794 if (m_nextOnQueueEmpty == 0)
732 m_nextOnQueueEmpty = 1; 795 m_nextOnQueueEmpty = 1;
733 796
734 // Use a value of 0 to signal that FireQueueEmpty is running 797 if (HasUpdates(categories))
735// m_nextOnQueueEmpty = 0;
736
737 m_categories = categories;
738
739 if (HasUpdates(m_categories))
740 { 798 {
741 if (!m_udpServer.OqrEngine.IsRunning) 799 if (!m_udpServer.OqrEngine.IsRunning)
742 { 800 {
@@ -756,7 +814,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
756 } 814 }
757 815
758 private bool m_isQueueEmptyRunning; 816 private bool m_isQueueEmptyRunning;
759 private ThrottleOutPacketTypeFlags m_categories = 0; 817
760 818
761 /// <summary> 819 /// <summary>
762 /// Fires the OnQueueEmpty callback and sets the minimum time that it 820 /// Fires the OnQueueEmpty callback and sets the minimum time that it
@@ -767,33 +825,33 @@ namespace OpenSim.Region.ClientStack.LindenUDP
767 /// signature</param> 825 /// signature</param>
768 public void FireQueueEmpty(object o) 826 public void FireQueueEmpty(object o)
769 { 827 {
770// m_log.DebugFormat("[LLUDPCLIENT]: FireQueueEmpty for {0} in {1}", AgentID, m_udpServer.Scene.Name); 828 ThrottleOutPacketTypeFlags categories = (ThrottleOutPacketTypeFlags)o;
771 829 QueueEmpty callback = OnQueueEmpty;
772// int start = Environment.TickCount & Int32.MaxValue;
773// const int MIN_CALLBACK_MS = 30;
774 830
775// if (m_udpServer.IsRunningOutbound) 831 if (callback != null)
776// { 832 {
777 ThrottleOutPacketTypeFlags categories = (ThrottleOutPacketTypeFlags)o; 833 // if (m_udpServer.IsRunningOutbound)
778 QueueEmpty callback = OnQueueEmpty; 834 // {
779 835 try { callback(categories); }
780 if (callback != null) 836 catch (Exception e) { m_log.Error("[LLUDPCLIENT]: OnQueueEmpty(" + categories + ") threw an exception: " + e.Message, e); }
781 { 837 // }
782// if (m_udpServer.IsRunningOutbound) 838 }
783// {
784 try { callback(categories); }
785 catch (Exception e) { m_log.Error("[LLUDPCLIENT]: OnQueueEmpty(" + categories + ") threw an exception: " + e.Message, e); }
786// }
787 }
788// }
789 839
790// m_nextOnQueueEmpty = start + MIN_CALLBACK_MS; 840 m_isQueueEmptyRunning = false;
791// if (m_nextOnQueueEmpty == 0) 841 }
792// m_nextOnQueueEmpty = 1;
793 842
794// } 843 internal void ForceThrottleSetting(int throttle, int setting)
844 {
845 if (throttle > 0 && throttle < THROTTLE_CATEGORY_COUNT)
846 m_throttleCategories[throttle].RequestedDripRate = Math.Max(setting, LLUDPServer.MTU);
847 }
795 848
796 m_isQueueEmptyRunning = false; 849 internal int GetThrottleSetting(int throttle)
850 {
851 if (throttle > 0 && throttle < THROTTLE_CATEGORY_COUNT)
852 return (int)m_throttleCategories[throttle].RequestedDripRate;
853 else
854 return 0;
797 } 855 }
798 856
799 /// <summary> 857 /// <summary>
@@ -839,4 +897,33 @@ namespace OpenSim.Region.ClientStack.LindenUDP
839 } 897 }
840 } 898 }
841 } 899 }
900
901 public class DoubleLocklessQueue<T> : OpenSim.Framework.LocklessQueue<T>
902 {
903 OpenSim.Framework.LocklessQueue<T> highQueue = new OpenSim.Framework.LocklessQueue<T>();
904
905 public override int Count
906 {
907 get
908 {
909 return base.Count + highQueue.Count;
910 }
911 }
912
913 public override bool Dequeue(out T item)
914 {
915 if (highQueue.Dequeue(out item))
916 return true;
917
918 return base.Dequeue(out item);
919 }
920
921 public void Enqueue(T item, bool highPriority)
922 {
923 if (highPriority)
924 highQueue.Enqueue(item);
925 else
926 Enqueue(item);
927 }
928 }
842} 929}
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
index 4528714..8f345e7 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
@@ -284,7 +284,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
284 /// <summary>Handlers for incoming packets</summary> 284 /// <summary>Handlers for incoming packets</summary>
285 //PacketEventDictionary packetEvents = new PacketEventDictionary(); 285 //PacketEventDictionary packetEvents = new PacketEventDictionary();
286 /// <summary>Incoming packets that are awaiting handling</summary> 286 /// <summary>Incoming packets that are awaiting handling</summary>
287 private OpenMetaverse.BlockingQueue<IncomingPacket> packetInbox = new OpenMetaverse.BlockingQueue<IncomingPacket>(); 287 //private OpenMetaverse.BlockingQueue<IncomingPacket> packetInbox = new OpenMetaverse.BlockingQueue<IncomingPacket>();
288
289 private DoubleQueue<IncomingPacket> packetInbox = new DoubleQueue<IncomingPacket>();
288 290
289 /// <summary>Bandwidth throttle for this UDP server</summary> 291 /// <summary>Bandwidth throttle for this UDP server</summary>
290 public TokenBucket Throttle { get; private set; } 292 public TokenBucket Throttle { get; private set; }
@@ -342,14 +344,32 @@ namespace OpenSim.Region.ClientStack.LindenUDP
342 /// <summary>Flag to signal when clients should send pings</summary> 344 /// <summary>Flag to signal when clients should send pings</summary>
343 protected bool m_sendPing; 345 protected bool m_sendPing;
344 346
347 private int m_animationSequenceNumber;
348
349 public int NextAnimationSequenceNumber
350 {
351 get
352 {
353 m_animationSequenceNumber++;
354 if (m_animationSequenceNumber > 2147482624)
355 m_animationSequenceNumber = 1;
356 return m_animationSequenceNumber;
357 }
358 }
359
360
361
362 private ExpiringCache<IPEndPoint, Queue<UDPPacketBuffer>> m_pendingCache = new ExpiringCache<IPEndPoint, Queue<UDPPacketBuffer>>();
363
345 /// <summary> 364 /// <summary>
346 /// Event used to signal when queued packets are available for sending. 365 /// Event used to signal when queued packets are available for sending.
347 /// </summary> 366 /// </summary>
348 /// <remarks> 367 /// <remarks>
349 /// This allows the outbound loop to only operate when there is data to send rather than continuously polling. 368 /// This allows the outbound loop to only operate when there is data to send rather than continuously polling.
350 /// Some data is sent immediately and not queued. That data would not trigger this event. 369 /// Some data is sent immediately and not queued. That data would not trigger this event.
370 /// WRONG use. May be usefull in future revision
351 /// </remarks> 371 /// </remarks>
352 private AutoResetEvent m_dataPresentEvent = new AutoResetEvent(false); 372// private AutoResetEvent m_dataPresentEvent = new AutoResetEvent(false);
353 373
354 private Pool<IncomingPacket> m_incomingPacketPool; 374 private Pool<IncomingPacket> m_incomingPacketPool;
355 375
@@ -431,16 +451,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP
431 451
432 // Measure the resolution of Environment.TickCount 452 // Measure the resolution of Environment.TickCount
433 TickCountResolution = 0f; 453 TickCountResolution = 0f;
434 for (int i = 0; i < 5; i++) 454 for (int i = 0; i < 10; i++)
435 { 455 {
436 int start = Environment.TickCount; 456 int start = Environment.TickCount;
437 int now = start; 457 int now = start;
438 while (now == start) 458 while (now == start)
439 now = Environment.TickCount; 459 now = Environment.TickCount;
440 TickCountResolution += (float)(now - start) * 0.2f; 460 TickCountResolution += (float)(now - start) * 0.1f;
441 } 461 }
442 m_log.Info("[LLUDPSERVER]: Average Environment.TickCount resolution: " + TickCountResolution + "ms");
443 TickCountResolution = (float)Math.Ceiling(TickCountResolution); 462 TickCountResolution = (float)Math.Ceiling(TickCountResolution);
463 m_log.Info("[LLUDPSERVER]: Average Environment.TickCount resolution: " + TickCountResolution + "ms");
444 464
445 #endregion Environment.TickCount Measurement 465 #endregion Environment.TickCount Measurement
446 466
@@ -448,6 +468,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
448 int sceneThrottleBps = 0; 468 int sceneThrottleBps = 0;
449 bool usePools = false; 469 bool usePools = false;
450 470
471
472
451 IConfig config = configSource.Configs["ClientStack.LindenUDP"]; 473 IConfig config = configSource.Configs["ClientStack.LindenUDP"];
452 if (config != null) 474 if (config != null)
453 { 475 {
@@ -494,15 +516,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
494 } 516 }
495 #endregion BinaryStats 517 #endregion BinaryStats
496 518
497 // FIXME: Can't add info here because don't know scene yet. 519 Throttle = new TokenBucket(null, sceneThrottleBps, sceneThrottleBps * 10e-3f);
498// m_throttle
499// = new TokenBucket(
500// string.Format("server throttle bucket for {0}", Scene.Name), null, sceneThrottleBps);
501
502 Throttle = new TokenBucket("server throttle bucket", null, 0, sceneThrottleBps);
503
504 ThrottleRates = new ThrottleRates(configSource); 520 ThrottleRates = new ThrottleRates(configSource);
505 521
522 Random rnd = new Random(Util.EnvironmentTickCount());
523 m_animationSequenceNumber = rnd.Next(11474826);
524
506 if (usePools) 525 if (usePools)
507 EnablePools(); 526 EnablePools();
508 } 527 }
@@ -798,8 +817,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
798 if (UsePools) 817 if (UsePools)
799 EnablePoolStats(); 818 EnablePoolStats();
800 819
820
801 LLUDPServerCommands commands = new LLUDPServerCommands(MainConsole.Instance, this); 821 LLUDPServerCommands commands = new LLUDPServerCommands(MainConsole.Instance, this);
802 commands.Register(); 822 commands.Register();
823
803 } 824 }
804 825
805 public bool HandlesRegion(Location x) 826 public bool HandlesRegion(Location x)
@@ -907,8 +928,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
907 928
908 PacketPool.Instance.ReturnPacket(packet); 929 PacketPool.Instance.ReturnPacket(packet);
909 930
910 if (packetQueued) 931 /// WRONG use. May be usefull in future revision
911 m_dataPresentEvent.Set(); 932// if (packetQueued)
933// m_dataPresentEvent.Set();
912 } 934 }
913 935
914 /// <summary> 936 /// <summary>
@@ -969,8 +991,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
969 bufferSize = dataLength; 991 bufferSize = dataLength;
970 buffer = new UDPPacketBuffer(udpClient.RemoteEndPoint, bufferSize); 992 buffer = new UDPPacketBuffer(udpClient.RemoteEndPoint, bufferSize);
971 993
972 // m_log.Error("[LLUDPSERVER]: Packet exceeded buffer size! This could be an indication of packet assembly not obeying the MTU. Type=" + 994 m_log.Error("[LLUDPSERVER]: Packet exceeded buffer size! This could be an indication of packet assembly not obeying the MTU. Type=" +
973 // type + ", DataLength=" + dataLength + ", BufferLength=" + buffer.Data.Length + ". Dropping packet"); 995 type + ", DataLength=" + dataLength + ", BufferLength=" + buffer.Data.Length);
974 Buffer.BlockCopy(data, 0, buffer.Data, 0, dataLength); 996 Buffer.BlockCopy(data, 0, buffer.Data, 0, dataLength);
975 } 997 }
976 } 998 }
@@ -979,6 +1001,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
979 1001
980 #region Queue or Send 1002 #region Queue or Send
981 1003
1004 bool highPriority = false;
1005
1006 if (category != ThrottleOutPacketType.Unknown && (category & ThrottleOutPacketType.HighPriority) != 0)
1007 {
1008 category = (ThrottleOutPacketType)((int)category & 127);
1009 highPriority = true;
1010 }
1011
982 OutgoingPacket outgoingPacket = new OutgoingPacket(udpClient, buffer, category, null); 1012 OutgoingPacket outgoingPacket = new OutgoingPacket(udpClient, buffer, category, null);
983 1013
984 // If we were not provided a method for handling unacked, use the UDPServer default method 1014 // If we were not provided a method for handling unacked, use the UDPServer default method
@@ -988,26 +1018,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
988 // If a Linden Lab 1.23.5 client receives an update packet after a kill packet for an object, it will 1018 // If a Linden Lab 1.23.5 client receives an update packet after a kill packet for an object, it will
989 // continue to display the deleted object until relog. Therefore, we need to always queue a kill object 1019 // continue to display the deleted object until relog. Therefore, we need to always queue a kill object
990 // packet so that it isn't sent before a queued update packet. 1020 // packet so that it isn't sent before a queued update packet.
991 bool forceQueue = (type == PacketType.KillObject);
992 1021
993// if (type == PacketType.ImprovedTerseObjectUpdate) 1022 bool requestQueue = type == PacketType.KillObject;
994// { 1023 if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket, requestQueue, highPriority))
995// m_log.DebugFormat("Direct send ITOU to {0} in {1}", udpClient.AgentID, Scene.Name);
996// SendPacketFinal(outgoingPacket);
997// return false;
998// }
999// else
1000// {
1001 if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket, forceQueue))
1002 { 1024 {
1003 SendPacketFinal(outgoingPacket); 1025 SendPacketFinal(outgoingPacket);
1004 return true; 1026 return true;
1005 } 1027 }
1006 else 1028
1007 { 1029 return false;
1008 return false;
1009 }
1010// }
1011 1030
1012 #endregion Queue or Send 1031 #endregion Queue or Send
1013 } 1032 }
@@ -1048,6 +1067,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1048 pc.PingID.OldestUnacked = 0; 1067 pc.PingID.OldestUnacked = 0;
1049 1068
1050 SendPacket(udpClient, pc, ThrottleOutPacketType.Unknown, false, null); 1069 SendPacket(udpClient, pc, ThrottleOutPacketType.Unknown, false, null);
1070 udpClient.m_lastStartpingTimeMS = Util.EnvironmentTickCount();
1051 } 1071 }
1052 1072
1053 public void CompletePing(LLUDPClient udpClient, byte pingID) 1073 public void CompletePing(LLUDPClient udpClient, byte pingID)
@@ -1145,7 +1165,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1145 int dataLength = buffer.DataLength; 1165 int dataLength = buffer.DataLength;
1146 1166
1147 // NOTE: I'm seeing problems with some viewers when ACKs are appended to zerocoded packets so I've disabled that here 1167 // NOTE: I'm seeing problems with some viewers when ACKs are appended to zerocoded packets so I've disabled that here
1148 if (!isZerocoded) 1168 if (!isZerocoded && !isResend && outgoingPacket.UnackedMethod == null)
1149 { 1169 {
1150 // Keep appending ACKs until there is no room left in the buffer or there are 1170 // Keep appending ACKs until there is no room left in the buffer or there are
1151 // no more ACKs to append 1171 // no more ACKs to append
@@ -1180,7 +1200,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1180 Utils.UIntToBytesBig(sequenceNumber, buffer.Data, 1); 1200 Utils.UIntToBytesBig(sequenceNumber, buffer.Data, 1);
1181 outgoingPacket.SequenceNumber = sequenceNumber; 1201 outgoingPacket.SequenceNumber = sequenceNumber;
1182 1202
1183 if (udpClient.ProcessUnackedSends && isReliable) 1203 if (isReliable)
1184 { 1204 {
1185 // Add this packet to the list of ACK responses we are waiting on from the server 1205 // Add this packet to the list of ACK responses we are waiting on from the server
1186 udpClient.NeedAcks.Add(outgoingPacket); 1206 udpClient.NeedAcks.Add(outgoingPacket);
@@ -1311,35 +1331,62 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1311 1331
1312 #region Packet to Client Mapping 1332 #region Packet to Client Mapping
1313 1333
1314 // UseCircuitCode handling 1334 // If there is already a client for this endpoint, don't process UseCircuitCode
1315 if (packet.Type == PacketType.UseCircuitCode) 1335 IClientAPI client = null;
1336 if (!Scene.TryGetClient(endPoint, out client) || !(client is LLClientView))
1316 { 1337 {
1317 // We need to copy the endpoint so that it doesn't get changed when another thread reuses the 1338 // UseCircuitCode handling
1318 // buffer. 1339 if (packet.Type == PacketType.UseCircuitCode)
1319 object[] array = new object[] { new IPEndPoint(endPoint.Address, endPoint.Port), packet }; 1340 {
1341 // And if there is a UseCircuitCode pending, also drop it
1342 lock (m_pendingCache)
1343 {
1344 if (m_pendingCache.Contains(endPoint))
1345 return;
1320 1346
1321 Util.FireAndForget(HandleUseCircuitCode, array, "LLUDPServer.HandleUseCircuitCode"); 1347 m_pendingCache.AddOrUpdate(endPoint, new Queue<UDPPacketBuffer>(), 60);
1348 }
1322 1349
1323 return; 1350 // We need to copy the endpoint so that it doesn't get changed when another thread reuses the
1351 // buffer.
1352 object[] array = new object[] { new IPEndPoint(endPoint.Address, endPoint.Port), packet };
1353
1354 Util.FireAndForget(HandleUseCircuitCode, array);
1355
1356 return;
1357 }
1324 } 1358 }
1325 else if (packet.Type == PacketType.CompleteAgentMovement) 1359
1360 // If this is a pending connection, enqueue, don't process yet
1361 lock (m_pendingCache)
1326 { 1362 {
1327 // Send ack straight away to let the viewer know that we got it. 1363 Queue<UDPPacketBuffer> queue;
1328 SendAckImmediate(endPoint, packet.Header.Sequence); 1364 if (m_pendingCache.TryGetValue(endPoint, out queue))
1365 {
1366 //m_log.DebugFormat("[LLUDPSERVER]: Enqueued a {0} packet into the pending queue", packet.Type);
1367 queue.Enqueue(buffer);
1368 return;
1369 }
1329 1370
1330 // We need to copy the endpoint so that it doesn't get changed when another thread reuses the 1371/*
1331 // buffer. 1372 else if (packet.Type == PacketType.CompleteAgentMovement)
1332 object[] array = new object[] { new IPEndPoint(endPoint.Address, endPoint.Port), packet }; 1373 {
1374 // Send ack straight away to let the viewer know that we got it.
1375 SendAckImmediate(endPoint, packet.Header.Sequence);
1333 1376
1334 Util.FireAndForget( 1377 // We need to copy the endpoint so that it doesn't get changed when another thread reuses the
1335 HandleCompleteMovementIntoRegion, array, "LLUDPServer.HandleCompleteMovementIntoRegion"); 1378 // buffer.
1379 object[] array = new object[] { new IPEndPoint(endPoint.Address, endPoint.Port), packet };
1336 1380
1337 return; 1381 Util.FireAndForget(HandleCompleteMovementIntoRegion, array);
1382
1383 return;
1384 }
1385 */
1338 } 1386 }
1339 1387
1340 // Determine which agent this packet came from 1388 // Determine which agent this packet came from
1341 IClientAPI client; 1389 if (client == null || !(client is LLClientView))
1342 if (!Scene.TryGetClient(endPoint, out client) || !(client is LLClientView))
1343 { 1390 {
1344 //m_log.Debug("[LLUDPSERVER]: Received a " + packet.Type + " packet from an unrecognized source: " + address + " in " + m_scene.RegionInfo.RegionName); 1391 //m_log.Debug("[LLUDPSERVER]: Received a " + packet.Type + " packet from an unrecognized source: " + address + " in " + m_scene.RegionInfo.RegionName);
1345 1392
@@ -1356,7 +1403,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1356 udpClient = ((LLClientView)client).UDPClient; 1403 udpClient = ((LLClientView)client).UDPClient;
1357 1404
1358 if (!udpClient.IsConnected) 1405 if (!udpClient.IsConnected)
1406 {
1407 m_log.Debug("[LLUDPSERVER]: Received a " + packet.Type + " packet for a unConnected client in " + Scene.RegionInfo.RegionName);
1359 return; 1408 return;
1409 }
1360 1410
1361 #endregion Packet to Client Mapping 1411 #endregion Packet to Client Mapping
1362 1412
@@ -1368,37 +1418,30 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1368 1418
1369 #region ACK Receiving 1419 #region ACK Receiving
1370 1420
1371 if (udpClient.ProcessUnackedSends) 1421 // Handle appended ACKs
1422 if (packet.Header.AppendedAcks && packet.Header.AckList != null)
1372 { 1423 {
1373 // Handle appended ACKs 1424 // m_log.DebugFormat(
1374 if (packet.Header.AppendedAcks && packet.Header.AckList != null) 1425 // "[LLUDPSERVER]: Handling {0} appended acks from {1} in {2}",
1375 { 1426 // packet.Header.AckList.Length, client.Name, m_scene.Name);
1376 // m_log.DebugFormat(
1377 // "[LLUDPSERVER]: Handling {0} appended acks from {1} in {2}",
1378 // packet.Header.AckList.Length, client.Name, m_scene.Name);
1379 1427
1380 for (int i = 0; i < packet.Header.AckList.Length; i++) 1428 for (int i = 0; i < packet.Header.AckList.Length; i++)
1381 udpClient.NeedAcks.Acknowledge(packet.Header.AckList[i], now, packet.Header.Resent); 1429 udpClient.NeedAcks.Acknowledge(packet.Header.AckList[i], now, packet.Header.Resent);
1382 } 1430 }
1383 1431
1384 // Handle PacketAck packets 1432 // Handle PacketAck packets
1385 if (packet.Type == PacketType.PacketAck) 1433 if (packet.Type == PacketType.PacketAck)
1386 { 1434 {
1387 PacketAckPacket ackPacket = (PacketAckPacket)packet; 1435 PacketAckPacket ackPacket = (PacketAckPacket)packet;
1388 1436
1389 // m_log.DebugFormat( 1437 // m_log.DebugFormat(
1390 // "[LLUDPSERVER]: Handling {0} packet acks for {1} in {2}", 1438 // "[LLUDPSERVER]: Handling {0} packet acks for {1} in {2}",
1391 // ackPacket.Packets.Length, client.Name, m_scene.Name); 1439 // ackPacket.Packets.Length, client.Name, m_scene.Name);
1392 1440
1393 for (int i = 0; i < ackPacket.Packets.Length; i++) 1441 for (int i = 0; i < ackPacket.Packets.Length; i++)
1394 udpClient.NeedAcks.Acknowledge(ackPacket.Packets[i].ID, now, packet.Header.Resent); 1442 udpClient.NeedAcks.Acknowledge(ackPacket.Packets[i].ID, now, packet.Header.Resent);
1395 1443
1396 // We don't need to do anything else with PacketAck packets 1444 // We don't need to do anything else with PacketAck packets
1397 return;
1398 }
1399 }
1400 else if (packet.Type == PacketType.PacketAck)
1401 {
1402 return; 1445 return;
1403 } 1446 }
1404 1447
@@ -1459,24 +1502,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1459 LogPacketHeader(true, udpClient.CircuitCode, 0, packet.Type, (ushort)packet.Length); 1502 LogPacketHeader(true, udpClient.CircuitCode, 0, packet.Type, (ushort)packet.Length);
1460 #endregion BinaryStats 1503 #endregion BinaryStats
1461 1504
1462 if (packet.Type == PacketType.AgentUpdate)
1463 {
1464 if (DiscardInboundAgentUpdates)
1465 return;
1466 1505
1467 ((LLClientView)client).TotalAgentUpdates++; 1506//AgentUpdate removed from here
1468 1507
1469 AgentUpdatePacket agentUpdate = (AgentUpdatePacket)packet;
1470
1471 LLClientView llClient = client as LLClientView;
1472 if (agentUpdate.AgentData.SessionID != client.SessionId
1473 || agentUpdate.AgentData.AgentID != client.AgentId
1474 || !(llClient == null || llClient.CheckAgentUpdateSignificance(agentUpdate.AgentData)) )
1475 {
1476 PacketPool.Instance.ReturnPacket(packet);
1477 return;
1478 }
1479 }
1480 1508
1481 #region Ping Check Handling 1509 #region Ping Check Handling
1482 1510
@@ -1487,7 +1515,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1487 // We don't need to do anything else with ping checks 1515 // We don't need to do anything else with ping checks
1488 StartPingCheckPacket startPing = (StartPingCheckPacket)packet; 1516 StartPingCheckPacket startPing = (StartPingCheckPacket)packet;
1489 CompletePing(udpClient, startPing.PingID.PingID); 1517 CompletePing(udpClient, startPing.PingID.PingID);
1490 1518
1491 if ((Environment.TickCount - m_elapsedMSSinceLastStatReport) >= 3000) 1519 if ((Environment.TickCount - m_elapsedMSSinceLastStatReport) >= 3000)
1492 { 1520 {
1493 udpClient.SendPacketStats(); 1521 udpClient.SendPacketStats();
@@ -1497,7 +1525,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1497 } 1525 }
1498 else if (packet.Type == PacketType.CompletePingCheck) 1526 else if (packet.Type == PacketType.CompletePingCheck)
1499 { 1527 {
1500 // We don't currently track client ping times 1528 int t = Util.EnvironmentTickCountSubtract(udpClient.m_lastStartpingTimeMS);
1529 int c = udpClient.m_pingMS;
1530 c = 800 * c + 200 * t;
1531 c /= 1000;
1532 udpClient.m_pingMS = c;
1501 return; 1533 return;
1502 } 1534 }
1503 1535
@@ -1517,7 +1549,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1517 incomingPacket = new IncomingPacket((LLClientView)client, packet); 1549 incomingPacket = new IncomingPacket((LLClientView)client, packet);
1518 } 1550 }
1519 1551
1520 packetInbox.Enqueue(incomingPacket); 1552// if (incomingPacket.Packet.Type == PacketType.AgentUpdate ||
1553// incomingPacket.Packet.Type == PacketType.ChatFromViewer)
1554 if (incomingPacket.Packet.Type == PacketType.ChatFromViewer)
1555 packetInbox.EnqueueHigh(incomingPacket);
1556 else
1557 packetInbox.EnqueueLow(incomingPacket);
1558
1521 } 1559 }
1522 1560
1523 #region BinaryStats 1561 #region BinaryStats
@@ -1634,7 +1672,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1634 1672
1635 try 1673 try
1636 { 1674 {
1637 // DateTime startTime = DateTime.Now; 1675// DateTime startTime = DateTime.Now;
1638 object[] array = (object[])o; 1676 object[] array = (object[])o;
1639 endPoint = (IPEndPoint)array[0]; 1677 endPoint = (IPEndPoint)array[0];
1640 UseCircuitCodePacket uccp = (UseCircuitCodePacket)array[1]; 1678 UseCircuitCodePacket uccp = (UseCircuitCodePacket)array[1];
@@ -1646,6 +1684,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1646 AuthenticateResponse sessionInfo; 1684 AuthenticateResponse sessionInfo;
1647 if (IsClientAuthorized(uccp, out sessionInfo)) 1685 if (IsClientAuthorized(uccp, out sessionInfo))
1648 { 1686 {
1687 AgentCircuitData aCircuit = Scene.AuthenticateHandler.GetAgentCircuitData(uccp.CircuitCode.Code);
1688
1649 // Begin the process of adding the client to the simulator 1689 // Begin the process of adding the client to the simulator
1650 client 1690 client
1651 = AddClient( 1691 = AddClient(
@@ -1654,20 +1694,55 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1654 uccp.CircuitCode.SessionID, 1694 uccp.CircuitCode.SessionID,
1655 endPoint, 1695 endPoint,
1656 sessionInfo); 1696 sessionInfo);
1657 1697
1698 // This will be true if the client is new, e.g. not
1699 // an existing child agent, and there is no circuit data
1700 if (client != null && aCircuit == null)
1701 {
1702 Scene.CloseAgent(client.AgentId, true);
1703 return;
1704 }
1705
1706 // Now we know we can handle more data
1707 Thread.Sleep(200);
1708
1709 // Obtain the pending queue and remove it from the cache
1710 Queue<UDPPacketBuffer> queue = null;
1711
1712 lock (m_pendingCache)
1713 {
1714 if (!m_pendingCache.TryGetValue(endPoint, out queue))
1715 {
1716 m_log.DebugFormat("[LLUDPSERVER]: Client created but no pending queue present");
1717 return;
1718
1719 }
1720 m_pendingCache.Remove(endPoint);
1721 }
1722
1723 m_log.DebugFormat("[LLUDPSERVER]: Client created, processing pending queue, {0} entries", queue.Count);
1724
1725 // Reinject queued packets
1726 while (queue.Count > 0)
1727 {
1728 UDPPacketBuffer buf = queue.Dequeue();
1729 PacketReceived(buf);
1730 }
1731
1732 queue = null;
1733
1658 // Send ack straight away to let the viewer know that the connection is active. 1734 // Send ack straight away to let the viewer know that the connection is active.
1659 // The client will be null if it already exists (e.g. if on a region crossing the client sends a use 1735 // The client will be null if it already exists (e.g. if on a region crossing the client sends a use
1660 // circuit code to the existing child agent. This is not particularly obvious. 1736 // circuit code to the existing child agent. This is not particularly obvious.
1661 SendAckImmediate(endPoint, uccp.Header.Sequence); 1737 SendAckImmediate(endPoint, uccp.Header.Sequence);
1662 1738
1663 // We only want to send initial data to new clients, not ones which are being converted from child to root. 1739 // We only want to send initial data to new clients, not ones which are being converted from child to root.
1664 if (client != null) 1740 if (client != null)
1665 { 1741 {
1666 AgentCircuitData aCircuit = Scene.AuthenticateHandler.GetAgentCircuitData(uccp.CircuitCode.Code);
1667 bool tp = (aCircuit.teleportFlags > 0); 1742 bool tp = (aCircuit.teleportFlags > 0);
1668 // Let's delay this for TP agents, otherwise the viewer doesn't know where to get resources from 1743 // Let's delay this for TP agents, otherwise the viewer doesn't know where to get resources from
1669 if (!tp && !client.SceneAgent.SentInitialDataToClient) 1744 if (!tp)
1670 client.SceneAgent.SendInitialDataToClient(); 1745 client.SceneAgent.SendInitialDataToMe();
1671 } 1746 }
1672 } 1747 }
1673 else 1748 else
@@ -1675,9 +1750,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1675 // Don't create clients for unauthorized requesters. 1750 // Don't create clients for unauthorized requesters.
1676 m_log.WarnFormat( 1751 m_log.WarnFormat(
1677 "[LLUDPSERVER]: Ignoring connection request for {0} to {1} with unknown circuit code {2} from IP {3}", 1752 "[LLUDPSERVER]: Ignoring connection request for {0} to {1} with unknown circuit code {2} from IP {3}",
1753
1678 uccp.CircuitCode.ID, Scene.RegionInfo.RegionName, uccp.CircuitCode.Code, endPoint); 1754 uccp.CircuitCode.ID, Scene.RegionInfo.RegionName, uccp.CircuitCode.Code, endPoint);
1679 } 1755
1680 1756 lock (m_pendingCache)
1757 m_pendingCache.Remove(endPoint);
1758 }
1759
1681 // m_log.DebugFormat( 1760 // m_log.DebugFormat(
1682 // "[LLUDPSERVER]: Handling UseCircuitCode request from {0} took {1}ms", 1761 // "[LLUDPSERVER]: Handling UseCircuitCode request from {0} took {1}ms",
1683 // buffer.RemoteEndPoint, (DateTime.Now - startTime).Milliseconds); 1762 // buffer.RemoteEndPoint, (DateTime.Now - startTime).Milliseconds);
@@ -1694,8 +1773,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1694 e.StackTrace); 1773 e.StackTrace);
1695 } 1774 }
1696 } 1775 }
1697 1776/*
1698 private void HandleCompleteMovementIntoRegion(object o) 1777 private void HandleCompleteMovementIntoRegion(object o)
1699 { 1778 {
1700 IPEndPoint endPoint = null; 1779 IPEndPoint endPoint = null;
1701 IClientAPI client = null; 1780 IClientAPI client = null;
@@ -1804,6 +1883,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1804 e.StackTrace); 1883 e.StackTrace);
1805 } 1884 }
1806 } 1885 }
1886*/
1807 1887
1808 /// <summary> 1888 /// <summary>
1809 /// Send an ack immediately to the given endpoint. 1889 /// Send an ack immediately to the given endpoint.
@@ -1861,6 +1941,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1861 uint circuitCode, UUID agentID, UUID sessionID, IPEndPoint remoteEndPoint, AuthenticateResponse sessionInfo) 1941 uint circuitCode, UUID agentID, UUID sessionID, IPEndPoint remoteEndPoint, AuthenticateResponse sessionInfo)
1862 { 1942 {
1863 IClientAPI client = null; 1943 IClientAPI client = null;
1944 bool createNew = false;
1864 1945
1865 // We currently synchronize this code across the whole scene to avoid issues such as 1946 // We currently synchronize this code across the whole scene to avoid issues such as
1866 // http://opensimulator.org/mantis/view.php?id=5365 However, once locking per agent circuit can be done 1947 // http://opensimulator.org/mantis/view.php?id=5365 However, once locking per agent circuit can be done
@@ -1869,7 +1950,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1869 { 1950 {
1870 if (!Scene.TryGetClient(agentID, out client)) 1951 if (!Scene.TryGetClient(agentID, out client))
1871 { 1952 {
1953 createNew = true;
1954 }
1955 else
1956 {
1957 if (client.SceneAgent == null)
1958 {
1959 Scene.CloseAgent(agentID, true);
1960 createNew = true;
1961 }
1962 }
1963
1964 if (createNew)
1965 {
1872 LLUDPClient udpClient = new LLUDPClient(this, ThrottleRates, Throttle, circuitCode, agentID, remoteEndPoint, m_defaultRTO, m_maxRTO); 1966 LLUDPClient udpClient = new LLUDPClient(this, ThrottleRates, Throttle, circuitCode, agentID, remoteEndPoint, m_defaultRTO, m_maxRTO);
1967
1873 1968
1874 client = new LLClientView(Scene, this, udpClient, sessionInfo, agentID, sessionID, circuitCode); 1969 client = new LLClientView(Scene, this, udpClient, sessionInfo, agentID, sessionID, circuitCode);
1875 client.OnLogout += LogoutHandler; 1970 client.OnLogout += LogoutHandler;
@@ -1899,15 +1994,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1899 { 1994 {
1900 ClientLogoutsDueToNoReceives++; 1995 ClientLogoutsDueToNoReceives++;
1901 1996
1902 m_log.WarnFormat( 1997 if (client.SceneAgent != null)
1903 "[LLUDPSERVER]: No packets received from {0} agent of {1} for {2}ms in {3}. Disconnecting.", 1998 {
1904 client.SceneAgent.IsChildAgent ? "child" : "root", client.Name, timeoutTicks, Scene.Name); 1999 m_log.WarnFormat(
2000 "[LLUDPSERVER]: No packets received from {0} agent of {1} for {2}ms in {3}. Disconnecting.",
2001 client.SceneAgent.IsChildAgent ? "child" : "root", client.Name, timeoutTicks, Scene.Name);
1905 2002
1906 if (!client.SceneAgent.IsChildAgent) 2003 if (!client.SceneAgent.IsChildAgent)
1907 client.Kick("Simulator logged you out due to connection timeout."); 2004 client.Kick("Simulator logged you out due to connection timeout.");
2005 }
1908 } 2006 }
1909 2007
1910 Scene.CloseAgent(client.AgentId, true); 2008 if (!Scene.CloseAgent(client.AgentId, true))
2009 client.Close(true,true);
1911 } 2010 }
1912 2011
1913 private void IncomingPacketHandler() 2012 private void IncomingPacketHandler()
@@ -1920,6 +2019,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1920 2019
1921 while (IsRunningInbound) 2020 while (IsRunningInbound)
1922 { 2021 {
2022 Scene.ThreadAlive(1);
1923 try 2023 try
1924 { 2024 {
1925 IncomingPacket incomingPacket = null; 2025 IncomingPacket incomingPacket = null;
@@ -1942,7 +2042,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1942 m_incomingPacketPool.ReturnObject(incomingPacket); 2042 m_incomingPacketPool.ReturnObject(incomingPacket);
1943 } 2043 }
1944 } 2044 }
1945 catch (Exception ex) 2045 catch(Exception ex)
1946 { 2046 {
1947 m_log.Error("[LLUDPSERVER]: Error in the incoming packet handler loop: " + ex.Message, ex); 2047 m_log.Error("[LLUDPSERVER]: Error in the incoming packet handler loop: " + ex.Message, ex);
1948 } 2048 }
@@ -1971,6 +2071,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1971 2071
1972 while (base.IsRunningOutbound) 2072 while (base.IsRunningOutbound)
1973 { 2073 {
2074 Scene.ThreadAlive(2);
1974 try 2075 try
1975 { 2076 {
1976 m_packetSent = false; 2077 m_packetSent = false;
@@ -2029,13 +2130,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2029 2130
2030 // If nothing was sent, sleep for the minimum amount of time before a 2131 // If nothing was sent, sleep for the minimum amount of time before a
2031 // token bucket could get more tokens 2132 // token bucket could get more tokens
2032 //if (!m_packetSent) 2133
2033 // Thread.Sleep((int)TickCountResolution);
2034 //
2035 // Instead, now wait for data present to be explicitly signalled. Evidence so far is that with
2036 // modern mono it reduces CPU base load since there is no more continuous polling.
2037 if (!m_packetSent) 2134 if (!m_packetSent)
2038 m_dataPresentEvent.WaitOne(100); 2135 Thread.Sleep((int)TickCountResolution);
2136
2137 // .... wrong core code removed
2138
2039 2139
2040 Watchdog.UpdateThread(); 2140 Watchdog.UpdateThread();
2041 } 2141 }
@@ -2061,7 +2161,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2061 2161
2062 if (udpClient.IsConnected) 2162 if (udpClient.IsConnected)
2063 { 2163 {
2064 if (udpClient.ProcessUnackedSends && m_resendUnacked) 2164 if (m_resendUnacked)
2065 HandleUnacked(llClient); 2165 HandleUnacked(llClient);
2066 2166
2067 if (m_sendAcks) 2167 if (m_sendAcks)
@@ -2206,8 +2306,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2206 Packet packet = incomingPacket.Packet; 2306 Packet packet = incomingPacket.Packet;
2207 LLClientView client = incomingPacket.Client; 2307 LLClientView client = incomingPacket.Client;
2208 2308
2209 if (client.IsActive) 2309// if (client.IsActive)
2210 { 2310// {
2211 m_currentIncomingClient = client; 2311 m_currentIncomingClient = client;
2212 2312
2213 try 2313 try
@@ -2234,13 +2334,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2234 { 2334 {
2235 m_currentIncomingClient = null; 2335 m_currentIncomingClient = null;
2236 } 2336 }
2237 } 2337// }
2238 else 2338// else
2239 { 2339// {
2240 m_log.DebugFormat( 2340// m_log.DebugFormat(
2241 "[LLUDPSERVER]: Dropped incoming {0} for dead client {1} in {2}", 2341// "[LLUDPSERVER]: Dropped incoming {0} for dead client {1} in {2}",
2242 packet.Type, client.Name, Scene.RegionInfo.RegionName); 2342// packet.Type, client.Name, m_scene.RegionInfo.RegionName);
2243 } 2343// }
2244 2344
2245 IncomingPacketsProcessed++; 2345 IncomingPacketsProcessed++;
2246 } 2346 }
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServerCommands.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServerCommands.cs
index ac6c0b4..6e6a2d1 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServerCommands.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServerCommands.cs
@@ -48,6 +48,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
48 48
49 public void Register() 49 public void Register()
50 { 50 {
51/*
51 m_console.Commands.AddCommand( 52 m_console.Commands.AddCommand(
52 "Comms", false, "show server throttles", 53 "Comms", false, "show server throttles",
53 "show server throttles", 54 "show server throttles",
@@ -213,6 +214,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
213 "Set a debug parameter for a particular client. If no name is given then the value is set on all clients.", 214 "Set a debug parameter for a particular client. If no name is given then the value is set on all clients.",
214 "process-unacked-sends - Do we take action if a sent reliable packet has not been acked.", 215 "process-unacked-sends - Do we take action if a sent reliable packet has not been acked.",
215 HandleClientSetCommand); 216 HandleClientSetCommand);
217*/
216 } 218 }
217 219
218 private void HandleShowServerThrottlesCommand(string module, string[] args) 220 private void HandleShowServerThrottlesCommand(string module, string[] args)
@@ -224,7 +226,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
224 ConsoleDisplayList cdl = new ConsoleDisplayList(); 226 ConsoleDisplayList cdl = new ConsoleDisplayList();
225 cdl.AddRow("Adaptive throttles", m_udpServer.ThrottleRates.AdaptiveThrottlesEnabled); 227 cdl.AddRow("Adaptive throttles", m_udpServer.ThrottleRates.AdaptiveThrottlesEnabled);
226 228
227 long maxSceneDripRate = m_udpServer.Throttle.MaxDripRate; 229 long maxSceneDripRate = (long)m_udpServer.Throttle.MaxDripRate;
228 cdl.AddRow( 230 cdl.AddRow(
229 "Max scene throttle", 231 "Max scene throttle",
230 maxSceneDripRate != 0 ? string.Format("{0} kbps", maxSceneDripRate * 8 / 1000) : "unset"); 232 maxSceneDripRate != 0 ? string.Format("{0} kbps", maxSceneDripRate * 8 / 1000) : "unset");
@@ -505,7 +507,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
505 m_console.OutputFormat("Debug settings for {0}", m_udpServer.Scene.Name); 507 m_console.OutputFormat("Debug settings for {0}", m_udpServer.Scene.Name);
506 ConsoleDisplayList cdl = new ConsoleDisplayList(); 508 ConsoleDisplayList cdl = new ConsoleDisplayList();
507 509
508 long maxSceneDripRate = m_udpServer.Throttle.MaxDripRate; 510 long maxSceneDripRate = (long)m_udpServer.Throttle.MaxDripRate;
509 cdl.AddRow( 511 cdl.AddRow(
510 "max-scene-throttle", 512 "max-scene-throttle",
511 maxSceneDripRate != 0 ? string.Format("{0} kbps", maxSceneDripRate * 8 / 1000) : "unset"); 513 maxSceneDripRate != 0 ? string.Format("{0} kbps", maxSceneDripRate * 8 / 1000) : "unset");
@@ -556,6 +558,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
556 m_console.OutputFormat("{0} set to {1} in {2}", param, rawValue, m_udpServer.Scene.Name); 558 m_console.OutputFormat("{0} set to {1} in {2}", param, rawValue, m_udpServer.Scene.Name);
557 } 559 }
558 560
561/* not in use, nothing to set/get from lludp
559 private void HandleClientGetCommand(string module, string[] args) 562 private void HandleClientGetCommand(string module, string[] args)
560 { 563 {
561 if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_udpServer.Scene) 564 if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_udpServer.Scene)
@@ -582,11 +585,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
582 m_console.OutputFormat( 585 m_console.OutputFormat(
583 "Client debug parameters for {0} ({1}) in {2}", 586 "Client debug parameters for {0} ({1}) in {2}",
584 sp.Name, sp.IsChildAgent ? "child" : "root", m_udpServer.Scene.Name); 587 sp.Name, sp.IsChildAgent ? "child" : "root", m_udpServer.Scene.Name);
585
586 ConsoleDisplayList cdl = new ConsoleDisplayList();
587 cdl.AddRow("process-unacked-sends", udpClient.ProcessUnackedSends);
588
589 m_console.Output(cdl.ToString());
590 } 588 }
591 }); 589 });
592 } 590 }
@@ -609,28 +607,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
609 607
610 if (args.Length == 8) 608 if (args.Length == 8)
611 name = string.Format("{0} {1}", args[6], args[7]); 609 name = string.Format("{0} {1}", args[6], args[7]);
612 610 // nothing here now
613 if (param == "process-unacked-sends")
614 {
615 bool newValue;
616
617 if (!ConsoleUtil.TryParseConsoleBool(MainConsole.Instance, rawValue, out newValue))
618 return;
619
620 m_udpServer.Scene.ForEachScenePresence(
621 sp =>
622 {
623 if ((name == null || sp.Name == name) && sp.ControllingClient is LLClientView)
624 {
625 LLUDPClient udpClient = ((LLClientView)sp.ControllingClient).UDPClient;
626 udpClient.ProcessUnackedSends = newValue;
627
628 m_console.OutputFormat("{0} set to {1} for {2} in {3}", param, newValue, sp.Name, m_udpServer.Scene.Name);
629 }
630 });
631 }
632 } 611 }
633 612*/
634 private void HandlePacketCommand(string module, string[] args) 613 private void HandlePacketCommand(string module, string[] args)
635 { 614 {
636 if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_udpServer.Scene) 615 if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_udpServer.Scene)
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs
index f62dc15..7171974 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs
@@ -206,16 +206,16 @@ namespace OpenMetaverse
206 const int SIO_UDP_CONNRESET = -1744830452; 206 const int SIO_UDP_CONNRESET = -1744830452;
207 207
208 IPEndPoint ipep = new IPEndPoint(m_localBindAddress, m_udpPort); 208 IPEndPoint ipep = new IPEndPoint(m_localBindAddress, m_udpPort);
209
210 m_log.DebugFormat(
211 "[UDPBASE]: Binding UDP listener using internal IP address config {0}:{1}",
212 ipep.Address, ipep.Port);
213 209
214 m_udpSocket = new Socket( 210 m_udpSocket = new Socket(
215 AddressFamily.InterNetwork, 211 AddressFamily.InterNetwork,
216 SocketType.Dgram, 212 SocketType.Dgram,
217 ProtocolType.Udp); 213 ProtocolType.Udp);
218 214
215 // OpenSim may need this but in AVN, this messes up automated
216 // sim restarts badly
217 //m_udpSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, false);
218
219 try 219 try
220 { 220 {
221 if (m_udpSocket.Ttl < 128) 221 if (m_udpSocket.Ttl < 128)
@@ -501,4 +501,4 @@ namespace OpenMetaverse
501 catch (ObjectDisposedException) { } 501 catch (ObjectDisposedException) { }
502 } 502 }
503 } 503 }
504} \ No newline at end of file 504}
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/Tests/ThrottleTests.cs b/OpenSim/Region/ClientStack/Linden/UDP/Tests/ThrottleTests.cs
index 3c82a78..5e41dbd 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/Tests/ThrottleTests.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/Tests/ThrottleTests.cs
@@ -35,6 +35,7 @@ using OpenSim.Tests.Common;
35 35
36namespace OpenSim.Region.ClientStack.LindenUDP.Tests 36namespace OpenSim.Region.ClientStack.LindenUDP.Tests
37{ 37{
38 /*
38 [TestFixture] 39 [TestFixture]
39 public class ThrottleTests : OpenSimTestCase 40 public class ThrottleTests : OpenSimTestCase
40 { 41 {
@@ -57,16 +58,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
57 [Test] 58 [Test]
58 public void TestSetRequestDripRate() 59 public void TestSetRequestDripRate()
59 { 60 {
61
60 TestHelpers.InMethod(); 62 TestHelpers.InMethod();
61 63
62 TokenBucket tb = new TokenBucket("tb", null, 5000, 0); 64 TokenBucket tb = new TokenBucket(null, 5000f,10000f);
63 AssertRates(tb, 5000, 0, 5000, 0); 65 AssertRates(tb, 5000, 0, 5000, 0);
64 66
65 tb.RequestedDripRate = 4000; 67 tb.RequestedDripRate = 4000f;
66 AssertRates(tb, 4000, 0, 4000, 0); 68 AssertRates(tb, 4000, 0, 4000, 0);
67 69
68 tb.RequestedDripRate = 6000; 70 tb.RequestedDripRate = 6000;
69 AssertRates(tb, 6000, 0, 6000, 0); 71 AssertRates(tb, 6000, 0, 6000, 0);
72
70 } 73 }
71 74
72 [Test] 75 [Test]
@@ -74,7 +77,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
74 { 77 {
75 TestHelpers.InMethod(); 78 TestHelpers.InMethod();
76 79
77 TokenBucket tb = new TokenBucket("tb", null, 5000, 10000); 80 TokenBucket tb = new TokenBucket(null, 5000,15000);
78 AssertRates(tb, 5000, 0, 5000, 10000); 81 AssertRates(tb, 5000, 0, 5000, 10000);
79 82
80 tb.RequestedDripRate = 4000; 83 tb.RequestedDripRate = 4000;
@@ -92,9 +95,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
92 { 95 {
93 TestHelpers.InMethod(); 96 TestHelpers.InMethod();
94 97
95 TokenBucket tbParent = new TokenBucket("tbParent", null, 0, 0); 98 TokenBucket tbParent = new TokenBucket("tbParent", null, 0);
96 TokenBucket tbChild1 = new TokenBucket("tbChild1", tbParent, 3000, 0); 99 TokenBucket tbChild1 = new TokenBucket("tbChild1", tbParent, 3000);
97 TokenBucket tbChild2 = new TokenBucket("tbChild2", tbParent, 5000, 0); 100 TokenBucket tbChild2 = new TokenBucket("tbChild2", tbParent, 5000);
98 101
99 AssertRates(tbParent, 8000, 8000, 8000, 0); 102 AssertRates(tbParent, 8000, 8000, 8000, 0);
100 AssertRates(tbChild1, 3000, 0, 3000, 0); 103 AssertRates(tbChild1, 3000, 0, 3000, 0);
@@ -113,6 +116,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
113 AssertRates(tbParent, 6000, 8000, 6000, 0); 116 AssertRates(tbParent, 6000, 8000, 6000, 0);
114 AssertRates(tbChild1, 3000, 0, 6000 / 8 * 3, 0); 117 AssertRates(tbChild1, 3000, 0, 6000 / 8 * 3, 0);
115 AssertRates(tbChild2, 5000, 0, 6000 / 8 * 5, 0); 118 AssertRates(tbChild2, 5000, 0, 6000 / 8 * 5, 0);
119
116 } 120 }
117 121
118 private void AssertRates( 122 private void AssertRates(
@@ -424,4 +428,5 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
424 udpClient.SetThrottles(throttles); 428 udpClient.SetThrottles(throttles);
425 } 429 }
426 } 430 }
431 */
427} \ No newline at end of file 432} \ No newline at end of file
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/ThrottleRates.cs b/OpenSim/Region/ClientStack/Linden/UDP/ThrottleRates.cs
index 7a2756b..076551f 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/ThrottleRates.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/ThrottleRates.cs
@@ -69,6 +69,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
69 /// <summary>Amount of the texture throttle to steal for the task throttle</summary> 69 /// <summary>Amount of the texture throttle to steal for the task throttle</summary>
70 public double CannibalizeTextureRate; 70 public double CannibalizeTextureRate;
71 71
72 public int ClientMaxRate;
73 public float BrustTime;
74
72 /// <summary> 75 /// <summary>
73 /// Default constructor 76 /// Default constructor
74 /// </summary> 77 /// </summary>
@@ -88,7 +91,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
88 Texture = throttleConfig.GetInt("texture_default", 18500); 91 Texture = throttleConfig.GetInt("texture_default", 18500);
89 Asset = throttleConfig.GetInt("asset_default", 10500); 92 Asset = throttleConfig.GetInt("asset_default", 10500);
90 93
91 Total = throttleConfig.GetInt("client_throttle_max_bps", 0); 94 Total = Resend + Land + Wind + Cloud + Task + Texture + Asset;
95 // 3000000 bps default max
96 ClientMaxRate = throttleConfig.GetInt("client_throttle_max_bps", 375000);
97 if (ClientMaxRate > 1000000)
98 ClientMaxRate = 1000000; // no more than 8Mbps
99
100 BrustTime = (float)throttleConfig.GetInt("client_throttle_burtsTimeMS", 10);
101 BrustTime *= 1e-3f;
92 102
93 AdaptiveThrottlesEnabled = throttleConfig.GetBoolean("enable_adaptive_throttles", false); 103 AdaptiveThrottlesEnabled = throttleConfig.GetBoolean("enable_adaptive_throttles", false);
94 MinimumAdaptiveThrottleRate = throttleConfig.GetInt("adaptive_throttle_min_bps", 32000); 104 MinimumAdaptiveThrottleRate = throttleConfig.GetInt("adaptive_throttle_min_bps", 32000);
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/TokenBucket.cs b/OpenSim/Region/ClientStack/Linden/UDP/TokenBucket.cs
index 4616203..0f71222 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/TokenBucket.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/TokenBucket.cs
@@ -43,25 +43,24 @@ namespace OpenSim.Region.ClientStack.LindenUDP
43 { 43 {
44 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 44 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
45 45
46 public string Identifier { get; private set; } 46 private static Int32 m_counter = 0;
47
48 public int DebugLevel { get; set; }
49 47
50 /// <summary> 48// private Int32 m_identifier;
51 /// Number of ticks (ms) per quantum, drip rate and max burst 49
52 /// are defined over this interval. 50 protected const float m_timeScale = 1e-3f;
53 /// </summary>
54 protected const Int32 m_ticksPerQuantum = 1000;
55 51
56 /// <summary> 52 /// <summary>
57 /// This is the number of quantums worth of packets that can 53 /// This is the number of m_minimumDripRate bytes
58 /// be accommodated during a burst 54 /// allowed in a burst
55 /// roughtly, with this settings, the maximum time system will take
56 /// to recheck a bucket in ms
57 ///
59 /// </summary> 58 /// </summary>
60 protected const Double m_quantumsPerBurst = 1.5; 59 protected const float m_quantumsPerBurst = 5;
61 60
62 /// <summary> 61 /// <summary>
63 /// </summary> 62 /// </summary>
64 protected const Int32 m_minimumDripRate = LLUDPServer.MTU; 63 protected const float m_minimumDripRate = 1500;
65 64
66 /// <summary>Time of the last drip, in system ticks</summary> 65 /// <summary>Time of the last drip, in system ticks</summary>
67 protected Int32 m_lastDrip; 66 protected Int32 m_lastDrip;
@@ -70,40 +69,57 @@ namespace OpenSim.Region.ClientStack.LindenUDP
70 /// The number of bytes that can be sent at this moment. This is the 69 /// The number of bytes that can be sent at this moment. This is the
71 /// current number of tokens in the bucket 70 /// current number of tokens in the bucket
72 /// </summary> 71 /// </summary>
73 protected Int64 m_tokenCount; 72 protected float m_tokenCount;
74 73
75 /// <summary> 74 /// <summary>
76 /// Map of children buckets and their requested maximum burst rate 75 /// Map of children buckets and their requested maximum burst rate
77 /// </summary> 76 /// </summary>
78 protected Dictionary<TokenBucket,Int64> m_children = new Dictionary<TokenBucket,Int64>(); 77
78 protected Dictionary<TokenBucket, float> m_children = new Dictionary<TokenBucket, float>();
79
80#region Properties
79 81
80 /// <summary> 82 /// <summary>
81 /// The parent bucket of this bucket, or null if this bucket has no 83 /// The parent bucket of this bucket, or null if this bucket has no
82 /// parent. The parent bucket will limit the aggregate bandwidth of all 84 /// parent. The parent bucket will limit the aggregate bandwidth of all
83 /// of its children buckets 85 /// of its children buckets
84 /// </summary> 86 /// </summary>
85 public TokenBucket Parent { get; protected set; } 87 protected TokenBucket m_parent;
86 88 public TokenBucket Parent
89 {
90 get { return m_parent; }
91 set { m_parent = value; }
92 }
87 /// <summary> 93 /// <summary>
88 /// Maximum burst rate in bytes per second. This is the maximum number 94 /// This is the maximum number
89 /// of tokens that can accumulate in the bucket at any one time. This 95 /// of tokens that can accumulate in the bucket at any one time. This
90 /// also sets the total request for leaf nodes 96 /// also sets the total request for leaf nodes
91 /// </summary> 97 /// </summary>
92 protected Int64 m_burstRate; 98 protected float m_burst;
93 public Int64 RequestedBurstRate 99//not in use
100 public float MaxDripRate { get; set; }
101
102 public float RequestedBurst
94 { 103 {
95 get { return m_burstRate; } 104 get { return m_burst; }
96 set { m_burstRate = (value < 0 ? 0 : value); } 105 set {
106 float rate = (value < 0 ? 0 : value);
107 if (rate < 1.5f * m_minimumDripRate)
108 rate = 1.5f * m_minimumDripRate;
109 else if (rate > m_minimumDripRate * m_quantumsPerBurst)
110 rate = m_minimumDripRate * m_quantumsPerBurst;
111
112 m_burst = rate;
113 }
97 } 114 }
98 115
99 public Int64 BurstRate 116 public float Burst
100 { 117 {
101 get { 118 get {
102 double rate = RequestedBurstRate * BurstRateModifier(); 119 float rate = RequestedBurst * BurstModifier();
103 if (rate < m_minimumDripRate * m_quantumsPerBurst) 120 if (rate < m_minimumDripRate)
104 rate = m_minimumDripRate * m_quantumsPerBurst; 121 rate = m_minimumDripRate;
105 122 return (float)rate;
106 return (Int64) rate;
107 } 123 }
108 } 124 }
109 125
@@ -115,78 +131,50 @@ namespace OpenSim.Region.ClientStack.LindenUDP
115 /// Can never be above MaxDripRate. 131 /// Can never be above MaxDripRate.
116 /// Tokens are added to the bucket at any time 132 /// Tokens are added to the bucket at any time
117 /// <seealso cref="RemoveTokens"/> is called, at the granularity of 133 /// <seealso cref="RemoveTokens"/> is called, at the granularity of
118 /// the system tick interval (typically around 15-22ms) 134 /// the system tick interval (typically around 15-22ms)</remarks>
119 /// FIXME: It is extremely confusing to be able to set a RequestedDripRate of 0 and then receive a positive 135 protected float m_dripRate;
120 /// number on get if TotalDripRequest is set. This also stops us being able to retrieve the fact that
121 /// RequestedDripRate is set to 0. Really, this should always return m_dripRate and then we can get
122 /// (m_dripRate == 0 ? TotalDripRequest : m_dripRate) on some other properties.
123 /// </remarks>
124 public virtual Int64 RequestedDripRate
125 {
126 get { return (m_dripRate == 0 ? TotalDripRequest : m_dripRate); }
127 set
128 {
129 if (value <= 0)
130 m_dripRate = 0;
131 else if (MaxDripRate > 0 && value > MaxDripRate)
132 m_dripRate = MaxDripRate;
133 else
134 m_dripRate = value;
135 136
136 m_burstRate = (Int64)((double)m_dripRate * m_quantumsPerBurst); 137 public virtual float RequestedDripRate
138 {
139 get { return (m_dripRate == 0 ? m_totalDripRequest : m_dripRate); }
140 set {
141 m_dripRate = (value < 0 ? 0 : value);
142 m_totalDripRequest = m_dripRate;
137 143
138 if (Parent != null) 144 if (m_parent != null)
139 Parent.RegisterRequest(this, m_dripRate); 145 m_parent.RegisterRequest(this,m_dripRate);
140 } 146 }
141 } 147 }
142 148
143 /// <summary> 149 public virtual float DripRate
144 /// Gets the drip rate.
145 /// </summary>
146 /// <value>
147 /// DripRate can never be above max drip rate or below min drip rate.
148 /// If we are a child bucket then the drip rate return is modifed by the total load on the capacity of the
149 /// parent bucket.
150 /// </value>
151 public virtual Int64 DripRate
152 { 150 {
153 get 151 get {
154 { 152 float rate = Math.Min(RequestedDripRate,TotalDripRequest);
155 double rate; 153 if (m_parent == null)
156 154 return rate;
157 // FIXME: This doesn't properly work if we have a parent and children and a requested drip rate set
158 // on ourselves which is not equal to the child drip rates.
159 if (Parent == null)
160 {
161 if (TotalDripRequest > 0)
162 rate = Math.Min(RequestedDripRate, TotalDripRequest);
163 else
164 rate = RequestedDripRate;
165 }
166 else
167 {
168 rate = (double)RequestedDripRate * Parent.DripRateModifier();
169 }
170 155
156 rate *= m_parent.DripRateModifier();
171 if (rate < m_minimumDripRate) 157 if (rate < m_minimumDripRate)
172 rate = m_minimumDripRate; 158 rate = m_minimumDripRate;
173 else if (MaxDripRate > 0 && rate > MaxDripRate)
174 rate = MaxDripRate;
175 159
176 return (Int64)rate; 160 return (float)rate;
177 } 161 }
178 } 162 }
179 protected Int64 m_dripRate;
180
181 // <summary>
182 // The maximum rate for flow control. Drip rate can never be greater than this.
183 // </summary>
184 public Int64 MaxDripRate { get; set; }
185 163
186 /// <summary> 164 /// <summary>
187 /// The current total of the requested maximum burst rates of children buckets. 165 /// The current total of the requested maximum burst rates of children buckets.
188 /// </summary> 166 /// </summary>
189 public Int64 TotalDripRequest { get; protected set; } 167 protected float m_totalDripRequest;
168 public float TotalDripRequest
169 {
170 get { return m_totalDripRequest; }
171 set { m_totalDripRequest = value; }
172 }
173
174#endregion Properties
175
176#region Constructor
177
190 178
191 /// <summary> 179 /// <summary>
192 /// Default constructor 180 /// Default constructor
@@ -194,20 +182,24 @@ namespace OpenSim.Region.ClientStack.LindenUDP
194 /// <param name="identifier">Identifier for this token bucket</param> 182 /// <param name="identifier">Identifier for this token bucket</param>
195 /// <param name="parent">Parent bucket if this is a child bucket, or 183 /// <param name="parent">Parent bucket if this is a child bucket, or
196 /// null if this is a root bucket</param> 184 /// null if this is a root bucket</param>
197 /// <param name="requestedDripRate"> 185 /// <param name="maxBurst">Maximum size of the bucket in bytes, or
198 /// Requested rate that the bucket fills, in bytes per 186 /// zero if this bucket has no maximum capacity</param>
199 /// second. If zero, the bucket always remains full. 187 /// <param name="dripRate">Rate that the bucket fills, in bytes per
200 /// </param> 188 /// second. If zero, the bucket always remains full</param>
201 public TokenBucket(string identifier, TokenBucket parent, Int64 requestedDripRate, Int64 maxDripRate) 189 public TokenBucket(TokenBucket parent, float dripRate, float MaxBurst)
202 { 190 {
203 Identifier = identifier; 191 m_counter++;
204 192
205 Parent = parent; 193 Parent = parent;
206 RequestedDripRate = requestedDripRate; 194 RequestedDripRate = dripRate;
207 MaxDripRate = maxDripRate; 195 RequestedBurst = MaxBurst;
208 m_lastDrip = Util.EnvironmentTickCount(); 196 // TotalDripRequest = dripRate; // this will be overwritten when a child node registers
197 // MaxBurst = (Int64)((double)dripRate * m_quantumsPerBurst);
198 m_lastDrip = Util.EnvironmentTickCount() + 100000;
209 } 199 }
210 200
201#endregion Constructor
202
211 /// <summary> 203 /// <summary>
212 /// Compute a modifier for the MaxBurst rate. This is 1.0, meaning 204 /// Compute a modifier for the MaxBurst rate. This is 1.0, meaning
213 /// no modification if the requested bandwidth is less than the 205 /// no modification if the requested bandwidth is less than the
@@ -215,22 +207,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
215 /// hierarchy. However, if any of the parents is over-booked, then 207 /// hierarchy. However, if any of the parents is over-booked, then
216 /// the modifier will be less than 1. 208 /// the modifier will be less than 1.
217 /// </summary> 209 /// </summary>
218 protected double DripRateModifier() 210 protected float DripRateModifier()
219 { 211 {
220 Int64 driprate = DripRate; 212 float driprate = DripRate;
221 double modifier = driprate >= TotalDripRequest ? 1.0 : (double)driprate / (double)TotalDripRequest; 213 return driprate >= TotalDripRequest ? 1.0f : driprate / TotalDripRequest;
222
223// if (DebugLevel > 0)
224// m_log.DebugFormat(
225// "[TOKEN BUCKET]: Returning drip modifier {0}/{1} = {2} from {3}",
226// driprate, TotalDripRequest, modifier, Identifier);
227
228 return modifier;
229 } 214 }
230 215
231 /// <summary> 216 /// <summary>
232 /// </summary> 217 /// </summary>
233 protected double BurstRateModifier() 218 protected float BurstModifier()
234 { 219 {
235 // for now... burst rate is always m_quantumsPerBurst (constant) 220 // for now... burst rate is always m_quantumsPerBurst (constant)
236 // larger than drip rate so the ratio of burst requests is the 221 // larger than drip rate so the ratio of burst requests is the
@@ -242,29 +227,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP
242 /// Register drip rate requested by a child of this throttle. Pass the 227 /// Register drip rate requested by a child of this throttle. Pass the
243 /// changes up the hierarchy. 228 /// changes up the hierarchy.
244 /// </summary> 229 /// </summary>
245 public void RegisterRequest(TokenBucket child, Int64 request) 230 public void RegisterRequest(TokenBucket child, float request)
246 { 231 {
247 lock (m_children) 232 lock (m_children)
248 { 233 {
249 m_children[child] = request; 234 m_children[child] = request;
250 235
251 TotalDripRequest = 0; 236 m_totalDripRequest = 0;
252 foreach (KeyValuePair<TokenBucket, Int64> cref in m_children) 237 foreach (KeyValuePair<TokenBucket, float> cref in m_children)
253 TotalDripRequest += cref.Value; 238 m_totalDripRequest += cref.Value;
254 } 239 }
255 240
256 // Pass the new values up to the parent 241 // Pass the new values up to the parent
257 if (Parent != null) 242 if (m_parent != null)
258 { 243 m_parent.RegisterRequest(this, Math.Min(RequestedDripRate, TotalDripRequest));
259 Int64 effectiveDripRate;
260
261 if (RequestedDripRate > 0)
262 effectiveDripRate = Math.Min(RequestedDripRate, TotalDripRequest);
263 else
264 effectiveDripRate = TotalDripRequest;
265
266 Parent.RegisterRequest(this, effectiveDripRate);
267 }
268 } 244 }
269 245
270 /// <summary> 246 /// <summary>
@@ -277,9 +253,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
277 { 253 {
278 m_children.Remove(child); 254 m_children.Remove(child);
279 255
280 TotalDripRequest = 0; 256 m_totalDripRequest = 0;
281 foreach (KeyValuePair<TokenBucket, Int64> cref in m_children) 257 foreach (KeyValuePair<TokenBucket, float> cref in m_children)
282 TotalDripRequest += cref.Value; 258 m_totalDripRequest += cref.Value;
283 } 259 }
284 260
285 // Pass the new values up to the parent 261 // Pass the new values up to the parent
@@ -293,7 +269,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
293 /// <param name="amount">Number of tokens to remove from the bucket</param> 269 /// <param name="amount">Number of tokens to remove from the bucket</param>
294 /// <returns>True if the requested number of tokens were removed from 270 /// <returns>True if the requested number of tokens were removed from
295 /// the bucket, otherwise false</returns> 271 /// the bucket, otherwise false</returns>
296 public bool RemoveTokens(Int64 amount) 272 public bool RemoveTokens(int amount)
297 { 273 {
298 // Deposit tokens for this interval 274 // Deposit tokens for this interval
299 Drip(); 275 Drip();
@@ -310,19 +286,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
310 return false; 286 return false;
311 } 287 }
312 288
313 /// <summary> 289 public bool CheckTokens(int amount)
314 /// Deposit tokens into the bucket from a child bucket that did
315 /// not use all of its available tokens
316 /// </summary>
317 protected void Deposit(Int64 count)
318 { 290 {
319 m_tokenCount += count; 291 return (m_tokenCount - amount >= 0);
292 }
320 293
321 // Deposit the overflow in the parent bucket, this is how we share 294 public int GetCatBytesCanSend(int timeMS)
322 // unused bandwidth 295 {
323 Int64 burstrate = BurstRate; 296// return (int)(m_tokenCount + timeMS * m_dripRate * 1e-3);
324 if (m_tokenCount > burstrate) 297 return (int)(timeMS * DripRate * 1e-3);
325 m_tokenCount = burstrate;
326 } 298 }
327 299
328 /// <summary> 300 /// <summary>
@@ -337,21 +309,22 @@ namespace OpenSim.Region.ClientStack.LindenUDP
337 // with no drip rate... 309 // with no drip rate...
338 if (DripRate == 0) 310 if (DripRate == 0)
339 { 311 {
340 m_log.WarnFormat("[TOKENBUCKET] something odd is happening and drip rate is 0 for {0}", Identifier); 312 m_log.WarnFormat("[TOKENBUCKET] something odd is happening and drip rate is 0 for {0}", m_counter);
341 return; 313 return;
342 } 314 }
343 315
344 // Determine the interval over which we are adding tokens, never add 316 Int32 now = Util.EnvironmentTickCount();
345 // more than a single quantum of tokens 317 Int32 deltaMS = now - m_lastDrip;
346 Int32 deltaMS = Math.Min(Util.EnvironmentTickCountSubtract(m_lastDrip), m_ticksPerQuantum); 318 m_lastDrip = now;
347 m_lastDrip = Util.EnvironmentTickCount();
348 319
349 // This can be 0 in the very unusual case that the timer wrapped
350 // It can be 0 if we try add tokens at a sub-tick rate
351 if (deltaMS <= 0) 320 if (deltaMS <= 0)
352 return; 321 return;
353 322
354 Deposit(deltaMS * DripRate / m_ticksPerQuantum); 323 m_tokenCount += deltaMS * DripRate * m_timeScale;
324
325 float burst = Burst;
326 if (m_tokenCount > burst)
327 m_tokenCount = burst;
355 } 328 }
356 } 329 }
357 330
@@ -362,103 +335,79 @@ namespace OpenSim.Region.ClientStack.LindenUDP
362 public bool AdaptiveEnabled { get; set; } 335 public bool AdaptiveEnabled { get; set; }
363 336
364 /// <summary> 337 /// <summary>
365 /// Target drip rate for this bucket. 338 /// The minimum rate for flow control. Minimum drip rate is one
339 /// packet per second.
366 /// </summary> 340 /// </summary>
367 /// <remarks>Usually set by the client. If adaptive is enabled then throttles will increase until we reach this.</remarks> 341
368 public Int64 TargetDripRate 342 protected const float m_minimumFlow = 50000;
369 { 343
370 get { return m_targetDripRate; } 344 // <summary>
371 set 345 // The maximum rate for flow control. Drip rate can never be
346 // greater than this.
347 // </summary>
348
349 protected float m_maxDripRate = 0;
350 public float MaxDripRate
351 {
352 get { return (m_maxDripRate == 0 ? m_totalDripRequest : m_maxDripRate); }
353 set
372 { 354 {
373 m_targetDripRate = Math.Max(value, m_minimumFlow); 355 m_maxDripRate = (value == 0 ? m_totalDripRequest : Math.Max(value, m_minimumFlow));
374 } 356 }
375 } 357 }
376 protected Int64 m_targetDripRate; 358
359 private bool m_enabled = false;
377 360
378 // <summary> 361 // <summary>
379 // Adjust drip rate in response to network conditions. 362 // Adjust drip rate in response to network conditions.
380 // </summary> 363 // </summary>
381 public virtual Int64 AdjustedDripRate 364 public virtual float AdjustedDripRate
382 { 365 {
383 get { return m_dripRate; } 366 get { return m_dripRate; }
384 set 367 set
385 { 368 {
386 m_dripRate = OpenSim.Framework.Util.Clamp<Int64>(value, m_minimumFlow, TargetDripRate); 369 m_dripRate = OpenSim.Framework.Util.Clamp<float>(value, m_minimumFlow, MaxDripRate);
387 m_burstRate = (Int64)((double)m_dripRate * m_quantumsPerBurst);
388 370
389 if (Parent != null) 371 if (m_parent != null)
390 Parent.RegisterRequest(this, m_dripRate); 372 m_parent.RegisterRequest(this, m_dripRate);
391 } 373 }
392 } 374 }
393 375
394 /// <summary> 376
395 /// The minimum rate for adaptive flow control. 377 // <summary>
396 /// </summary> 378 //
397 protected Int64 m_minimumFlow = 32000; 379 // </summary>
398 380 public AdaptiveTokenBucket(TokenBucket parent, float maxDripRate, float maxBurst, bool enabled)
399 /// <summary> 381 : base(parent, maxDripRate, maxBurst)
400 /// Constructor for the AdaptiveTokenBucket class
401 /// <param name="identifier">Unique identifier for the client</param>
402 /// <param name="parent">Parent bucket in the hierarchy</param>
403 /// <param name="requestedDripRate"></param>
404 /// <param name="maxDripRate">The ceiling rate for adaptation</param>
405 /// <param name="minDripRate">The floor rate for adaptation</param>
406 /// </summary>
407 public AdaptiveTokenBucket(string identifier, TokenBucket parent, Int64 requestedDripRate, Int64 maxDripRate, Int64 minDripRate, bool enabled)
408 : base(identifier, parent, requestedDripRate, maxDripRate)
409 { 382 {
410 AdaptiveEnabled = enabled; 383 m_enabled = enabled;
411 384
412 if (AdaptiveEnabled) 385 MaxDripRate = maxDripRate;
413 { 386
414// m_log.DebugFormat("[TOKENBUCKET]: Adaptive throttle enabled"); 387 if (enabled)
415 m_minimumFlow = minDripRate; 388 AdjustedDripRate = m_maxDripRate * .5f;
416 TargetDripRate = m_minimumFlow; 389 else
417 AdjustedDripRate = m_minimumFlow; 390 AdjustedDripRate = m_maxDripRate;
418 }
419 } 391 }
420 392
421 /// <summary> 393 /// <summary>
422 /// Reliable packets sent to the client for which we never received an ack adjust the drip rate down. 394 /// Reliable packets sent to the client for which we never received an ack adjust the drip rate down.
423 /// <param name="packets">Number of packets that expired without successful delivery</param> 395 /// <param name="packets">Number of packets that expired without successful delivery</param>
424 /// </summary> 396 /// </summary>
425 public void ExpirePackets(Int32 packets) 397 public void ExpirePackets(Int32 count)
426 { 398 {
427 if (AdaptiveEnabled) 399 // m_log.WarnFormat("[ADAPTIVEBUCKET] drop {0} by {1} expired packets",AdjustedDripRate,count);
428 { 400 if (m_enabled)
429 if (DebugLevel > 0) 401 AdjustedDripRate = (Int64)(AdjustedDripRate / Math.Pow(2, count));
430 m_log.WarnFormat(
431 "[ADAPTIVEBUCKET] drop {0} by {1} expired packets for {2}",
432 AdjustedDripRate, packets, Identifier);
433
434 // AdjustedDripRate = (Int64) (AdjustedDripRate / Math.Pow(2,packets));
435
436 // Compute the fallback solely on the rate allocated beyond the minimum, this
437 // should smooth out the fallback to the minimum rate
438 AdjustedDripRate = m_minimumFlow + (Int64) ((AdjustedDripRate - m_minimumFlow) / Math.Pow(2, packets));
439 }
440 } 402 }
441 403
442 /// <summary> 404 // <summary>
443 /// Reliable packets acked by the client adjust the drip rate up. 405 //
444 /// <param name="packets">Number of packets successfully acknowledged</param> 406 // </summary>
445 /// </summary> 407 public void AcknowledgePackets(Int32 count)
446 public void AcknowledgePackets(Int32 packets)
447 {
448 if (AdaptiveEnabled)
449 AdjustedDripRate = AdjustedDripRate + packets * LLUDPServer.MTU;
450 }
451
452 /// <summary>
453 /// Adjust the minimum flow level for the adaptive throttle, this will drop adjusted
454 /// throttles back to the minimum levels
455 /// <param>minDripRate--the new minimum flow</param>
456 /// </summary>
457 public void ResetMinimumAdaptiveFlow(Int64 minDripRate)
458 { 408 {
459 m_minimumFlow = minDripRate; 409 if (m_enabled)
460 TargetDripRate = m_minimumFlow; 410 AdjustedDripRate = AdjustedDripRate + count;
461 AdjustedDripRate = m_minimumFlow;
462 } 411 }
463 } 412 }
464} \ No newline at end of file 413}