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.cs526
-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/OpenSimUDPBase.cs4
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/TokenBucket.cs71
6 files changed, 378 insertions, 240 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 8de31d7..5b2484d 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
@@ -157,6 +157,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
157 public event RequestTaskInventory OnRequestTaskInventory; 157 public event RequestTaskInventory OnRequestTaskInventory;
158 public event UpdateInventoryItem OnUpdateInventoryItem; 158 public event UpdateInventoryItem OnUpdateInventoryItem;
159 public event CopyInventoryItem OnCopyInventoryItem; 159 public event CopyInventoryItem OnCopyInventoryItem;
160 public event MoveItemsAndLeaveCopy OnMoveItemsAndLeaveCopy;
160 public event MoveInventoryItem OnMoveInventoryItem; 161 public event MoveInventoryItem OnMoveInventoryItem;
161 public event RemoveInventoryItem OnRemoveInventoryItem; 162 public event RemoveInventoryItem OnRemoveInventoryItem;
162 public event RemoveInventoryFolder OnRemoveInventoryFolder; 163 public event RemoveInventoryFolder OnRemoveInventoryFolder;
@@ -400,7 +401,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
400 /// thread servicing the m_primFullUpdates queue after a kill. If this happens the object persists as an 401 /// thread servicing the m_primFullUpdates queue after a kill. If this happens the object persists as an
401 /// ownerless phantom. 402 /// ownerless phantom.
402 /// 403 ///
403 /// All manipulation of this set has to occur under a lock 404 /// All manipulation of this set has to occur under an m_entityUpdates.SyncRoot lock
404 /// 405 ///
405 /// </value> 406 /// </value>
406 protected HashSet<uint> m_killRecord; 407 protected HashSet<uint> m_killRecord;
@@ -408,6 +409,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
408// protected HashSet<uint> m_attachmentsSent; 409// protected HashSet<uint> m_attachmentsSent;
409 410
410 private int m_moneyBalance; 411 private int m_moneyBalance;
412 private bool m_deliverPackets = true;
411 private int m_animationSequenceNumber = 1; 413 private int m_animationSequenceNumber = 1;
412 private bool m_SendLogoutPacketWhenClosing = true; 414 private bool m_SendLogoutPacketWhenClosing = true;
413 private AgentUpdateArgs lastarg; 415 private AgentUpdateArgs lastarg;
@@ -451,6 +453,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
451 get { return m_startpos; } 453 get { return m_startpos; }
452 set { m_startpos = value; } 454 set { m_startpos = value; }
453 } 455 }
456 public bool DeliverPackets
457 {
458 get { return m_deliverPackets; }
459 set {
460 m_deliverPackets = value;
461 m_udpClient.m_deliverPackets = value;
462 }
463 }
454 public UUID AgentId { get { return m_agentId; } } 464 public UUID AgentId { get { return m_agentId; } }
455 public UUID ActiveGroupId { get { return m_activeGroupID; } } 465 public UUID ActiveGroupId { get { return m_activeGroupID; } }
456 public string ActiveGroupName { get { return m_activeGroupName; } } 466 public string ActiveGroupName { get { return m_activeGroupName; } }
@@ -549,18 +559,30 @@ namespace OpenSim.Region.ClientStack.LindenUDP
549 559
550 #region Client Methods 560 #region Client Methods
551 561
562
552 /// <summary> 563 /// <summary>
553 /// Shut down the client view 564 /// Shut down the client view
554 /// </summary> 565 /// </summary>
555 public void Close() 566 public void Close()
556 { 567 {
568 Close(true);
569 }
570
571 /// <summary>
572 /// Shut down the client view
573 /// </summary>
574 public void Close(bool sendStop)
575 {
557 m_log.DebugFormat( 576 m_log.DebugFormat(
558 "[CLIENT]: Close has been called for {0} attached to scene {1}", 577 "[CLIENT]: Close has been called for {0} attached to scene {1}",
559 Name, m_scene.RegionInfo.RegionName); 578 Name, m_scene.RegionInfo.RegionName);
560 579
561 // Send the STOP packet 580 if (sendStop)
562 DisableSimulatorPacket disable = (DisableSimulatorPacket)PacketPool.Instance.GetPacket(PacketType.DisableSimulator); 581 {
563 OutPacket(disable, ThrottleOutPacketType.Unknown); 582 // Send the STOP packet
583 DisableSimulatorPacket disable = (DisableSimulatorPacket)PacketPool.Instance.GetPacket(PacketType.DisableSimulator);
584 OutPacket(disable, ThrottleOutPacketType.Unknown);
585 }
564 586
565 IsActive = false; 587 IsActive = false;
566 588
@@ -841,7 +863,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
841 reply.ChatData.OwnerID = fromAgentID; 863 reply.ChatData.OwnerID = fromAgentID;
842 reply.ChatData.SourceID = fromAgentID; 864 reply.ChatData.SourceID = fromAgentID;
843 865
844 OutPacket(reply, ThrottleOutPacketType.Task); 866 OutPacket(reply, ThrottleOutPacketType.Unknown);
845 } 867 }
846 868
847 /// <summary> 869 /// <summary>
@@ -1127,6 +1149,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1127 public virtual void SendLayerData(float[] map) 1149 public virtual void SendLayerData(float[] map)
1128 { 1150 {
1129 Util.FireAndForget(DoSendLayerData, map); 1151 Util.FireAndForget(DoSendLayerData, map);
1152
1153 // Send it sync, and async. It's not that much data
1154 // and it improves user experience just so much!
1155 DoSendLayerData(map);
1130 } 1156 }
1131 1157
1132 /// <summary> 1158 /// <summary>
@@ -1139,16 +1165,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1139 1165
1140 try 1166 try
1141 { 1167 {
1142 //for (int y = 0; y < 16; y++) 1168 for (int y = 0; y < 16; y++)
1143 //{ 1169 {
1144 // for (int x = 0; x < 16; x++) 1170 for (int x = 0; x < 16; x+=4)
1145 // { 1171 {
1146 // SendLayerData(x, y, map); 1172 SendLayerPacket(x, y, map);
1147 // } 1173 }
1148 //} 1174 }
1149
1150 // Send LayerData in a spiral pattern. Fun!
1151 SendLayerTopRight(map, 0, 0, 15, 15);
1152 } 1175 }
1153 catch (Exception e) 1176 catch (Exception e)
1154 { 1177 {
@@ -1156,51 +1179,35 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1156 } 1179 }
1157 } 1180 }
1158 1181
1159 private void SendLayerTopRight(float[] map, int x1, int y1, int x2, int y2)
1160 {
1161 // Row
1162 for (int i = x1; i <= x2; i++)
1163 SendLayerData(i, y1, map);
1164
1165 // Column
1166 for (int j = y1 + 1; j <= y2; j++)
1167 SendLayerData(x2, j, map);
1168
1169 if (x2 - x1 > 0)
1170 SendLayerBottomLeft(map, x1, y1 + 1, x2 - 1, y2);
1171 }
1172
1173 void SendLayerBottomLeft(float[] map, int x1, int y1, int x2, int y2)
1174 {
1175 // Row in reverse
1176 for (int i = x2; i >= x1; i--)
1177 SendLayerData(i, y2, map);
1178
1179 // Column in reverse
1180 for (int j = y2 - 1; j >= y1; j--)
1181 SendLayerData(x1, j, map);
1182
1183 if (x2 - x1 > 0)
1184 SendLayerTopRight(map, x1 + 1, y1, x2, y2 - 1);
1185 }
1186
1187 /// <summary> 1182 /// <summary>
1188 /// Sends a set of four patches (x, x+1, ..., x+3) to the client 1183 /// Sends a set of four patches (x, x+1, ..., x+3) to the client
1189 /// </summary> 1184 /// </summary>
1190 /// <param name="map">heightmap</param> 1185 /// <param name="map">heightmap</param>
1191 /// <param name="px">X coordinate for patches 0..12</param> 1186 /// <param name="px">X coordinate for patches 0..12</param>
1192 /// <param name="py">Y coordinate for patches 0..15</param> 1187 /// <param name="py">Y coordinate for patches 0..15</param>
1193 // private void SendLayerPacket(float[] map, int y, int x) 1188 private void SendLayerPacket(int x, int y, float[] map)
1194 // { 1189 {
1195 // int[] patches = new int[4]; 1190 int[] patches = new int[4];
1196 // patches[0] = x + 0 + y * 16; 1191 patches[0] = x + 0 + y * 16;
1197 // patches[1] = x + 1 + y * 16; 1192 patches[1] = x + 1 + y * 16;
1198 // patches[2] = x + 2 + y * 16; 1193 patches[2] = x + 2 + y * 16;
1199 // patches[3] = x + 3 + y * 16; 1194 patches[3] = x + 3 + y * 16;
1200 1195
1201 // Packet layerpack = LLClientView.TerrainManager.CreateLandPacket(map, patches); 1196 float[] heightmap = (map.Length == 65536) ?
1202 // OutPacket(layerpack, ThrottleOutPacketType.Land); 1197 map :
1203 // } 1198 LLHeightFieldMoronize(map);
1199
1200 try
1201 {
1202 Packet layerpack = TerrainCompressor.CreateLandPacket(heightmap, patches);
1203 OutPacket(layerpack, ThrottleOutPacketType.Land);
1204 }
1205 catch
1206 {
1207 for (int px = x ; px < x + 4 ; px++)
1208 SendLayerData(px, y, map);
1209 }
1210 }
1204 1211
1205 /// <summary> 1212 /// <summary>
1206 /// Sends a specified patch to a client 1213 /// Sends a specified patch to a client
@@ -1220,7 +1227,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1220 LayerDataPacket layerpack = TerrainCompressor.CreateLandPacket(heightmap, patches); 1227 LayerDataPacket layerpack = TerrainCompressor.CreateLandPacket(heightmap, patches);
1221 layerpack.Header.Reliable = true; 1228 layerpack.Header.Reliable = true;
1222 1229
1223 OutPacket(layerpack, ThrottleOutPacketType.Land); 1230 OutPacket(layerpack, ThrottleOutPacketType.Task);
1224 } 1231 }
1225 catch (Exception e) 1232 catch (Exception e)
1226 { 1233 {
@@ -1581,37 +1588,49 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1581 OutPacket(pc, ThrottleOutPacketType.Unknown); 1588 OutPacket(pc, ThrottleOutPacketType.Unknown);
1582 } 1589 }
1583 1590
1584 public void SendKillObject(ulong regionHandle, uint localID) 1591 public void SendKillObject(ulong regionHandle, List<uint> localIDs)
1585 { 1592 {
1586// m_log.DebugFormat("[CLIENT]: Sending KillObjectPacket to {0} for {1} in {2}", Name, localID, regionHandle); 1593// m_log.DebugFormat("[CLIENT]: Sending KillObjectPacket to {0} for {1} in {2}", Name, localID, regionHandle);
1587 1594
1588 KillObjectPacket kill = (KillObjectPacket)PacketPool.Instance.GetPacket(PacketType.KillObject); 1595 KillObjectPacket kill = (KillObjectPacket)PacketPool.Instance.GetPacket(PacketType.KillObject);
1589 // TODO: don't create new blocks if recycling an old packet 1596 // TODO: don't create new blocks if recycling an old packet
1590 kill.ObjectData = new KillObjectPacket.ObjectDataBlock[1]; 1597 kill.ObjectData = new KillObjectPacket.ObjectDataBlock[localIDs.Count];
1591 kill.ObjectData[0] = new KillObjectPacket.ObjectDataBlock(); 1598 for (int i = 0 ; i < localIDs.Count ; i++ )
1592 kill.ObjectData[0].ID = localID; 1599 {
1600 kill.ObjectData[i] = new KillObjectPacket.ObjectDataBlock();
1601 kill.ObjectData[i].ID = localIDs[i];
1602 }
1593 kill.Header.Reliable = true; 1603 kill.Header.Reliable = true;
1594 kill.Header.Zerocoded = true; 1604 kill.Header.Zerocoded = true;
1595 1605
1596 if (m_scene.GetScenePresence(localID) == null) 1606 lock (m_killRecord)
1597 { 1607 {
1598 // We must lock for both manipulating the kill record and sending the packet, in order to avoid a race 1608 if (localIDs.Count == 1)
1599 // condition where a kill can be processed before an out-of-date update for the same object.
1600 lock (m_killRecord)
1601 { 1609 {
1602 m_killRecord.Add(localID); 1610 if (m_scene.GetScenePresence(localIDs[0]) != null)
1603 1611 {
1604 // The throttle queue used here must match that being used for updates. Otherwise, there is a 1612 OutPacket(kill, ThrottleOutPacketType.State);
1605 // chance that a kill packet put on a separate queue will be sent to the client before an existing 1613 return;
1606 // update packet on another queue. Receiving updates after kills results in unowned and undeletable 1614 }
1607 // scene objects in a viewer until that viewer is relogged in. 1615 m_killRecord.Add(localIDs[0]);
1608 OutPacket(kill, ThrottleOutPacketType.Task); 1616 }
1617 else
1618 {
1619 lock (m_entityUpdates.SyncRoot)
1620 {
1621 foreach (uint localID in localIDs)
1622 m_killRecord.Add(localID);
1623 }
1609 } 1624 }
1610 } 1625 }
1611 else 1626
1612 { 1627 // The throttle queue used here must match that being used for
1613 OutPacket(kill, ThrottleOutPacketType.State); 1628 // updates. Otherwise, there is a chance that a kill packet put
1614 } 1629 // on a separate queue will be sent to the client before an
1630 // existing update packet on another queue. Receiving updates
1631 // after kills results in unowned and undeletable
1632 // scene objects in a viewer until that viewer is relogged in.
1633 OutPacket(kill, ThrottleOutPacketType.Task);
1615 } 1634 }
1616 1635
1617 /// <summary> 1636 /// <summary>
@@ -2324,6 +2343,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2324 OutPacket(sound, ThrottleOutPacketType.Task); 2343 OutPacket(sound, ThrottleOutPacketType.Task);
2325 } 2344 }
2326 2345
2346 public void SendTransferAbort(TransferRequestPacket transferRequest)
2347 {
2348 TransferAbortPacket abort = (TransferAbortPacket)PacketPool.Instance.GetPacket(PacketType.TransferAbort);
2349 abort.TransferInfo.TransferID = transferRequest.TransferInfo.TransferID;
2350 abort.TransferInfo.ChannelType = transferRequest.TransferInfo.ChannelType;
2351 m_log.Debug("[Assets] Aborting transfer; asset request failed");
2352 OutPacket(abort, ThrottleOutPacketType.Task);
2353 }
2354
2327 public void SendTriggeredSound(UUID soundID, UUID ownerID, UUID objectID, UUID parentID, ulong handle, Vector3 position, float gain) 2355 public void SendTriggeredSound(UUID soundID, UUID ownerID, UUID objectID, UUID parentID, ulong handle, Vector3 position, float gain)
2328 { 2356 {
2329 SoundTriggerPacket sound = (SoundTriggerPacket)PacketPool.Instance.GetPacket(PacketType.SoundTrigger); 2357 SoundTriggerPacket sound = (SoundTriggerPacket)PacketPool.Instance.GetPacket(PacketType.SoundTrigger);
@@ -3627,7 +3655,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3627 /// </summary> 3655 /// </summary>
3628 public void SendPrimUpdate(ISceneEntity entity, PrimUpdateFlags updateFlags) 3656 public void SendPrimUpdate(ISceneEntity entity, PrimUpdateFlags updateFlags)
3629 { 3657 {
3630 //double priority = m_prioritizer.GetUpdatePriority(this, entity); 3658 if (entity is SceneObjectPart)
3659 {
3660 SceneObjectPart e = (SceneObjectPart)entity;
3661 SceneObjectGroup g = e.ParentGroup;
3662 if (g.RootPart.Shape.State > 30) // HUD
3663 if (g.OwnerID != AgentId)
3664 return; // Don't send updates for other people's HUDs
3665 }
3666
3631 uint priority = m_prioritizer.GetUpdatePriority(this, entity); 3667 uint priority = m_prioritizer.GetUpdatePriority(this, entity);
3632 3668
3633 lock (m_entityUpdates.SyncRoot) 3669 lock (m_entityUpdates.SyncRoot)
@@ -3673,9 +3709,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3673//</MIC> 3709//</MIC>
3674 // We must lock for both manipulating the kill record and sending the packet, in order to avoid a race 3710 // We must lock for both manipulating the kill record and sending the packet, in order to avoid a race
3675 // condition where a kill can be processed before an out-of-date update for the same object. 3711 // condition where a kill can be processed before an out-of-date update for the same object.
3712 float avgTimeDilation = 1.0f;
3713
3676 lock (m_killRecord) 3714 lock (m_killRecord)
3677 { 3715 {
3678 float avgTimeDilation = 1.0f;
3679 EntityUpdate update; 3716 EntityUpdate update;
3680 Int32 timeinqueue; // this is just debugging code & can be dropped later 3717 Int32 timeinqueue; // this is just debugging code & can be dropped later
3681 3718
@@ -3690,7 +3727,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3690 if (update.Entity is SceneObjectPart) 3727 if (update.Entity is SceneObjectPart)
3691 { 3728 {
3692 SceneObjectPart part = (SceneObjectPart)update.Entity; 3729 SceneObjectPart part = (SceneObjectPart)update.Entity;
3693 3730
3694 // Please do not remove this unless you can demonstrate on the OpenSim mailing list that a client 3731 // Please do not remove this unless you can demonstrate on the OpenSim mailing list that a client
3695 // will never receive an update after a prim kill. Even then, keeping the kill record may be a good 3732 // will never receive an update after a prim kill. Even then, keeping the kill record may be a good
3696 // safety measure. 3733 // safety measure.
@@ -3701,14 +3738,45 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3701 // 3738 //
3702 // This doesn't appear to apply to child prims - a client will happily ignore these updates 3739 // This doesn't appear to apply to child prims - a client will happily ignore these updates
3703 // after the root prim has been deleted. 3740 // after the root prim has been deleted.
3704 if (m_killRecord.Contains(part.LocalId)) 3741 lock (m_killRecord)
3705 { 3742 {
3706 // m_log.WarnFormat( 3743 if (m_killRecord.Contains(part.LocalId))
3707 // "[CLIENT]: Preventing update for prim with local id {0} after client for user {1} told it was deleted", 3744 continue;
3708 // part.LocalId, Name); 3745 if (m_killRecord.Contains(part.ParentGroup.RootPart.LocalId))
3746 continue;
3747 }
3748
3749 if (part.ParentGroup.IsDeleted)
3709 continue; 3750 continue;
3710 } 3751
3711 3752 if (part.ParentGroup.IsAttachment)
3753 { // Someone else's HUD, why are we getting these?
3754 if (part.ParentGroup.OwnerID != AgentId &&
3755 part.ParentGroup.RootPart.Shape.State >= 30)
3756 continue;
3757 ScenePresence sp;
3758 // Owner is not in the sim, don't update it to
3759 // anyone
3760 if (!m_scene.TryGetScenePresence(part.OwnerID, out sp))
3761 continue;
3762
3763 List<SceneObjectGroup> atts = sp.Attachments;
3764 bool found = false;
3765 foreach (SceneObjectGroup att in atts)
3766 {
3767 if (att == part.ParentGroup)
3768 {
3769 found = true;
3770 break;
3771 }
3772 }
3773
3774 // It's an attachment of a valid avatar, but
3775 // doesn't seem to be attached, skip
3776 if (!found)
3777 continue;
3778 }
3779
3712 if (part.ParentGroup.IsAttachment && m_disableFacelights) 3780 if (part.ParentGroup.IsAttachment && m_disableFacelights)
3713 { 3781 {
3714 if (part.ParentGroup.RootPart.Shape.State != (byte)AttachmentPoint.LeftHand && 3782 if (part.ParentGroup.RootPart.Shape.State != (byte)AttachmentPoint.LeftHand &&
@@ -3718,22 +3786,22 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3718 } 3786 }
3719 } 3787 }
3720 } 3788 }
3721 3789
3722 ++updatesThisCall; 3790 ++updatesThisCall;
3723 3791
3724 #region UpdateFlags to packet type conversion 3792 #region UpdateFlags to packet type conversion
3725 3793
3726 PrimUpdateFlags updateFlags = update.Flags; 3794 PrimUpdateFlags updateFlags = update.Flags;
3727 3795
3728 bool canUseCompressed = true; 3796 bool canUseCompressed = true;
3729 bool canUseImproved = true; 3797 bool canUseImproved = true;
3730 3798
3731 // Compressed object updates only make sense for LL primitives 3799 // Compressed object updates only make sense for LL primitives
3732 if (!(update.Entity is SceneObjectPart)) 3800 if (!(update.Entity is SceneObjectPart))
3733 { 3801 {
3734 canUseCompressed = false; 3802 canUseCompressed = false;
3735 } 3803 }
3736 3804
3737 if (updateFlags.HasFlag(PrimUpdateFlags.FullUpdate)) 3805 if (updateFlags.HasFlag(PrimUpdateFlags.FullUpdate))
3738 { 3806 {
3739 canUseCompressed = false; 3807 canUseCompressed = false;
@@ -3746,9 +3814,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3746 updateFlags.HasFlag(PrimUpdateFlags.CollisionPlane) || 3814 updateFlags.HasFlag(PrimUpdateFlags.CollisionPlane) ||
3747 updateFlags.HasFlag(PrimUpdateFlags.Joint)) 3815 updateFlags.HasFlag(PrimUpdateFlags.Joint))
3748 { 3816 {
3749 canUseCompressed = false; 3817 if (update.Entity is ScenePresence)
3818 {
3819 objectUpdateBlocks.Value.Add(CreateAvatarUpdateBlock((ScenePresence)update.Entity));
3820 }
3821 else
3822 {
3823 objectUpdateBlocks.Value.Add(CreatePrimUpdateBlock((SceneObjectPart)update.Entity, this.m_agentId));
3824 }
3750 } 3825 }
3751 3826
3752 if (updateFlags.HasFlag(PrimUpdateFlags.PrimFlags) || 3827 if (updateFlags.HasFlag(PrimUpdateFlags.PrimFlags) ||
3753 updateFlags.HasFlag(PrimUpdateFlags.ParentID) || 3828 updateFlags.HasFlag(PrimUpdateFlags.ParentID) ||
3754 updateFlags.HasFlag(PrimUpdateFlags.Scale) || 3829 updateFlags.HasFlag(PrimUpdateFlags.Scale) ||
@@ -3767,14 +3842,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3767 canUseImproved = false; 3842 canUseImproved = false;
3768 } 3843 }
3769 } 3844 }
3770 3845
3771 #endregion UpdateFlags to packet type conversion 3846 #endregion UpdateFlags to packet type conversion
3772 3847
3773 #region Block Construction 3848 #region Block Construction
3774 3849
3775 // TODO: Remove this once we can build compressed updates 3850 // TODO: Remove this once we can build compressed updates
3776 canUseCompressed = false; 3851 canUseCompressed = false;
3777 3852
3778 if (!canUseImproved && !canUseCompressed) 3853 if (!canUseImproved && !canUseCompressed)
3779 { 3854 {
3780 if (update.Entity is ScenePresence) 3855 if (update.Entity is ScenePresence)
@@ -3783,7 +3858,36 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3783 } 3858 }
3784 else 3859 else
3785 { 3860 {
3786 objectUpdateBlocks.Value.Add(CreatePrimUpdateBlock((SceneObjectPart)update.Entity, this.m_agentId)); 3861 // if (update.Entity is SceneObjectPart && ((SceneObjectPart)update.Entity).IsAttachment)
3862 // {
3863 // SceneObjectPart sop = (SceneObjectPart)update.Entity;
3864 // string text = sop.Text;
3865 // if (text.IndexOf("\n") >= 0)
3866 // text = text.Remove(text.IndexOf("\n"));
3867 //
3868 // if (m_attachmentsSent.Contains(sop.ParentID))
3869 // {
3870 //// m_log.DebugFormat(
3871 //// "[CLIENT]: Sending full info about attached prim {0} text {1}",
3872 //// sop.LocalId, text);
3873 //
3874 // objectUpdateBlocks.Value.Add(CreatePrimUpdateBlock(sop, this.m_agentId));
3875 //
3876 // m_attachmentsSent.Add(sop.LocalId);
3877 // }
3878 // else
3879 // {
3880 // m_log.DebugFormat(
3881 // "[CLIENT]: Requeueing full update of prim {0} text {1} since we haven't sent its parent {2} yet",
3882 // sop.LocalId, text, sop.ParentID);
3883 //
3884 // m_entityUpdates.Enqueue(double.MaxValue, update, sop.LocalId);
3885 // }
3886 // }
3887 // else
3888 // {
3889 objectUpdateBlocks.Value.Add(CreatePrimUpdateBlock((SceneObjectPart)update.Entity, this.m_agentId));
3890 // }
3787 } 3891 }
3788 } 3892 }
3789 else if (!canUseImproved) 3893 else if (!canUseImproved)
@@ -3799,77 +3903,74 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3799 // Everything else goes here 3903 // Everything else goes here
3800 terseUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures))); 3904 terseUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures)));
3801 } 3905 }
3802 3906
3803 #endregion Block Construction 3907 #endregion Block Construction
3804 } 3908 }
3909 }
3910
3911 #region Packet Sending
3805 3912
3806 #region Packet Sending 3913 const float TIME_DILATION = 1.0f;
3807 3914 ushort timeDilation = Utils.FloatToUInt16(avgTimeDilation, 0.0f, 1.0f);
3808 //const float TIME_DILATION = 1.0f; 3915
3916 if (terseAgentUpdateBlocks.IsValueCreated)
3917 {
3918 List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseAgentUpdateBlocks.Value;
3919
3920 ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket();
3921 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
3922 packet.RegionData.TimeDilation = timeDilation;
3923 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count];
3809 3924
3925 for (int i = 0; i < blocks.Count; i++)
3926 packet.ObjectData[i] = blocks[i];
3810 3927
3811 ushort timeDilation = Utils.FloatToUInt16(avgTimeDilation, 0.0f, 1.0f); 3928 OutPacket(packet, ThrottleOutPacketType.Unknown, true);
3929 }
3930
3931 if (objectUpdateBlocks.IsValueCreated)
3932 {
3933 List<ObjectUpdatePacket.ObjectDataBlock> blocks = objectUpdateBlocks.Value;
3812 3934
3813 if (terseAgentUpdateBlocks.IsValueCreated) 3935 ObjectUpdatePacket packet = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate);
3814 { 3936 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
3815 List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseAgentUpdateBlocks.Value; 3937 packet.RegionData.TimeDilation = timeDilation;
3938 packet.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[blocks.Count];
3816 3939
3817 ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket(); 3940 for (int i = 0; i < blocks.Count; i++)
3818 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; 3941 packet.ObjectData[i] = blocks[i];
3819 packet.RegionData.TimeDilation = timeDilation;
3820 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count];
3821 3942
3822 for (int i = 0; i < blocks.Count; i++) 3943 OutPacket(packet, ThrottleOutPacketType.Task, true);
3823 packet.ObjectData[i] = blocks[i]; 3944 }
3945
3946 if (compressedUpdateBlocks.IsValueCreated)
3947 {
3948 List<ObjectUpdateCompressedPacket.ObjectDataBlock> blocks = compressedUpdateBlocks.Value;
3949
3950 ObjectUpdateCompressedPacket packet = (ObjectUpdateCompressedPacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdateCompressed);
3951 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
3952 packet.RegionData.TimeDilation = timeDilation;
3953 packet.ObjectData = new ObjectUpdateCompressedPacket.ObjectDataBlock[blocks.Count];
3824 3954
3825 3955 for (int i = 0; i < blocks.Count; i++)
3826 OutPacket(packet, ThrottleOutPacketType.Unknown, true); 3956 packet.ObjectData[i] = blocks[i];
3827 }
3828 3957
3829 if (objectUpdateBlocks.IsValueCreated) 3958 OutPacket(packet, ThrottleOutPacketType.Task, true);
3830 { 3959 }
3831 List<ObjectUpdatePacket.ObjectDataBlock> blocks = objectUpdateBlocks.Value; 3960
3832 3961 if (terseUpdateBlocks.IsValueCreated)
3833 ObjectUpdatePacket packet = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate); 3962 {
3834 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; 3963 List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseUpdateBlocks.Value;
3835 packet.RegionData.TimeDilation = timeDilation; 3964
3836 packet.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[blocks.Count]; 3965 ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket();
3837 3966 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
3838 for (int i = 0; i < blocks.Count; i++) 3967 packet.RegionData.TimeDilation = timeDilation;
3839 packet.ObjectData[i] = blocks[i]; 3968 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count];
3840 3969
3841 OutPacket(packet, ThrottleOutPacketType.Task, true); 3970 for (int i = 0; i < blocks.Count; i++)
3842 } 3971 packet.ObjectData[i] = blocks[i];
3843 3972
3844 if (compressedUpdateBlocks.IsValueCreated) 3973 OutPacket(packet, ThrottleOutPacketType.Task, true);
3845 {
3846 List<ObjectUpdateCompressedPacket.ObjectDataBlock> blocks = compressedUpdateBlocks.Value;
3847
3848 ObjectUpdateCompressedPacket packet = (ObjectUpdateCompressedPacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdateCompressed);
3849 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
3850 packet.RegionData.TimeDilation = timeDilation;
3851 packet.ObjectData = new ObjectUpdateCompressedPacket.ObjectDataBlock[blocks.Count];
3852
3853 for (int i = 0; i < blocks.Count; i++)
3854 packet.ObjectData[i] = blocks[i];
3855
3856 OutPacket(packet, ThrottleOutPacketType.Task, true);
3857 }
3858
3859 if (terseUpdateBlocks.IsValueCreated)
3860 {
3861 List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseUpdateBlocks.Value;
3862
3863 ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket();
3864 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
3865 packet.RegionData.TimeDilation = timeDilation;
3866 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count];
3867
3868 for (int i = 0; i < blocks.Count; i++)
3869 packet.ObjectData[i] = blocks[i];
3870
3871 OutPacket(packet, ThrottleOutPacketType.Task, true);
3872 }
3873 } 3974 }
3874 3975
3875 #endregion Packet Sending 3976 #endregion Packet Sending
@@ -4133,6 +4234,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4133 { 4234 {
4134 m_propertiesPacketTimer.Stop(); 4235 m_propertiesPacketTimer.Stop();
4135 4236
4237 if (m_propertiesBlocks.Count == 0)
4238 return;
4239
4136 proper.ObjectData = new ObjectPropertiesPacket.ObjectDataBlock[m_propertiesBlocks.Count]; 4240 proper.ObjectData = new ObjectPropertiesPacket.ObjectDataBlock[m_propertiesBlocks.Count];
4137 4241
4138 int index = 0; 4242 int index = 0;
@@ -4534,14 +4638,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4534 4638
4535 if (notifyCount > 0) 4639 if (notifyCount > 0)
4536 { 4640 {
4537 if (notifyCount > 32) 4641// if (notifyCount > 32)
4538 { 4642// {
4539 m_log.InfoFormat( 4643// m_log.InfoFormat(
4540 "[LAND]: More than {0} avatars own prims on this parcel. Only sending back details of first {0}" 4644// "[LAND]: More than {0} avatars own prims on this parcel. Only sending back details of first {0}"
4541 + " - a developer might want to investigate whether this is a hard limit", 32); 4645// + " - a developer might want to investigate whether this is a hard limit", 32);
4542 4646//
4543 notifyCount = 32; 4647// notifyCount = 32;
4544 } 4648// }
4545 4649
4546 ParcelObjectOwnersReplyPacket.DataBlock[] dataBlock 4650 ParcelObjectOwnersReplyPacket.DataBlock[] dataBlock
4547 = new ParcelObjectOwnersReplyPacket.DataBlock[notifyCount]; 4651 = new ParcelObjectOwnersReplyPacket.DataBlock[notifyCount];
@@ -5049,6 +5153,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5049 AddLocalPacketHandler(PacketType.TransferAbort, HandleTransferAbort, false); 5153 AddLocalPacketHandler(PacketType.TransferAbort, HandleTransferAbort, false);
5050 AddLocalPacketHandler(PacketType.MuteListRequest, HandleMuteListRequest, false); 5154 AddLocalPacketHandler(PacketType.MuteListRequest, HandleMuteListRequest, false);
5051 AddLocalPacketHandler(PacketType.UseCircuitCode, HandleUseCircuitCode); 5155 AddLocalPacketHandler(PacketType.UseCircuitCode, HandleUseCircuitCode);
5156 AddLocalPacketHandler(PacketType.CreateNewOutfitAttachments, HandleCreateNewOutfitAttachments);
5052 AddLocalPacketHandler(PacketType.AgentHeightWidth, HandleAgentHeightWidth, false); 5157 AddLocalPacketHandler(PacketType.AgentHeightWidth, HandleAgentHeightWidth, false);
5053 AddLocalPacketHandler(PacketType.InventoryDescendents, HandleInventoryDescendents); 5158 AddLocalPacketHandler(PacketType.InventoryDescendents, HandleInventoryDescendents);
5054 AddLocalPacketHandler(PacketType.DirPlacesQuery, HandleDirPlacesQuery); 5159 AddLocalPacketHandler(PacketType.DirPlacesQuery, HandleDirPlacesQuery);
@@ -5148,6 +5253,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5148 (x.CameraLeftAxis != lastarg.CameraLeftAxis) || 5253 (x.CameraLeftAxis != lastarg.CameraLeftAxis) ||
5149 (x.CameraUpAxis != lastarg.CameraUpAxis) || 5254 (x.CameraUpAxis != lastarg.CameraUpAxis) ||
5150 (x.ControlFlags != lastarg.ControlFlags) || 5255 (x.ControlFlags != lastarg.ControlFlags) ||
5256 (x.ControlFlags != 0) ||
5151 (x.Far != lastarg.Far) || 5257 (x.Far != lastarg.Far) ||
5152 (x.Flags != lastarg.Flags) || 5258 (x.Flags != lastarg.Flags) ||
5153 (x.State != lastarg.State) || 5259 (x.State != lastarg.State) ||
@@ -5521,7 +5627,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5521 args.Channel = ch; 5627 args.Channel = ch;
5522 args.From = String.Empty; 5628 args.From = String.Empty;
5523 args.Message = Utils.BytesToString(msg); 5629 args.Message = Utils.BytesToString(msg);
5524 args.Type = ChatTypeEnum.Shout; 5630 args.Type = ChatTypeEnum.Region; //Behaviour in SL is that the response can be heard from any distance
5525 args.Position = new Vector3(); 5631 args.Position = new Vector3();
5526 args.Scene = Scene; 5632 args.Scene = Scene;
5527 args.Sender = this; 5633 args.Sender = this;
@@ -9509,7 +9615,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
9509 handlerUpdateMuteListEntry(this, UpdateMuteListEntry.MuteData.MuteID, 9615 handlerUpdateMuteListEntry(this, UpdateMuteListEntry.MuteData.MuteID,
9510 Utils.BytesToString(UpdateMuteListEntry.MuteData.MuteName), 9616 Utils.BytesToString(UpdateMuteListEntry.MuteData.MuteName),
9511 UpdateMuteListEntry.MuteData.MuteType, 9617 UpdateMuteListEntry.MuteData.MuteType,
9512 UpdateMuteListEntry.AgentData.AgentID); 9618 UpdateMuteListEntry.MuteData.MuteFlags);
9513 return true; 9619 return true;
9514 } 9620 }
9515 return false; 9621 return false;
@@ -9524,8 +9630,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
9524 { 9630 {
9525 handlerRemoveMuteListEntry(this, 9631 handlerRemoveMuteListEntry(this,
9526 RemoveMuteListEntry.MuteData.MuteID, 9632 RemoveMuteListEntry.MuteData.MuteID,
9527 Utils.BytesToString(RemoveMuteListEntry.MuteData.MuteName), 9633 Utils.BytesToString(RemoveMuteListEntry.MuteData.MuteName));
9528 RemoveMuteListEntry.AgentData.AgentID);
9529 return true; 9634 return true;
9530 } 9635 }
9531 return false; 9636 return false;
@@ -9573,6 +9678,37 @@ namespace OpenSim.Region.ClientStack.LindenUDP
9573 { 9678 {
9574 return true; 9679 return true;
9575 } 9680 }
9681
9682 private bool HandleCreateNewOutfitAttachments(IClientAPI sender, Packet Pack)
9683 {
9684 CreateNewOutfitAttachmentsPacket packet = (CreateNewOutfitAttachmentsPacket)Pack;
9685
9686 #region Packet Session and User Check
9687 if (m_checkPackets)
9688 {
9689 if (packet.AgentData.SessionID != SessionId ||
9690 packet.AgentData.AgentID != AgentId)
9691 return true;
9692 }
9693 #endregion
9694 MoveItemsAndLeaveCopy handlerMoveItemsAndLeaveCopy = null;
9695 List<InventoryItemBase> items = new List<InventoryItemBase>();
9696 foreach (CreateNewOutfitAttachmentsPacket.ObjectDataBlock n in packet.ObjectData)
9697 {
9698 InventoryItemBase b = new InventoryItemBase();
9699 b.ID = n.OldItemID;
9700 b.Folder = n.OldFolderID;
9701 items.Add(b);
9702 }
9703
9704 handlerMoveItemsAndLeaveCopy = OnMoveItemsAndLeaveCopy;
9705 if (handlerMoveItemsAndLeaveCopy != null)
9706 {
9707 handlerMoveItemsAndLeaveCopy(this, items, packet.HeaderData.NewFolderID);
9708 }
9709
9710 return true;
9711 }
9576 9712
9577 private bool HandleAgentHeightWidth(IClientAPI sender, Packet Pack) 9713 private bool HandleAgentHeightWidth(IClientAPI sender, Packet Pack)
9578 { 9714 {
@@ -9999,6 +10135,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP
9999 groupProfileReply.GroupData.MaturePublish = d.MaturePublish; 10135 groupProfileReply.GroupData.MaturePublish = d.MaturePublish;
10000 groupProfileReply.GroupData.OwnerRole = d.OwnerRole; 10136 groupProfileReply.GroupData.OwnerRole = d.OwnerRole;
10001 10137
10138 Scene scene = (Scene)m_scene;
10139 if (scene.Permissions.IsGod(sender.AgentId) && (!sender.IsGroupMember(groupProfileRequest.GroupData.GroupID)))
10140 {
10141 ScenePresence p;
10142 if (scene.TryGetScenePresence(sender.AgentId, out p))
10143 {
10144 if (p.GodLevel >= 200)
10145 {
10146 groupProfileReply.GroupData.OpenEnrollment = true;
10147 groupProfileReply.GroupData.MembershipFee = 0;
10148 }
10149 }
10150 }
10151
10002 OutPacket(groupProfileReply, ThrottleOutPacketType.Task); 10152 OutPacket(groupProfileReply, ThrottleOutPacketType.Task);
10003 } 10153 }
10004 return true; 10154 return true;
@@ -10571,11 +10721,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP
10571 10721
10572 StartLure handlerStartLure = OnStartLure; 10722 StartLure handlerStartLure = OnStartLure;
10573 if (handlerStartLure != null) 10723 if (handlerStartLure != null)
10574 handlerStartLure(startLureRequest.Info.LureType, 10724 {
10575 Utils.BytesToString( 10725 for (int i = 0 ; i < startLureRequest.TargetData.Length ; i++)
10576 startLureRequest.Info.Message), 10726 {
10577 startLureRequest.TargetData[0].TargetID, 10727 handlerStartLure(startLureRequest.Info.LureType,
10578 this); 10728 Utils.BytesToString(
10729 startLureRequest.Info.Message),
10730 startLureRequest.TargetData[i].TargetID,
10731 this);
10732 }
10733 }
10579 return true; 10734 return true;
10580 } 10735 }
10581 private bool HandleTeleportLureRequest(IClientAPI sender, Packet Pack) 10736 private bool HandleTeleportLureRequest(IClientAPI sender, Packet Pack)
@@ -11070,7 +11225,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11070 { 11225 {
11071 // It's a ghost! tell the client to delete it from view. 11226 // It's a ghost! tell the client to delete it from view.
11072 simClient.SendKillObject(Scene.RegionInfo.RegionHandle, 11227 simClient.SendKillObject(Scene.RegionInfo.RegionHandle,
11073 localId); 11228 new List<uint>() { localId });
11074 } 11229 }
11075 else 11230 else
11076 { 11231 {
@@ -11443,22 +11598,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11443 /// <param name="Pack">OpenMetaverse.packet</param> 11598 /// <param name="Pack">OpenMetaverse.packet</param>
11444 public void ProcessInPacket(Packet packet) 11599 public void ProcessInPacket(Packet packet)
11445 { 11600 {
11446 if (m_debugPacketLevel > 0) 11601 if (m_debugPacketLevel >= 255)
11447 { 11602 m_log.DebugFormat("[CLIENT]: Packet IN {0}", packet.Type);
11448 bool outputPacket = true;
11449
11450 if (m_debugPacketLevel <= 255 && packet.Type == PacketType.AgentUpdate)
11451 outputPacket = false;
11452
11453 if (m_debugPacketLevel <= 200 && packet.Type == PacketType.RequestImage)
11454 outputPacket = false;
11455
11456 if (m_debugPacketLevel <= 100 && (packet.Type == PacketType.ViewerEffect || packet.Type == PacketType.AgentAnimation))
11457 outputPacket = false;
11458
11459 if (outputPacket)
11460 m_log.DebugFormat("[CLIENT]: Packet IN {0}", packet.Type);
11461 }
11462 11603
11463 if (!ProcessPacketMethod(packet)) 11604 if (!ProcessPacketMethod(packet))
11464 m_log.Warn("[CLIENT]: unhandled packet " + packet.Type); 11605 m_log.Warn("[CLIENT]: unhandled packet " + packet.Type);
@@ -11700,7 +11841,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11700 11841
11701// m_log.DebugFormat("[CLIENT]: {0} requesting asset {1}", Name, requestID); 11842// m_log.DebugFormat("[CLIENT]: {0} requesting asset {1}", Name, requestID);
11702 11843
11844
11845 //Note, the bool returned from the below function is useless since it is always false.
11703 m_assetService.Get(requestID.ToString(), transferRequest, AssetReceived); 11846 m_assetService.Get(requestID.ToString(), transferRequest, AssetReceived);
11847
11704 } 11848 }
11705 11849
11706 /// <summary> 11850 /// <summary>
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs
index 9a8bfd3..0fa074d 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs
@@ -151,6 +151,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
151 151
152 private int m_defaultRTO = 1000; // 1sec is the recommendation in the RFC 152 private int m_defaultRTO = 1000; // 1sec is the recommendation in the RFC
153 private int m_maxRTO = 60000; 153 private int m_maxRTO = 60000;
154 public bool m_deliverPackets = true;
154 155
155 /// <summary> 156 /// <summary>
156 /// Default constructor 157 /// Default constructor
@@ -418,6 +419,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
418 if (category >= 0 && category < m_packetOutboxes.Length) 419 if (category >= 0 && category < m_packetOutboxes.Length)
419 { 420 {
420 OpenSim.Framework.LocklessQueue<OutgoingPacket> queue = m_packetOutboxes[category]; 421 OpenSim.Framework.LocklessQueue<OutgoingPacket> queue = m_packetOutboxes[category];
422
423 if (m_deliverPackets == false)
424 {
425 queue.Enqueue(packet);
426 return true;
427 }
428
421 TokenBucket bucket = m_throttleCategories[category]; 429 TokenBucket bucket = m_throttleCategories[category];
422 430
423 if (!forceQueue && bucket.RemoveTokens(packet.Buffer.DataLength)) 431 if (!forceQueue && bucket.RemoveTokens(packet.Buffer.DataLength))
@@ -457,6 +465,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
457 /// <returns>True if any packets were sent, otherwise false</returns> 465 /// <returns>True if any packets were sent, otherwise false</returns>
458 public bool DequeueOutgoing() 466 public bool DequeueOutgoing()
459 { 467 {
468 if (m_deliverPackets == false) return false;
469
460 OutgoingPacket packet; 470 OutgoingPacket packet;
461 OpenSim.Framework.LocklessQueue<OutgoingPacket> queue; 471 OpenSim.Framework.LocklessQueue<OutgoingPacket> queue;
462 TokenBucket bucket; 472 TokenBucket bucket;
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
index 583214c..c865c0f 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
@@ -960,7 +960,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
960 if (m_scene.TryGetClient(udpClient.AgentID, out client)) 960 if (m_scene.TryGetClient(udpClient.AgentID, out client))
961 { 961 {
962 client.IsLoggingOut = true; 962 client.IsLoggingOut = true;
963 client.Close(); 963 client.Close(false);
964 } 964 }
965 } 965 }
966 966
@@ -972,6 +972,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
972 972
973 while (base.IsRunning) 973 while (base.IsRunning)
974 { 974 {
975 m_scene.ThreadAlive(1);
975 try 976 try
976 { 977 {
977 IncomingPacket incomingPacket = null; 978 IncomingPacket incomingPacket = null;
@@ -1014,6 +1015,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1014 1015
1015 while (base.IsRunning) 1016 while (base.IsRunning)
1016 { 1017 {
1018 m_scene.ThreadAlive(2);
1017 try 1019 try
1018 { 1020 {
1019 m_packetSent = false; 1021 m_packetSent = false;
diff --git a/OpenSim/Region/ClientStack/LindenUDP/OpenSimUDPBase.cs b/OpenSim/Region/ClientStack/LindenUDP/OpenSimUDPBase.cs
index 6eebd9d..d2779ba 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/OpenSimUDPBase.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/OpenSimUDPBase.cs
@@ -100,10 +100,6 @@ namespace OpenMetaverse
100 const int SIO_UDP_CONNRESET = -1744830452; 100 const int SIO_UDP_CONNRESET = -1744830452;
101 101
102 IPEndPoint ipep = new IPEndPoint(m_localBindAddress, m_udpPort); 102 IPEndPoint ipep = new IPEndPoint(m_localBindAddress, m_udpPort);
103
104 m_log.DebugFormat(
105 "[UDPBASE]: Binding UDP listener using internal IP address config {0}:{1}",
106 ipep.Address, ipep.Port);
107 103
108 m_udpSocket = new Socket( 104 m_udpSocket = new Socket(
109 AddressFamily.InterNetwork, 105 AddressFamily.InterNetwork,
diff --git a/OpenSim/Region/ClientStack/LindenUDP/TokenBucket.cs b/OpenSim/Region/ClientStack/LindenUDP/TokenBucket.cs
index 0a8331f..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,30 +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
201 if (deltaMS <= 0)
202 {
203 if (deltaMS < 0)
204 lastDrip = now;
205 return false;
206 }
207 186
208 int dripAmount = deltaMS * tokensPerMS; 187 int now = Environment.TickCount;
188 int deltaMS = now - lastDrip;
189 lastDrip = now;
209 190
210 content = Math.Min(content + dripAmount, maxBurst); 191 if (deltaMS <= 0)
211 lastDrip = now; 192 {
212 193 return false;
213 if (dripAmount < 0 || content < 0) 194 }
214 // sim has been idle for too long, integer has overflown
215 // previous calculation is meaningless, let's put it at correct max
216 content = maxBurst;
217 195
218 return true; 196 long dripAmount = (long)deltaMS * (long)tokensPerMS + (long)content;
197 if (dripAmount > maxBurst)
198 {
199 dripAmount = maxBurst;
219 } 200 }
201 content = (int)dripAmount;
202 return true;
220 } 203 }
221 } 204 }
222} 205}