aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ClientStack/LindenUDP
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/ClientStack/LindenUDP')
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/J2KImage.cs3
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs687
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs10
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs4
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/TokenBucket.cs66
5 files changed, 433 insertions, 337 deletions
diff --git a/OpenSim/Region/ClientStack/LindenUDP/J2KImage.cs b/OpenSim/Region/ClientStack/LindenUDP/J2KImage.cs
index e9e2dca..9dd6663 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/J2KImage.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/J2KImage.cs
@@ -202,6 +202,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
202 m_stopPacket = TexturePacketCount(); 202 m_stopPacket = TexturePacketCount();
203 } 203 }
204 204
205 //Give them at least two packets, to play nice with some broken viewers (SL also behaves this way)
206 if (m_stopPacket == 1 && Layers[0].End > FIRST_PACKET_SIZE) m_stopPacket++;
207
205 m_currentPacket = StartPacket; 208 m_currentPacket = StartPacket;
206 } 209 }
207 } 210 }
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
index 63469c8..00a605e 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
@@ -155,6 +155,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
155 public event RequestTaskInventory OnRequestTaskInventory; 155 public event RequestTaskInventory OnRequestTaskInventory;
156 public event UpdateInventoryItem OnUpdateInventoryItem; 156 public event UpdateInventoryItem OnUpdateInventoryItem;
157 public event CopyInventoryItem OnCopyInventoryItem; 157 public event CopyInventoryItem OnCopyInventoryItem;
158 public event MoveItemsAndLeaveCopy OnMoveItemsAndLeaveCopy;
158 public event MoveInventoryItem OnMoveInventoryItem; 159 public event MoveInventoryItem OnMoveInventoryItem;
159 public event RemoveInventoryItem OnRemoveInventoryItem; 160 public event RemoveInventoryItem OnRemoveInventoryItem;
160 public event RemoveInventoryFolder OnRemoveInventoryFolder; 161 public event RemoveInventoryFolder OnRemoveInventoryFolder;
@@ -327,7 +328,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
327 /// thread servicing the m_primFullUpdates queue after a kill. If this happens the object persists as an 328 /// thread servicing the m_primFullUpdates queue after a kill. If this happens the object persists as an
328 /// ownerless phantom. 329 /// ownerless phantom.
329 /// 330 ///
330 /// All manipulation of this set has to occur under a lock 331 /// All manipulation of this set has to occur under an m_entityUpdates.SyncRoot lock
331 /// 332 ///
332 /// </value> 333 /// </value>
333 protected HashSet<uint> m_killRecord; 334 protected HashSet<uint> m_killRecord;
@@ -335,6 +336,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
335// protected HashSet<uint> m_attachmentsSent; 336// protected HashSet<uint> m_attachmentsSent;
336 337
337 private int m_moneyBalance; 338 private int m_moneyBalance;
339 private bool m_deliverPackets = true;
338 private int m_animationSequenceNumber = 1; 340 private int m_animationSequenceNumber = 1;
339 private bool m_SendLogoutPacketWhenClosing = true; 341 private bool m_SendLogoutPacketWhenClosing = true;
340 private AgentUpdateArgs lastarg; 342 private AgentUpdateArgs lastarg;
@@ -377,6 +379,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
377 get { return m_startpos; } 379 get { return m_startpos; }
378 set { m_startpos = value; } 380 set { m_startpos = value; }
379 } 381 }
382 public bool DeliverPackets
383 {
384 get { return m_deliverPackets; }
385 set {
386 m_deliverPackets = value;
387 m_udpClient.m_deliverPackets = value;
388 }
389 }
380 public UUID AgentId { get { return m_agentId; } } 390 public UUID AgentId { get { return m_agentId; } }
381 public UUID ActiveGroupId { get { return m_activeGroupID; } } 391 public UUID ActiveGroupId { get { return m_activeGroupID; } }
382 public string ActiveGroupName { get { return m_activeGroupName; } } 392 public string ActiveGroupName { get { return m_activeGroupName; } }
@@ -475,18 +485,30 @@ namespace OpenSim.Region.ClientStack.LindenUDP
475 485
476 #region Client Methods 486 #region Client Methods
477 487
488
478 /// <summary> 489 /// <summary>
479 /// Shut down the client view 490 /// Shut down the client view
480 /// </summary> 491 /// </summary>
481 public void Close() 492 public void Close()
482 { 493 {
494 Close(true);
495 }
496
497 /// <summary>
498 /// Shut down the client view
499 /// </summary>
500 public void Close(bool sendStop)
501 {
483 m_log.DebugFormat( 502 m_log.DebugFormat(
484 "[CLIENT]: Close has been called for {0} attached to scene {1}", 503 "[CLIENT]: Close has been called for {0} attached to scene {1}",
485 Name, m_scene.RegionInfo.RegionName); 504 Name, m_scene.RegionInfo.RegionName);
486 505
487 // Send the STOP packet 506 if (sendStop)
488 DisableSimulatorPacket disable = (DisableSimulatorPacket)PacketPool.Instance.GetPacket(PacketType.DisableSimulator); 507 {
489 OutPacket(disable, ThrottleOutPacketType.Unknown); 508 // Send the STOP packet
509 DisableSimulatorPacket disable = (DisableSimulatorPacket)PacketPool.Instance.GetPacket(PacketType.DisableSimulator);
510 OutPacket(disable, ThrottleOutPacketType.Unknown);
511 }
490 512
491 IsActive = false; 513 IsActive = false;
492 514
@@ -767,7 +789,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
767 reply.ChatData.OwnerID = fromAgentID; 789 reply.ChatData.OwnerID = fromAgentID;
768 reply.ChatData.SourceID = fromAgentID; 790 reply.ChatData.SourceID = fromAgentID;
769 791
770 OutPacket(reply, ThrottleOutPacketType.Task); 792 OutPacket(reply, ThrottleOutPacketType.Unknown);
771 } 793 }
772 794
773 /// <summary> 795 /// <summary>
@@ -1053,6 +1075,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1053 public virtual void SendLayerData(float[] map) 1075 public virtual void SendLayerData(float[] map)
1054 { 1076 {
1055 Util.FireAndForget(DoSendLayerData, map); 1077 Util.FireAndForget(DoSendLayerData, map);
1078
1079 // Send it sync, and async. It's not that much data
1080 // and it improves user experience just so much!
1081 DoSendLayerData(map);
1056 } 1082 }
1057 1083
1058 /// <summary> 1084 /// <summary>
@@ -1065,16 +1091,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1065 1091
1066 try 1092 try
1067 { 1093 {
1068 //for (int y = 0; y < 16; y++) 1094 for (int y = 0; y < 16; y++)
1069 //{ 1095 {
1070 // for (int x = 0; x < 16; x++) 1096 for (int x = 0; x < 16; x+=4)
1071 // { 1097 {
1072 // SendLayerData(x, y, map); 1098 SendLayerPacket(x, y, map);
1073 // } 1099 }
1074 //} 1100 }
1075
1076 // Send LayerData in a spiral pattern. Fun!
1077 SendLayerTopRight(map, 0, 0, 15, 15);
1078 } 1101 }
1079 catch (Exception e) 1102 catch (Exception e)
1080 { 1103 {
@@ -1082,51 +1105,35 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1082 } 1105 }
1083 } 1106 }
1084 1107
1085 private void SendLayerTopRight(float[] map, int x1, int y1, int x2, int y2)
1086 {
1087 // Row
1088 for (int i = x1; i <= x2; i++)
1089 SendLayerData(i, y1, map);
1090
1091 // Column
1092 for (int j = y1 + 1; j <= y2; j++)
1093 SendLayerData(x2, j, map);
1094
1095 if (x2 - x1 > 0)
1096 SendLayerBottomLeft(map, x1, y1 + 1, x2 - 1, y2);
1097 }
1098
1099 void SendLayerBottomLeft(float[] map, int x1, int y1, int x2, int y2)
1100 {
1101 // Row in reverse
1102 for (int i = x2; i >= x1; i--)
1103 SendLayerData(i, y2, map);
1104
1105 // Column in reverse
1106 for (int j = y2 - 1; j >= y1; j--)
1107 SendLayerData(x1, j, map);
1108
1109 if (x2 - x1 > 0)
1110 SendLayerTopRight(map, x1 + 1, y1, x2, y2 - 1);
1111 }
1112
1113 /// <summary> 1108 /// <summary>
1114 /// Sends a set of four patches (x, x+1, ..., x+3) to the client 1109 /// Sends a set of four patches (x, x+1, ..., x+3) to the client
1115 /// </summary> 1110 /// </summary>
1116 /// <param name="map">heightmap</param> 1111 /// <param name="map">heightmap</param>
1117 /// <param name="px">X coordinate for patches 0..12</param> 1112 /// <param name="px">X coordinate for patches 0..12</param>
1118 /// <param name="py">Y coordinate for patches 0..15</param> 1113 /// <param name="py">Y coordinate for patches 0..15</param>
1119 // private void SendLayerPacket(float[] map, int y, int x) 1114 private void SendLayerPacket(int x, int y, float[] map)
1120 // { 1115 {
1121 // int[] patches = new int[4]; 1116 int[] patches = new int[4];
1122 // patches[0] = x + 0 + y * 16; 1117 patches[0] = x + 0 + y * 16;
1123 // patches[1] = x + 1 + y * 16; 1118 patches[1] = x + 1 + y * 16;
1124 // patches[2] = x + 2 + y * 16; 1119 patches[2] = x + 2 + y * 16;
1125 // patches[3] = x + 3 + y * 16; 1120 patches[3] = x + 3 + y * 16;
1126 1121
1127 // Packet layerpack = LLClientView.TerrainManager.CreateLandPacket(map, patches); 1122 float[] heightmap = (map.Length == 65536) ?
1128 // OutPacket(layerpack, ThrottleOutPacketType.Land); 1123 map :
1129 // } 1124 LLHeightFieldMoronize(map);
1125
1126 try
1127 {
1128 Packet layerpack = TerrainCompressor.CreateLandPacket(heightmap, patches);
1129 OutPacket(layerpack, ThrottleOutPacketType.Land);
1130 }
1131 catch
1132 {
1133 for (int px = x ; px < x + 4 ; px++)
1134 SendLayerData(px, y, map);
1135 }
1136 }
1130 1137
1131 /// <summary> 1138 /// <summary>
1132 /// Sends a specified patch to a client 1139 /// Sends a specified patch to a client
@@ -1146,7 +1153,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1146 LayerDataPacket layerpack = TerrainCompressor.CreateLandPacket(heightmap, patches); 1153 LayerDataPacket layerpack = TerrainCompressor.CreateLandPacket(heightmap, patches);
1147 layerpack.Header.Reliable = true; 1154 layerpack.Header.Reliable = true;
1148 1155
1149 OutPacket(layerpack, ThrottleOutPacketType.Land); 1156 OutPacket(layerpack, ThrottleOutPacketType.Task);
1150 } 1157 }
1151 catch (Exception e) 1158 catch (Exception e)
1152 { 1159 {
@@ -1507,37 +1514,49 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1507 OutPacket(pc, ThrottleOutPacketType.Unknown); 1514 OutPacket(pc, ThrottleOutPacketType.Unknown);
1508 } 1515 }
1509 1516
1510 public void SendKillObject(ulong regionHandle, uint localID) 1517 public void SendKillObject(ulong regionHandle, List<uint> localIDs)
1511 { 1518 {
1512// m_log.DebugFormat("[CLIENT]: Sending KillObjectPacket to {0} for {1} in {2}", Name, localID, regionHandle); 1519// m_log.DebugFormat("[CLIENT]: Sending KillObjectPacket to {0} for {1} in {2}", Name, localID, regionHandle);
1513 1520
1514 KillObjectPacket kill = (KillObjectPacket)PacketPool.Instance.GetPacket(PacketType.KillObject); 1521 KillObjectPacket kill = (KillObjectPacket)PacketPool.Instance.GetPacket(PacketType.KillObject);
1515 // TODO: don't create new blocks if recycling an old packet 1522 // TODO: don't create new blocks if recycling an old packet
1516 kill.ObjectData = new KillObjectPacket.ObjectDataBlock[1]; 1523 kill.ObjectData = new KillObjectPacket.ObjectDataBlock[localIDs.Count];
1517 kill.ObjectData[0] = new KillObjectPacket.ObjectDataBlock(); 1524 for (int i = 0 ; i < localIDs.Count ; i++ )
1518 kill.ObjectData[0].ID = localID; 1525 {
1526 kill.ObjectData[i] = new KillObjectPacket.ObjectDataBlock();
1527 kill.ObjectData[i].ID = localIDs[i];
1528 }
1519 kill.Header.Reliable = true; 1529 kill.Header.Reliable = true;
1520 kill.Header.Zerocoded = true; 1530 kill.Header.Zerocoded = true;
1521 1531
1522 if (m_scene.GetScenePresence(localID) == null) 1532 lock (m_killRecord)
1523 { 1533 {
1524 // We must lock for both manipulating the kill record and sending the packet, in order to avoid a race 1534 if (localIDs.Count == 1)
1525 // condition where a kill can be processed before an out-of-date update for the same object.
1526 lock (m_killRecord)
1527 { 1535 {
1528 m_killRecord.Add(localID); 1536 if (m_scene.GetScenePresence(localIDs[0]) != null)
1529 1537 {
1530 // The throttle queue used here must match that being used for updates. Otherwise, there is a 1538 OutPacket(kill, ThrottleOutPacketType.State);
1531 // chance that a kill packet put on a separate queue will be sent to the client before an existing 1539 return;
1532 // update packet on another queue. Receiving updates after kills results in unowned and undeletable 1540 }
1533 // scene objects in a viewer until that viewer is relogged in. 1541 m_killRecord.Add(localIDs[0]);
1534 OutPacket(kill, ThrottleOutPacketType.Task); 1542 }
1543 else
1544 {
1545 lock (m_entityUpdates.SyncRoot)
1546 {
1547 foreach (uint localID in localIDs)
1548 m_killRecord.Add(localID);
1549 }
1535 } 1550 }
1536 } 1551 }
1537 else 1552
1538 { 1553 // The throttle queue used here must match that being used for
1539 OutPacket(kill, ThrottleOutPacketType.State); 1554 // updates. Otherwise, there is a chance that a kill packet put
1540 } 1555 // on a separate queue will be sent to the client before an
1556 // existing update packet on another queue. Receiving updates
1557 // after kills results in unowned and undeletable
1558 // scene objects in a viewer until that viewer is relogged in.
1559 OutPacket(kill, ThrottleOutPacketType.Task);
1541 } 1560 }
1542 1561
1543 /// <summary> 1562 /// <summary>
@@ -2243,6 +2262,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2243 OutPacket(sound, ThrottleOutPacketType.Task); 2262 OutPacket(sound, ThrottleOutPacketType.Task);
2244 } 2263 }
2245 2264
2265 public void SendTransferAbort(TransferRequestPacket transferRequest)
2266 {
2267 TransferAbortPacket abort = (TransferAbortPacket)PacketPool.Instance.GetPacket(PacketType.TransferAbort);
2268 abort.TransferInfo.TransferID = transferRequest.TransferInfo.TransferID;
2269 abort.TransferInfo.ChannelType = transferRequest.TransferInfo.ChannelType;
2270 m_log.Debug("[Assets] Aborting transfer; asset request failed");
2271 OutPacket(abort, ThrottleOutPacketType.Task);
2272 }
2273
2246 public void SendTriggeredSound(UUID soundID, UUID ownerID, UUID objectID, UUID parentID, ulong handle, Vector3 position, float gain) 2274 public void SendTriggeredSound(UUID soundID, UUID ownerID, UUID objectID, UUID parentID, ulong handle, Vector3 position, float gain)
2247 { 2275 {
2248 SoundTriggerPacket sound = (SoundTriggerPacket)PacketPool.Instance.GetPacket(PacketType.SoundTrigger); 2276 SoundTriggerPacket sound = (SoundTriggerPacket)PacketPool.Instance.GetPacket(PacketType.SoundTrigger);
@@ -3544,6 +3572,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3544 /// </summary> 3572 /// </summary>
3545 public void SendPrimUpdate(ISceneEntity entity, PrimUpdateFlags updateFlags) 3573 public void SendPrimUpdate(ISceneEntity entity, PrimUpdateFlags updateFlags)
3546 { 3574 {
3575 if (entity is SceneObjectPart)
3576 {
3577 SceneObjectPart e = (SceneObjectPart)entity;
3578 SceneObjectGroup g = e.ParentGroup;
3579 if (g.RootPart.Shape.State > 30) // HUD
3580 if (g.OwnerID != AgentId)
3581 return; // Don't send updates for other people's HUDs
3582 }
3583
3547 double priority = m_prioritizer.GetUpdatePriority(this, entity); 3584 double priority = m_prioritizer.GetUpdatePriority(this, entity);
3548 3585
3549 lock (m_entityUpdates.SyncRoot) 3586 lock (m_entityUpdates.SyncRoot)
@@ -3560,226 +3597,252 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3560 if (maxUpdates <= 0) maxUpdates = Int32.MaxValue; 3597 if (maxUpdates <= 0) maxUpdates = Int32.MaxValue;
3561 int updatesThisCall = 0; 3598 int updatesThisCall = 0;
3562 3599
3563 // We must lock for both manipulating the kill record and sending the packet, in order to avoid a race 3600 EntityUpdate update;
3564 // condition where a kill can be processed before an out-of-date update for the same object. 3601 while (updatesThisCall < maxUpdates)
3565 lock (m_killRecord) 3602 {
3566 { 3603 lock (m_entityUpdates.SyncRoot)
3567 EntityUpdate update; 3604 if (!m_entityUpdates.TryDequeue(out update))
3568 while (updatesThisCall < maxUpdates) 3605 break;
3569 { 3606
3570 lock (m_entityUpdates.SyncRoot) 3607 if (update.Entity is SceneObjectPart)
3571 if (!m_entityUpdates.TryDequeue(out update)) 3608 {
3572 break; 3609 SceneObjectPart part = (SceneObjectPart)update.Entity;
3573 3610
3574 if (update.Entity is SceneObjectPart) 3611 // Please do not remove this unless you can demonstrate on the OpenSim mailing list that a client
3612 // will never receive an update after a prim kill. Even then, keeping the kill record may be a good
3613 // safety measure.
3614 //
3615 // If a Linden Lab 1.23.5 client (and possibly later and earlier) receives an object update
3616 // after a kill, it will keep displaying the deleted object until relog. OpenSim currently performs
3617 // updates and kills on different threads with different scheduling strategies, hence this protection.
3618 //
3619 // This doesn't appear to apply to child prims - a client will happily ignore these updates
3620 // after the root prim has been deleted.
3621 lock (m_killRecord)
3575 { 3622 {
3576 SceneObjectPart part = (SceneObjectPart)update.Entity;
3577
3578 // Please do not remove this unless you can demonstrate on the OpenSim mailing list that a client
3579 // will never receive an update after a prim kill. Even then, keeping the kill record may be a good
3580 // safety measure.
3581 //
3582 // If a Linden Lab 1.23.5 client (and possibly later and earlier) receives an object update
3583 // after a kill, it will keep displaying the deleted object until relog. OpenSim currently performs
3584 // updates and kills on different threads with different scheduling strategies, hence this protection.
3585 //
3586 // This doesn't appear to apply to child prims - a client will happily ignore these updates
3587 // after the root prim has been deleted.
3588 if (m_killRecord.Contains(part.LocalId)) 3623 if (m_killRecord.Contains(part.LocalId))
3589 {
3590 // m_log.WarnFormat(
3591 // "[CLIENT]: Preventing update for prim with local id {0} after client for user {1} told it was deleted",
3592 // part.LocalId, Name);
3593 continue; 3624 continue;
3594 } 3625 if (m_killRecord.Contains(part.ParentGroup.RootPart.LocalId))
3595 3626 continue;
3596 if (part.ParentGroup.IsAttachment && m_disableFacelights) 3627 }
3628
3629 if (part.ParentGroup.IsDeleted)
3630 continue;
3631
3632 if (part.ParentGroup.IsAttachment)
3633 { // Someone else's HUD, why are we getting these?
3634 if (part.ParentGroup.OwnerID != AgentId &&
3635 part.ParentGroup.RootPart.Shape.State >= 30)
3636 continue;
3637 ScenePresence sp;
3638 // Owner is not in the sim, don't update it to
3639 // anyone
3640 if (!m_scene.TryGetScenePresence(part.OwnerID, out sp))
3641 continue;
3642
3643 List<SceneObjectGroup> atts = sp.Attachments;
3644 bool found = false;
3645 foreach (SceneObjectGroup att in atts)
3597 { 3646 {
3598 if (part.ParentGroup.RootPart.Shape.State != (byte)AttachmentPoint.LeftHand && 3647 if (att == part.ParentGroup)
3599 part.ParentGroup.RootPart.Shape.State != (byte)AttachmentPoint.RightHand)
3600 { 3648 {
3601 part.Shape.LightEntry = false; 3649 found = true;
3650 break;
3602 } 3651 }
3603 } 3652 }
3653
3654 // It's an attachment of a valid avatar, but
3655 // doesn't seem to be attached, skip
3656 if (!found)
3657 continue;
3604 } 3658 }
3605 3659
3606 ++updatesThisCall; 3660 if (part.ParentGroup.IsAttachment && m_disableFacelights)
3607
3608 #region UpdateFlags to packet type conversion
3609
3610 PrimUpdateFlags updateFlags = update.Flags;
3611
3612 bool canUseCompressed = true;
3613 bool canUseImproved = true;
3614
3615 // Compressed object updates only make sense for LL primitives
3616 if (!(update.Entity is SceneObjectPart))
3617 { 3661 {
3618 canUseCompressed = false; 3662 if (part.ParentGroup.RootPart.Shape.State != (byte)AttachmentPoint.LeftHand &&
3663 part.ParentGroup.RootPart.Shape.State != (byte)AttachmentPoint.RightHand)
3664 {
3665 part.Shape.LightEntry = false;
3666 }
3619 } 3667 }
3620 3668 }
3621 if (updateFlags.HasFlag(PrimUpdateFlags.FullUpdate)) 3669
3670 ++updatesThisCall;
3671
3672 #region UpdateFlags to packet type conversion
3673
3674 PrimUpdateFlags updateFlags = update.Flags;
3675
3676 bool canUseCompressed = true;
3677 bool canUseImproved = true;
3678
3679 // Compressed object updates only make sense for LL primitives
3680 if (!(update.Entity is SceneObjectPart))
3681 {
3682 canUseCompressed = false;
3683 }
3684
3685 if (updateFlags.HasFlag(PrimUpdateFlags.FullUpdate))
3686 {
3687 canUseCompressed = false;
3688 canUseImproved = false;
3689 }
3690 else
3691 {
3692 if (updateFlags.HasFlag(PrimUpdateFlags.Velocity) ||
3693 updateFlags.HasFlag(PrimUpdateFlags.Acceleration) ||
3694 updateFlags.HasFlag(PrimUpdateFlags.CollisionPlane) ||
3695 updateFlags.HasFlag(PrimUpdateFlags.Joint))
3622 { 3696 {
3623 canUseCompressed = false; 3697 canUseCompressed = false;
3698 }
3699
3700 if (updateFlags.HasFlag(PrimUpdateFlags.PrimFlags) ||
3701 updateFlags.HasFlag(PrimUpdateFlags.ParentID) ||
3702 updateFlags.HasFlag(PrimUpdateFlags.Scale) ||
3703 updateFlags.HasFlag(PrimUpdateFlags.PrimData) ||
3704 updateFlags.HasFlag(PrimUpdateFlags.Text) ||
3705 updateFlags.HasFlag(PrimUpdateFlags.NameValue) ||
3706 updateFlags.HasFlag(PrimUpdateFlags.ExtraData) ||
3707 updateFlags.HasFlag(PrimUpdateFlags.TextureAnim) ||
3708 updateFlags.HasFlag(PrimUpdateFlags.Sound) ||
3709 updateFlags.HasFlag(PrimUpdateFlags.Particles) ||
3710 updateFlags.HasFlag(PrimUpdateFlags.Material) ||
3711 updateFlags.HasFlag(PrimUpdateFlags.ClickAction) ||
3712 updateFlags.HasFlag(PrimUpdateFlags.MediaURL) ||
3713 updateFlags.HasFlag(PrimUpdateFlags.Joint))
3714 {
3624 canUseImproved = false; 3715 canUseImproved = false;
3625 } 3716 }
3717 }
3718
3719 #endregion UpdateFlags to packet type conversion
3720
3721 #region Block Construction
3722
3723 // TODO: Remove this once we can build compressed updates
3724 canUseCompressed = false;
3725
3726 if (!canUseImproved && !canUseCompressed)
3727 {
3728 if (update.Entity is ScenePresence)
3729 {
3730 objectUpdateBlocks.Value.Add(CreateAvatarUpdateBlock((ScenePresence)update.Entity));
3731 }
3626 else 3732 else
3627 { 3733 {
3628 if (updateFlags.HasFlag(PrimUpdateFlags.Velocity) || 3734// if (update.Entity is SceneObjectPart && ((SceneObjectPart)update.Entity).IsAttachment)
3629 updateFlags.HasFlag(PrimUpdateFlags.Acceleration) || 3735// {
3630 updateFlags.HasFlag(PrimUpdateFlags.CollisionPlane) || 3736// SceneObjectPart sop = (SceneObjectPart)update.Entity;
3631 updateFlags.HasFlag(PrimUpdateFlags.Joint)) 3737// string text = sop.Text;
3632 { 3738// if (text.IndexOf("\n") >= 0)
3633 canUseCompressed = false; 3739// text = text.Remove(text.IndexOf("\n"));
3634 } 3740//
3635 3741// if (m_attachmentsSent.Contains(sop.ParentID))
3636 if (updateFlags.HasFlag(PrimUpdateFlags.PrimFlags) || 3742// {
3637 updateFlags.HasFlag(PrimUpdateFlags.ParentID) || 3743//// m_log.DebugFormat(
3638 updateFlags.HasFlag(PrimUpdateFlags.Scale) || 3744//// "[CLIENT]: Sending full info about attached prim {0} text {1}",
3639 updateFlags.HasFlag(PrimUpdateFlags.PrimData) || 3745//// sop.LocalId, text);
3640 updateFlags.HasFlag(PrimUpdateFlags.Text) || 3746//
3641 updateFlags.HasFlag(PrimUpdateFlags.NameValue) || 3747// objectUpdateBlocks.Value.Add(CreatePrimUpdateBlock(sop, this.m_agentId));
3642 updateFlags.HasFlag(PrimUpdateFlags.ExtraData) || 3748//
3643 updateFlags.HasFlag(PrimUpdateFlags.TextureAnim) || 3749// m_attachmentsSent.Add(sop.LocalId);
3644 updateFlags.HasFlag(PrimUpdateFlags.Sound) || 3750// }
3645 updateFlags.HasFlag(PrimUpdateFlags.Particles) || 3751// else
3646 updateFlags.HasFlag(PrimUpdateFlags.Material) || 3752// {
3647 updateFlags.HasFlag(PrimUpdateFlags.ClickAction) || 3753// m_log.DebugFormat(
3648 updateFlags.HasFlag(PrimUpdateFlags.MediaURL) || 3754// "[CLIENT]: Requeueing full update of prim {0} text {1} since we haven't sent its parent {2} yet",
3649 updateFlags.HasFlag(PrimUpdateFlags.Joint)) 3755// sop.LocalId, text, sop.ParentID);
3650 { 3756//
3651 canUseImproved = false; 3757// m_entityUpdates.Enqueue(double.MaxValue, update, sop.LocalId);
3652 } 3758// }
3759// }
3760// else
3761// {
3762 objectUpdateBlocks.Value.Add(CreatePrimUpdateBlock((SceneObjectPart)update.Entity, this.m_agentId));
3763// }
3653 } 3764 }
3765 }
3766 else if (!canUseImproved)
3767 {
3768 compressedUpdateBlocks.Value.Add(CreateCompressedUpdateBlock((SceneObjectPart)update.Entity, updateFlags));
3769 }
3770 else
3771 {
3772 if (update.Entity is ScenePresence && ((ScenePresence)update.Entity).UUID == AgentId)
3773 // Self updates go into a special list
3774 terseAgentUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures)));
3775 else
3776 // Everything else goes here
3777 terseUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures)));
3778 }
3779
3780 #endregion Block Construction
3781 }
3782
3783 #region Packet Sending
3654 3784
3655 #endregion UpdateFlags to packet type conversion 3785 const float TIME_DILATION = 1.0f;
3786 ushort timeDilation = Utils.FloatToUInt16(TIME_DILATION, 0.0f, 1.0f);
3787
3788 if (terseAgentUpdateBlocks.IsValueCreated)
3789 {
3790 List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseAgentUpdateBlocks.Value;
3791
3792 ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket();
3793 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
3794 packet.RegionData.TimeDilation = timeDilation;
3795 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count];
3796
3797 for (int i = 0; i < blocks.Count; i++)
3798 packet.ObjectData[i] = blocks[i];
3799
3800 OutPacket(packet, ThrottleOutPacketType.Unknown, true);
3801 }
3802
3803 if (objectUpdateBlocks.IsValueCreated)
3804 {
3805 List<ObjectUpdatePacket.ObjectDataBlock> blocks = objectUpdateBlocks.Value;
3656 3806
3657 #region Block Construction 3807 ObjectUpdatePacket packet = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate);
3808 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
3809 packet.RegionData.TimeDilation = timeDilation;
3810 packet.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[blocks.Count];
3658 3811
3659 // TODO: Remove this once we can build compressed updates 3812 for (int i = 0; i < blocks.Count; i++)
3660 canUseCompressed = false; 3813 packet.ObjectData[i] = blocks[i];
3661 3814
3662 if (!canUseImproved && !canUseCompressed) 3815 OutPacket(packet, ThrottleOutPacketType.Task, true);
3663 { 3816 }
3664 if (update.Entity is ScenePresence)
3665 {
3666 objectUpdateBlocks.Value.Add(CreateAvatarUpdateBlock((ScenePresence)update.Entity));
3667 }
3668 else
3669 {
3670 // if (update.Entity is SceneObjectPart && ((SceneObjectPart)update.Entity).IsAttachment)
3671 // {
3672 // SceneObjectPart sop = (SceneObjectPart)update.Entity;
3673 // string text = sop.Text;
3674 // if (text.IndexOf("\n") >= 0)
3675 // text = text.Remove(text.IndexOf("\n"));
3676 //
3677 // if (m_attachmentsSent.Contains(sop.ParentID))
3678 // {
3679 //// m_log.DebugFormat(
3680 //// "[CLIENT]: Sending full info about attached prim {0} text {1}",
3681 //// sop.LocalId, text);
3682 //
3683 // objectUpdateBlocks.Value.Add(CreatePrimUpdateBlock(sop, this.m_agentId));
3684 //
3685 // m_attachmentsSent.Add(sop.LocalId);
3686 // }
3687 // else
3688 // {
3689 // m_log.DebugFormat(
3690 // "[CLIENT]: Requeueing full update of prim {0} text {1} since we haven't sent its parent {2} yet",
3691 // sop.LocalId, text, sop.ParentID);
3692 //
3693 // m_entityUpdates.Enqueue(double.MaxValue, update, sop.LocalId);
3694 // }
3695 // }
3696 // else
3697 // {
3698 objectUpdateBlocks.Value.Add(CreatePrimUpdateBlock((SceneObjectPart)update.Entity, this.m_agentId));
3699 // }
3700 }
3701 }
3702 else if (!canUseImproved)
3703 {
3704 compressedUpdateBlocks.Value.Add(CreateCompressedUpdateBlock((SceneObjectPart)update.Entity, updateFlags));
3705 }
3706 else
3707 {
3708 if (update.Entity is ScenePresence && ((ScenePresence)update.Entity).UUID == AgentId)
3709 // Self updates go into a special list
3710 terseAgentUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures)));
3711 else
3712 // Everything else goes here
3713 terseUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures)));
3714 }
3715 3817
3716 #endregion Block Construction 3818 if (compressedUpdateBlocks.IsValueCreated)
3717 } 3819 {
3820 List<ObjectUpdateCompressedPacket.ObjectDataBlock> blocks = compressedUpdateBlocks.Value;
3718 3821
3719 #region Packet Sending 3822 ObjectUpdateCompressedPacket packet = (ObjectUpdateCompressedPacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdateCompressed);
3720 3823 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
3721 const float TIME_DILATION = 1.0f; 3824 packet.RegionData.TimeDilation = timeDilation;
3722 ushort timeDilation = Utils.FloatToUInt16(TIME_DILATION, 0.0f, 1.0f); 3825 packet.ObjectData = new ObjectUpdateCompressedPacket.ObjectDataBlock[blocks.Count];
3723 3826
3724 if (terseAgentUpdateBlocks.IsValueCreated) 3827 for (int i = 0; i < blocks.Count; i++)
3725 { 3828 packet.ObjectData[i] = blocks[i];
3726 List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseAgentUpdateBlocks.Value;
3727 3829
3728 ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket(); 3830 OutPacket(packet, ThrottleOutPacketType.Task, true);
3729 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; 3831 }
3730 packet.RegionData.TimeDilation = timeDilation;
3731 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count];
3732 3832
3733 for (int i = 0; i < blocks.Count; i++) 3833 if (terseUpdateBlocks.IsValueCreated)
3734 packet.ObjectData[i] = blocks[i]; 3834 {
3835 List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseUpdateBlocks.Value;
3735 3836
3736 OutPacket(packet, ThrottleOutPacketType.Unknown, true); 3837 ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket();
3737 } 3838 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
3839 packet.RegionData.TimeDilation = timeDilation;
3840 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count];
3738 3841
3739 if (objectUpdateBlocks.IsValueCreated) 3842 for (int i = 0; i < blocks.Count; i++)
3740 { 3843 packet.ObjectData[i] = blocks[i];
3741 List<ObjectUpdatePacket.ObjectDataBlock> blocks = objectUpdateBlocks.Value; 3844
3742 3845 OutPacket(packet, ThrottleOutPacketType.Task, true);
3743 ObjectUpdatePacket packet = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate);
3744 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
3745 packet.RegionData.TimeDilation = timeDilation;
3746 packet.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[blocks.Count];
3747
3748 for (int i = 0; i < blocks.Count; i++)
3749 packet.ObjectData[i] = blocks[i];
3750
3751 OutPacket(packet, ThrottleOutPacketType.Task, true);
3752 }
3753
3754 if (compressedUpdateBlocks.IsValueCreated)
3755 {
3756 List<ObjectUpdateCompressedPacket.ObjectDataBlock> blocks = compressedUpdateBlocks.Value;
3757
3758 ObjectUpdateCompressedPacket packet = (ObjectUpdateCompressedPacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdateCompressed);
3759 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
3760 packet.RegionData.TimeDilation = timeDilation;
3761 packet.ObjectData = new ObjectUpdateCompressedPacket.ObjectDataBlock[blocks.Count];
3762
3763 for (int i = 0; i < blocks.Count; i++)
3764 packet.ObjectData[i] = blocks[i];
3765
3766 OutPacket(packet, ThrottleOutPacketType.Task, true);
3767 }
3768
3769 if (terseUpdateBlocks.IsValueCreated)
3770 {
3771 List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseUpdateBlocks.Value;
3772
3773 ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket();
3774 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
3775 packet.RegionData.TimeDilation = timeDilation;
3776 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count];
3777
3778 for (int i = 0; i < blocks.Count; i++)
3779 packet.ObjectData[i] = blocks[i];
3780
3781 OutPacket(packet, ThrottleOutPacketType.Task, true);
3782 }
3783 } 3846 }
3784 3847
3785 #endregion Packet Sending 3848 #endregion Packet Sending
@@ -4045,6 +4108,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4045 { 4108 {
4046 m_propertiesPacketTimer.Stop(); 4109 m_propertiesPacketTimer.Stop();
4047 4110
4111 if (m_propertiesBlocks.Count == 0)
4112 return;
4113
4048 proper.ObjectData = new ObjectPropertiesPacket.ObjectDataBlock[m_propertiesBlocks.Count]; 4114 proper.ObjectData = new ObjectPropertiesPacket.ObjectDataBlock[m_propertiesBlocks.Count];
4049 4115
4050 int index = 0; 4116 int index = 0;
@@ -4436,14 +4502,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4436 4502
4437 if (notifyCount > 0) 4503 if (notifyCount > 0)
4438 { 4504 {
4439 if (notifyCount > 32) 4505// if (notifyCount > 32)
4440 { 4506// {
4441 m_log.InfoFormat( 4507// m_log.InfoFormat(
4442 "[LAND]: More than {0} avatars own prims on this parcel. Only sending back details of first {0}" 4508// "[LAND]: More than {0} avatars own prims on this parcel. Only sending back details of first {0}"
4443 + " - a developer might want to investigate whether this is a hard limit", 32); 4509// + " - a developer might want to investigate whether this is a hard limit", 32);
4444 4510//
4445 notifyCount = 32; 4511// notifyCount = 32;
4446 } 4512// }
4447 4513
4448 ParcelObjectOwnersReplyPacket.DataBlock[] dataBlock 4514 ParcelObjectOwnersReplyPacket.DataBlock[] dataBlock
4449 = new ParcelObjectOwnersReplyPacket.DataBlock[notifyCount]; 4515 = new ParcelObjectOwnersReplyPacket.DataBlock[notifyCount];
@@ -4951,6 +5017,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4951 AddLocalPacketHandler(PacketType.TransferAbort, HandleTransferAbort, false); 5017 AddLocalPacketHandler(PacketType.TransferAbort, HandleTransferAbort, false);
4952 AddLocalPacketHandler(PacketType.MuteListRequest, HandleMuteListRequest, false); 5018 AddLocalPacketHandler(PacketType.MuteListRequest, HandleMuteListRequest, false);
4953 AddLocalPacketHandler(PacketType.UseCircuitCode, HandleUseCircuitCode); 5019 AddLocalPacketHandler(PacketType.UseCircuitCode, HandleUseCircuitCode);
5020 AddLocalPacketHandler(PacketType.CreateNewOutfitAttachments, HandleCreateNewOutfitAttachments);
4954 AddLocalPacketHandler(PacketType.AgentHeightWidth, HandleAgentHeightWidth, false); 5021 AddLocalPacketHandler(PacketType.AgentHeightWidth, HandleAgentHeightWidth, false);
4955 AddLocalPacketHandler(PacketType.InventoryDescendents, HandleInventoryDescendents); 5022 AddLocalPacketHandler(PacketType.InventoryDescendents, HandleInventoryDescendents);
4956 AddLocalPacketHandler(PacketType.DirPlacesQuery, HandleDirPlacesQuery); 5023 AddLocalPacketHandler(PacketType.DirPlacesQuery, HandleDirPlacesQuery);
@@ -5050,6 +5117,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5050 (x.CameraLeftAxis != lastarg.CameraLeftAxis) || 5117 (x.CameraLeftAxis != lastarg.CameraLeftAxis) ||
5051 (x.CameraUpAxis != lastarg.CameraUpAxis) || 5118 (x.CameraUpAxis != lastarg.CameraUpAxis) ||
5052 (x.ControlFlags != lastarg.ControlFlags) || 5119 (x.ControlFlags != lastarg.ControlFlags) ||
5120 (x.ControlFlags != 0) ||
5053 (x.Far != lastarg.Far) || 5121 (x.Far != lastarg.Far) ||
5054 (x.Flags != lastarg.Flags) || 5122 (x.Flags != lastarg.Flags) ||
5055 (x.State != lastarg.State) || 5123 (x.State != lastarg.State) ||
@@ -5423,7 +5491,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5423 args.Channel = ch; 5491 args.Channel = ch;
5424 args.From = String.Empty; 5492 args.From = String.Empty;
5425 args.Message = Utils.BytesToString(msg); 5493 args.Message = Utils.BytesToString(msg);
5426 args.Type = ChatTypeEnum.Shout; 5494 args.Type = ChatTypeEnum.Region; //Behaviour in SL is that the response can be heard from any distance
5427 args.Position = new Vector3(); 5495 args.Position = new Vector3();
5428 args.Scene = Scene; 5496 args.Scene = Scene;
5429 args.Sender = this; 5497 args.Sender = this;
@@ -9467,6 +9535,37 @@ namespace OpenSim.Region.ClientStack.LindenUDP
9467 { 9535 {
9468 return true; 9536 return true;
9469 } 9537 }
9538
9539 private bool HandleCreateNewOutfitAttachments(IClientAPI sender, Packet Pack)
9540 {
9541 CreateNewOutfitAttachmentsPacket packet = (CreateNewOutfitAttachmentsPacket)Pack;
9542
9543 #region Packet Session and User Check
9544 if (m_checkPackets)
9545 {
9546 if (packet.AgentData.SessionID != SessionId ||
9547 packet.AgentData.AgentID != AgentId)
9548 return true;
9549 }
9550 #endregion
9551 MoveItemsAndLeaveCopy handlerMoveItemsAndLeaveCopy = null;
9552 List<InventoryItemBase> items = new List<InventoryItemBase>();
9553 foreach (CreateNewOutfitAttachmentsPacket.ObjectDataBlock n in packet.ObjectData)
9554 {
9555 InventoryItemBase b = new InventoryItemBase();
9556 b.ID = n.OldItemID;
9557 b.Folder = n.OldFolderID;
9558 items.Add(b);
9559 }
9560
9561 handlerMoveItemsAndLeaveCopy = OnMoveItemsAndLeaveCopy;
9562 if (handlerMoveItemsAndLeaveCopy != null)
9563 {
9564 handlerMoveItemsAndLeaveCopy(this, items, packet.HeaderData.NewFolderID);
9565 }
9566
9567 return true;
9568 }
9470 9569
9471 private bool HandleAgentHeightWidth(IClientAPI sender, Packet Pack) 9570 private bool HandleAgentHeightWidth(IClientAPI sender, Packet Pack)
9472 { 9571 {
@@ -10465,11 +10564,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP
10465 10564
10466 StartLure handlerStartLure = OnStartLure; 10565 StartLure handlerStartLure = OnStartLure;
10467 if (handlerStartLure != null) 10566 if (handlerStartLure != null)
10468 handlerStartLure(startLureRequest.Info.LureType, 10567 {
10469 Utils.BytesToString( 10568 for (int i = 0 ; i < startLureRequest.TargetData.Length ; i++)
10470 startLureRequest.Info.Message), 10569 {
10471 startLureRequest.TargetData[0].TargetID, 10570 handlerStartLure(startLureRequest.Info.LureType,
10472 this); 10571 Utils.BytesToString(
10572 startLureRequest.Info.Message),
10573 startLureRequest.TargetData[i].TargetID,
10574 this);
10575 }
10576 }
10473 return true; 10577 return true;
10474 } 10578 }
10475 private bool HandleTeleportLureRequest(IClientAPI sender, Packet Pack) 10579 private bool HandleTeleportLureRequest(IClientAPI sender, Packet Pack)
@@ -10964,7 +11068,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
10964 { 11068 {
10965 // It's a ghost! tell the client to delete it from view. 11069 // It's a ghost! tell the client to delete it from view.
10966 simClient.SendKillObject(Scene.RegionInfo.RegionHandle, 11070 simClient.SendKillObject(Scene.RegionInfo.RegionHandle,
10967 localId); 11071 new List<uint>() { localId });
10968 } 11072 }
10969 else 11073 else
10970 { 11074 {
@@ -11337,22 +11441,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11337 /// <param name="Pack">OpenMetaverse.packet</param> 11441 /// <param name="Pack">OpenMetaverse.packet</param>
11338 public void ProcessInPacket(Packet packet) 11442 public void ProcessInPacket(Packet packet)
11339 { 11443 {
11340 if (m_debugPacketLevel > 0) 11444 if (m_debugPacketLevel >= 255)
11341 { 11445 m_log.DebugFormat("[CLIENT]: Packet IN {0}", packet.Type);
11342 bool outputPacket = true;
11343
11344 if (m_debugPacketLevel <= 255 && packet.Type == PacketType.AgentUpdate)
11345 outputPacket = false;
11346
11347 if (m_debugPacketLevel <= 200 && packet.Type == PacketType.RequestImage)
11348 outputPacket = false;
11349
11350 if (m_debugPacketLevel <= 100 && (packet.Type == PacketType.ViewerEffect || packet.Type == PacketType.AgentAnimation))
11351 outputPacket = false;
11352
11353 if (outputPacket)
11354 m_log.DebugFormat("[CLIENT]: Packet IN {0}", packet.Type);
11355 }
11356 11446
11357 if (!ProcessPacketMethod(packet)) 11447 if (!ProcessPacketMethod(packet))
11358 m_log.Warn("[CLIENT]: unhandled packet " + packet.Type); 11448 m_log.Warn("[CLIENT]: unhandled packet " + packet.Type);
@@ -11594,7 +11684,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11594 11684
11595// m_log.DebugFormat("[CLIENT]: {0} requesting asset {1}", Name, requestID); 11685// m_log.DebugFormat("[CLIENT]: {0} requesting asset {1}", Name, requestID);
11596 11686
11687
11688 //Note, the bool returned from the below function is useless since it is always false.
11597 m_assetService.Get(requestID.ToString(), transferRequest, AssetReceived); 11689 m_assetService.Get(requestID.ToString(), transferRequest, AssetReceived);
11690
11598 } 11691 }
11599 11692
11600 /// <summary> 11693 /// <summary>
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs
index e02783a..5aa9b40 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs
@@ -149,6 +149,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
149 149
150 private int m_defaultRTO = 3000; 150 private int m_defaultRTO = 3000;
151 private int m_maxRTO = 60000; 151 private int m_maxRTO = 60000;
152 public bool m_deliverPackets = true;
152 153
153 /// <summary> 154 /// <summary>
154 /// Default constructor 155 /// Default constructor
@@ -415,6 +416,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
415 if (category >= 0 && category < m_packetOutboxes.Length) 416 if (category >= 0 && category < m_packetOutboxes.Length)
416 { 417 {
417 OpenSim.Framework.LocklessQueue<OutgoingPacket> queue = m_packetOutboxes[category]; 418 OpenSim.Framework.LocklessQueue<OutgoingPacket> queue = m_packetOutboxes[category];
419
420 if (m_deliverPackets == false)
421 {
422 queue.Enqueue(packet);
423 return true;
424 }
425
418 TokenBucket bucket = m_throttleCategories[category]; 426 TokenBucket bucket = m_throttleCategories[category];
419 427
420 if (!forceQueue && bucket.RemoveTokens(packet.Buffer.DataLength)) 428 if (!forceQueue && bucket.RemoveTokens(packet.Buffer.DataLength))
@@ -451,6 +459,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
451 /// <returns>True if any packets were sent, otherwise false</returns> 459 /// <returns>True if any packets were sent, otherwise false</returns>
452 public bool DequeueOutgoing() 460 public bool DequeueOutgoing()
453 { 461 {
462 if (m_deliverPackets == false) return false;
463
454 OutgoingPacket packet; 464 OutgoingPacket packet;
455 OpenSim.Framework.LocklessQueue<OutgoingPacket> queue; 465 OpenSim.Framework.LocklessQueue<OutgoingPacket> queue;
456 TokenBucket bucket; 466 TokenBucket bucket;
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
index 149ae9e..7396c2d 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
@@ -952,7 +952,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
952 if (m_scene.TryGetClient(udpClient.AgentID, out client)) 952 if (m_scene.TryGetClient(udpClient.AgentID, out client))
953 { 953 {
954 client.IsLoggingOut = true; 954 client.IsLoggingOut = true;
955 client.Close(); 955 client.Close(false);
956 } 956 }
957 } 957 }
958 958
@@ -964,6 +964,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
964 964
965 while (base.IsRunning) 965 while (base.IsRunning)
966 { 966 {
967 m_scene.ThreadAlive(1);
967 try 968 try
968 { 969 {
969 IncomingPacket incomingPacket = null; 970 IncomingPacket incomingPacket = null;
@@ -1006,6 +1007,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1006 1007
1007 while (base.IsRunning) 1008 while (base.IsRunning)
1008 { 1009 {
1010 m_scene.ThreadAlive(2);
1009 try 1011 try
1010 { 1012 {
1011 m_packetSent = false; 1013 m_packetSent = false;
diff --git a/OpenSim/Region/ClientStack/LindenUDP/TokenBucket.cs b/OpenSim/Region/ClientStack/LindenUDP/TokenBucket.cs
index bdbd284..91e3d20 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/TokenBucket.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/TokenBucket.cs
@@ -133,7 +133,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
133 this.parent = parent; 133 this.parent = parent;
134 MaxBurst = maxBurst; 134 MaxBurst = maxBurst;
135 DripRate = dripRate; 135 DripRate = dripRate;
136 lastDrip = Environment.TickCount & Int32.MaxValue; 136 lastDrip = Environment.TickCount;
137 } 137 }
138 138
139 /// <summary> 139 /// <summary>
@@ -144,40 +144,30 @@ namespace OpenSim.Region.ClientStack.LindenUDP
144 /// the bucket, otherwise false</returns> 144 /// the bucket, otherwise false</returns>
145 public bool RemoveTokens(int amount) 145 public bool RemoveTokens(int amount)
146 { 146 {
147 bool dummy;
148 return RemoveTokens(amount, out dummy);
149 }
150
151 /// <summary>
152 /// Remove a given number of tokens from the bucket
153 /// </summary>
154 /// <param name="amount">Number of tokens to remove from the bucket</param>
155 /// <param name="dripSucceeded">True if tokens were added to the bucket
156 /// during this call, otherwise false</param>
157 /// <returns>True if the requested number of tokens were removed from
158 /// the bucket, otherwise false</returns>
159 public bool RemoveTokens(int amount, out bool dripSucceeded)
160 {
161 if (maxBurst == 0) 147 if (maxBurst == 0)
162 { 148 {
163 dripSucceeded = true;
164 return true; 149 return true;
165 } 150 }
166 151
167 dripSucceeded = Drip(); 152 if (amount > maxBurst)
168
169 if (content - amount >= 0)
170 { 153 {
171 if (parent != null && !parent.RemoveTokens(amount)) 154 throw new Exception("amount " + amount + " exceeds maxBurst " + maxBurst);
172 return false; 155 }
173 156
174 content -= amount; 157 Drip();
175 return true; 158
159 if (content < amount)
160 {
161 return false;
176 } 162 }
177 else 163
164 if (parent != null && !parent.RemoveTokens(amount))
178 { 165 {
179 return false; 166 return false;
180 } 167 }
168
169 content -= amount;
170 return true;
181 } 171 }
182 172
183 /// <summary> 173 /// <summary>
@@ -193,25 +183,23 @@ namespace OpenSim.Region.ClientStack.LindenUDP
193 content = maxBurst; 183 content = maxBurst;
194 return true; 184 return true;
195 } 185 }
196 else
197 {
198 int now = Environment.TickCount & Int32.MaxValue;
199 int deltaMS = now - lastDrip;
200 186
201 if (deltaMS <= 0) 187 int now = Environment.TickCount;
202 { 188 int deltaMS = now - lastDrip;
203 if (deltaMS < 0) 189 lastDrip = now;
204 lastDrip = now;
205 return false;
206 }
207 190
208 int dripAmount = deltaMS * tokensPerMS; 191 if (deltaMS <= 0)
209 192 {
210 content = Math.Min(content + dripAmount, maxBurst); 193 return false;
211 lastDrip = now; 194 }
212 195
213 return true; 196 long dripAmount = (long)deltaMS * (long)tokensPerMS + (long)content;
197 if (dripAmount > maxBurst)
198 {
199 dripAmount = maxBurst;
214 } 200 }
201 content = (int)dripAmount;
202 return true;
215 } 203 }
216 } 204 }
217} 205}