diff options
Diffstat (limited to '')
15 files changed, 2656 insertions, 388 deletions
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 56069a3..806269f 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | |||
@@ -34,11 +34,13 @@ using System.Text; | |||
34 | using System.Threading; | 34 | using System.Threading; |
35 | using System.Timers; | 35 | using System.Timers; |
36 | using System.Xml; | 36 | using System.Xml; |
37 | |||
37 | using log4net; | 38 | using log4net; |
38 | using OpenMetaverse; | 39 | using OpenMetaverse; |
39 | using OpenMetaverse.Packets; | 40 | using OpenMetaverse.Packets; |
40 | using OpenMetaverse.Messages.Linden; | 41 | using OpenMetaverse.Messages.Linden; |
41 | using OpenMetaverse.StructuredData; | 42 | using OpenMetaverse.StructuredData; |
43 | |||
42 | using OpenSim.Framework; | 44 | using OpenSim.Framework; |
43 | using OpenSim.Framework.Client; | 45 | using OpenSim.Framework.Client; |
44 | using OpenSim.Framework.Monitoring; | 46 | using OpenSim.Framework.Monitoring; |
@@ -48,7 +50,6 @@ using OpenSim.Services.Interfaces; | |||
48 | using Timer = System.Timers.Timer; | 50 | using Timer = System.Timers.Timer; |
49 | using AssetLandmark = OpenSim.Framework.AssetLandmark; | 51 | using AssetLandmark = OpenSim.Framework.AssetLandmark; |
50 | using RegionFlags = OpenMetaverse.RegionFlags; | 52 | using RegionFlags = OpenMetaverse.RegionFlags; |
51 | using Nini.Config; | ||
52 | 53 | ||
53 | using System.IO; | 54 | using System.IO; |
54 | using PermissionMask = OpenSim.Framework.PermissionMask; | 55 | using PermissionMask = OpenSim.Framework.PermissionMask; |
@@ -70,7 +71,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
70 | 71 | ||
71 | #region Events | 72 | #region Events |
72 | 73 | ||
73 | public event GenericMessage OnGenericMessage; | ||
74 | public event BinaryGenericMessage OnBinaryGenericMessage; | 74 | public event BinaryGenericMessage OnBinaryGenericMessage; |
75 | public event Action<IClientAPI> OnLogout; | 75 | public event Action<IClientAPI> OnLogout; |
76 | public event ObjectPermissions OnObjectPermissions; | 76 | public event ObjectPermissions OnObjectPermissions; |
@@ -78,13 +78,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
78 | public event ViewerEffectEventHandler OnViewerEffect; | 78 | public event ViewerEffectEventHandler OnViewerEffect; |
79 | public event ImprovedInstantMessage OnInstantMessage; | 79 | public event ImprovedInstantMessage OnInstantMessage; |
80 | public event ChatMessage OnChatFromClient; | 80 | public event ChatMessage OnChatFromClient; |
81 | public event TextureRequest OnRequestTexture; | ||
82 | public event RezObject OnRezObject; | 81 | public event RezObject OnRezObject; |
83 | public event DeRezObject OnDeRezObject; | 82 | public event DeRezObject OnDeRezObject; |
84 | public event ModifyTerrain OnModifyTerrain; | 83 | public event ModifyTerrain OnModifyTerrain; |
85 | public event Action<IClientAPI> OnRegionHandShakeReply; | 84 | public event Action<IClientAPI> OnRegionHandShakeReply; |
86 | public event GenericCall1 OnRequestWearables; | 85 | public event GenericCall1 OnRequestWearables; |
87 | public event CachedTextureRequest OnCachedTextureRequest; | ||
88 | public event SetAppearance OnSetAppearance; | 86 | public event SetAppearance OnSetAppearance; |
89 | public event AvatarNowWearing OnAvatarNowWearing; | 87 | public event AvatarNowWearing OnAvatarNowWearing; |
90 | public event RezSingleAttachmentFromInv OnRezSingleAttachmentFromInv; | 88 | public event RezSingleAttachmentFromInv OnRezSingleAttachmentFromInv; |
@@ -139,15 +137,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
139 | public event UpdatePrimGroupRotation OnUpdatePrimGroupMouseRotation; | 137 | public event UpdatePrimGroupRotation OnUpdatePrimGroupMouseRotation; |
140 | public event UpdateVector OnUpdatePrimScale; | 138 | public event UpdateVector OnUpdatePrimScale; |
141 | public event UpdateVector OnUpdatePrimGroupScale; | 139 | public event UpdateVector OnUpdatePrimGroupScale; |
142 | public event StatusChange OnChildAgentStatus; | ||
143 | public event GenericCall2 OnStopMovement; | ||
144 | public event Action<UUID> OnRemoveAvatar; | ||
145 | public event RequestMapBlocks OnRequestMapBlocks; | 140 | public event RequestMapBlocks OnRequestMapBlocks; |
146 | public event RequestMapName OnMapNameRequest; | 141 | public event RequestMapName OnMapNameRequest; |
147 | public event TeleportLocationRequest OnTeleportLocationRequest; | 142 | public event TeleportLocationRequest OnTeleportLocationRequest; |
148 | public event TeleportLandmarkRequest OnTeleportLandmarkRequest; | 143 | public event TeleportLandmarkRequest OnTeleportLandmarkRequest; |
149 | public event TeleportCancel OnTeleportCancel; | 144 | public event TeleportCancel OnTeleportCancel; |
150 | public event DisconnectUser OnDisconnectUser; | ||
151 | public event RequestAvatarProperties OnRequestAvatarProperties; | 145 | public event RequestAvatarProperties OnRequestAvatarProperties; |
152 | public event SetAlwaysRun OnSetAlwaysRun; | 146 | public event SetAlwaysRun OnSetAlwaysRun; |
153 | public event FetchInventory OnAgentDataUpdateRequest; | 147 | public event FetchInventory OnAgentDataUpdateRequest; |
@@ -178,7 +172,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
178 | public event UpdateTaskInventory OnUpdateTaskInventory; | 172 | public event UpdateTaskInventory OnUpdateTaskInventory; |
179 | public event MoveTaskInventory OnMoveTaskItem; | 173 | public event MoveTaskInventory OnMoveTaskItem; |
180 | public event RemoveTaskInventory OnRemoveTaskItem; | 174 | public event RemoveTaskInventory OnRemoveTaskItem; |
181 | public event RequestAsset OnRequestAsset; | ||
182 | public event UUIDNameRequest OnNameFromUUIDRequest; | 175 | public event UUIDNameRequest OnNameFromUUIDRequest; |
183 | public event ParcelAccessListRequest OnParcelAccessListRequest; | 176 | public event ParcelAccessListRequest OnParcelAccessListRequest; |
184 | public event ParcelAccessListUpdateRequest OnParcelAccessListUpdateRequest; | 177 | public event ParcelAccessListUpdateRequest OnParcelAccessListUpdateRequest; |
@@ -209,7 +202,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
209 | public event RequestPayPrice OnRequestPayPrice; | 202 | public event RequestPayPrice OnRequestPayPrice; |
210 | public event ObjectSaleInfo OnObjectSaleInfo; | 203 | public event ObjectSaleInfo OnObjectSaleInfo; |
211 | public event ObjectBuy OnObjectBuy; | 204 | public event ObjectBuy OnObjectBuy; |
212 | public event BuyObjectInventory OnBuyObjectInventory; | ||
213 | public event AgentSit OnUndo; | 205 | public event AgentSit OnUndo; |
214 | public event AgentSit OnRedo; | 206 | public event AgentSit OnRedo; |
215 | public event LandUndo OnLandUndo; | 207 | public event LandUndo OnLandUndo; |
@@ -218,7 +210,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
218 | public event RequestObjectPropertiesFamily OnObjectGroupRequest; | 210 | public event RequestObjectPropertiesFamily OnObjectGroupRequest; |
219 | public event DetailedEstateDataRequest OnDetailedEstateDataRequest; | 211 | public event DetailedEstateDataRequest OnDetailedEstateDataRequest; |
220 | public event SetEstateFlagsRequest OnSetEstateFlagsRequest; | 212 | public event SetEstateFlagsRequest OnSetEstateFlagsRequest; |
221 | public event SetEstateTerrainBaseTexture OnSetEstateTerrainBaseTexture; | ||
222 | public event SetEstateTerrainDetailTexture OnSetEstateTerrainDetailTexture; | 213 | public event SetEstateTerrainDetailTexture OnSetEstateTerrainDetailTexture; |
223 | public event SetEstateTerrainTextureHeights OnSetEstateTerrainTextureHeights; | 214 | public event SetEstateTerrainTextureHeights OnSetEstateTerrainTextureHeights; |
224 | public event CommitEstateTerrainTextureRequest OnCommitEstateTerrainTextureRequest; | 215 | public event CommitEstateTerrainTextureRequest OnCommitEstateTerrainTextureRequest; |
@@ -241,7 +232,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
241 | public event GetScriptRunning OnGetScriptRunning; | 232 | public event GetScriptRunning OnGetScriptRunning; |
242 | public event SetScriptRunning OnSetScriptRunning; | 233 | public event SetScriptRunning OnSetScriptRunning; |
243 | public event Action<Vector3, bool, bool> OnAutoPilotGo; | 234 | public event Action<Vector3, bool, bool> OnAutoPilotGo; |
244 | public event TerrainUnacked OnUnackedTerrain; | ||
245 | public event ActivateGesture OnActivateGesture; | 235 | public event ActivateGesture OnActivateGesture; |
246 | public event DeactivateGesture OnDeactivateGesture; | 236 | public event DeactivateGesture OnDeactivateGesture; |
247 | public event ObjectOwner OnObjectOwner; | 237 | public event ObjectOwner OnObjectOwner; |
@@ -301,6 +291,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
301 | public event GodUpdateRegionInfoUpdate OnGodUpdateRegionInfoUpdate; | 291 | public event GodUpdateRegionInfoUpdate OnGodUpdateRegionInfoUpdate; |
302 | public event GenericCall2 OnUpdateThrottles; | 292 | public event GenericCall2 OnUpdateThrottles; |
303 | 293 | ||
294 | #pragma warning disable 0067 | ||
295 | public event GenericMessage OnGenericMessage; | ||
296 | public event TextureRequest OnRequestTexture; | ||
297 | public event StatusChange OnChildAgentStatus; | ||
298 | public event GenericCall2 OnStopMovement; | ||
299 | public event Action<UUID> OnRemoveAvatar; | ||
300 | public event DisconnectUser OnDisconnectUser; | ||
301 | public event RequestAsset OnRequestAsset; | ||
302 | public event BuyObjectInventory OnBuyObjectInventory; | ||
303 | public event SetEstateTerrainBaseTexture OnSetEstateTerrainBaseTexture; | ||
304 | public event TerrainUnacked OnUnackedTerrain; | ||
305 | public event CachedTextureRequest OnCachedTextureRequest; | ||
306 | #pragma warning restore 0067 | ||
307 | |||
304 | #endregion Events | 308 | #endregion Events |
305 | 309 | ||
306 | #region Class Members | 310 | #region Class Members |
@@ -413,9 +417,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
413 | } | 417 | } |
414 | public UUID AgentId { get { return m_agentId; } } | 418 | public UUID AgentId { get { return m_agentId; } } |
415 | public ISceneAgent SceneAgent { get; set; } | 419 | public ISceneAgent SceneAgent { get; set; } |
416 | public UUID ActiveGroupId { get { return m_activeGroupID; } } | 420 | public UUID ActiveGroupId { get { return m_activeGroupID; } private set { m_activeGroupID = value; } } |
417 | public string ActiveGroupName { get { return m_activeGroupName; } } | 421 | public string ActiveGroupName { get { return m_activeGroupName; } private set { m_activeGroupName = value; } } |
418 | public ulong ActiveGroupPowers { get { return m_activeGroupPowers; } } | 422 | public ulong ActiveGroupPowers { get { return m_activeGroupPowers; } private set { m_activeGroupPowers = value; } } |
419 | public bool IsGroupMember(UUID groupID) { return m_groupPowers.ContainsKey(groupID); } | 423 | public bool IsGroupMember(UUID groupID) { return m_groupPowers.ContainsKey(groupID); } |
420 | 424 | ||
421 | public int PingTimeMS | 425 | public int PingTimeMS |
@@ -482,7 +486,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
482 | 486 | ||
483 | // ~LLClientView() | 487 | // ~LLClientView() |
484 | // { | 488 | // { |
485 | // m_log.DebugFormat("[LLCLIENTVIEW]: Destructor called for {0}, circuit code {1}", Name, CircuitCode); | 489 | // m_log.DebugFormat("{0} Destructor called for {1}, circuit code {2}", LogHeader, Name, CircuitCode); |
486 | // } | 490 | // } |
487 | 491 | ||
488 | /// <summary> | 492 | /// <summary> |
@@ -553,9 +557,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
553 | // there is some unidentified connection problem, not where we have issues due to deadlock | 557 | // there is some unidentified connection problem, not where we have issues due to deadlock |
554 | if (!IsActive && !force) | 558 | if (!IsActive && !force) |
555 | { | 559 | { |
556 | m_log.DebugFormat( | 560 | m_log.DebugFormat( "{0} Not attempting to close inactive client {1} in {2} since force flag is not set", |
557 | "[CLIENT]: Not attempting to close inactive client {0} in {1} since force flag is not set", | 561 | LogHeader, Name, m_scene.Name); |
558 | Name, m_scene.Name); | ||
559 | 562 | ||
560 | return; | 563 | return; |
561 | } | 564 | } |
@@ -720,7 +723,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
720 | if (!m_packetHandlers.ContainsKey(packetType)) | 723 | if (!m_packetHandlers.ContainsKey(packetType)) |
721 | { | 724 | { |
722 | m_packetHandlers.Add( | 725 | m_packetHandlers.Add( |
726 | <<<<<<< HEAD | ||
727 | packetType, new PacketProcessor() { method = handler, Async = doAsync, InEngine = inEngine }); | ||
728 | ======= | ||
723 | packetType, new PacketProcessor() { method = handler, Async = doAsync }); | 729 | packetType, new PacketProcessor() { method = handler, Async = doAsync }); |
730 | >>>>>>> avn/ubitvar | ||
724 | result = true; | 731 | result = true; |
725 | } | 732 | } |
726 | } | 733 | } |
@@ -755,21 +762,26 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
755 | PacketProcessor pprocessor; | 762 | PacketProcessor pprocessor; |
756 | if (m_packetHandlers.TryGetValue(packet.Type, out pprocessor)) | 763 | if (m_packetHandlers.TryGetValue(packet.Type, out pprocessor)) |
757 | { | 764 | { |
765 | ClientInfo cinfo = UDPClient.GetClientInfo(); | ||
766 | |||
758 | //there is a local handler for this packet type | 767 | //there is a local handler for this packet type |
759 | if (pprocessor.Async) | 768 | if (pprocessor.Async) |
760 | { | 769 | { |
761 | ClientInfo cinfo = UDPClient.GetClientInfo(); | ||
762 | if (!cinfo.AsyncRequests.ContainsKey(packet.Type.ToString())) | 770 | if (!cinfo.AsyncRequests.ContainsKey(packet.Type.ToString())) |
763 | cinfo.AsyncRequests[packet.Type.ToString()] = 0; | 771 | cinfo.AsyncRequests[packet.Type.ToString()] = 0; |
764 | cinfo.AsyncRequests[packet.Type.ToString()]++; | 772 | cinfo.AsyncRequests[packet.Type.ToString()]++; |
765 | 773 | ||
766 | object obj = new AsyncPacketProcess(this, pprocessor.method, packet); | 774 | object obj = new AsyncPacketProcess(this, pprocessor.method, packet); |
767 | Util.FireAndForget(ProcessSpecificPacketAsync, obj); | 775 | |
776 | if (pprocessor.InEngine) | ||
777 | m_udpServer.IpahEngine.QueueJob(packet.Type.ToString(), () => ProcessSpecificPacketAsync(obj)); | ||
778 | else | ||
779 | Util.FireAndForget(ProcessSpecificPacketAsync, obj, packet.Type.ToString()); | ||
780 | |||
768 | result = true; | 781 | result = true; |
769 | } | 782 | } |
770 | else | 783 | else |
771 | { | 784 | { |
772 | ClientInfo cinfo = UDPClient.GetClientInfo(); | ||
773 | if (!cinfo.SyncRequests.ContainsKey(packet.Type.ToString())) | 785 | if (!cinfo.SyncRequests.ContainsKey(packet.Type.ToString())) |
774 | cinfo.SyncRequests[packet.Type.ToString()] = 0; | 786 | cinfo.SyncRequests[packet.Type.ToString()] = 0; |
775 | cinfo.SyncRequests[packet.Type.ToString()]++; | 787 | cinfo.SyncRequests[packet.Type.ToString()]++; |
@@ -810,9 +822,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
810 | catch (Exception e) | 822 | catch (Exception e) |
811 | { | 823 | { |
812 | // Make sure that we see any exception caused by the asynchronous operation. | 824 | // Make sure that we see any exception caused by the asynchronous operation. |
813 | m_log.ErrorFormat( | 825 | m_log.Error( |
814 | "[LLCLIENTVIEW]: Caught exception while processing {0} for {1}, {2} {3}", | 826 | string.Format( |
815 | packetObject.Pack, Name, e.Message, e.StackTrace); | 827 | "[LLCLIENTVIEW]: Caught exception while processing {0} for {1} ", packetObject.Pack, Name), |
828 | e); | ||
816 | } | 829 | } |
817 | } | 830 | } |
818 | 831 | ||
@@ -1215,11 +1228,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1215 | /// <param name="map">heightmap</param> | 1228 | /// <param name="map">heightmap</param> |
1216 | public virtual void SendLayerData(float[] map) | 1229 | public virtual void SendLayerData(float[] map) |
1217 | { | 1230 | { |
1231 | <<<<<<< HEAD | ||
1232 | Util.FireAndForget(DoSendLayerData, m_scene.Heightmap.GetTerrainData(), "LLClientView.DoSendLayerData"); | ||
1233 | ======= | ||
1218 | Util.FireAndForget(DoSendLayerData, m_scene.Heightmap.GetTerrainData()); | 1234 | Util.FireAndForget(DoSendLayerData, m_scene.Heightmap.GetTerrainData()); |
1219 | 1235 | ||
1220 | // Send it sync, and async. It's not that much data | 1236 | // Send it sync, and async. It's not that much data |
1221 | // and it improves user experience just so much! | 1237 | // and it improves user experience just so much! |
1222 | // DoSendLayerData(map); | 1238 | // DoSendLayerData(map); |
1239 | >>>>>>> avn/ubitvar | ||
1223 | } | 1240 | } |
1224 | 1241 | ||
1225 | /// <summary> | 1242 | /// <summary> |
@@ -1233,6 +1250,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1233 | try | 1250 | try |
1234 | { | 1251 | { |
1235 | // Send LayerData in typerwriter pattern | 1252 | // Send LayerData in typerwriter pattern |
1253 | <<<<<<< HEAD | ||
1254 | //for (int y = 0; y < 16; y++) | ||
1255 | //{ | ||
1256 | // for (int x = 0; x < 16; x++) | ||
1257 | // { | ||
1258 | // SendLayerData(x, y, map); | ||
1259 | // } | ||
1260 | //} | ||
1261 | |||
1262 | // Send LayerData in a spiral pattern. Fun! | ||
1263 | SendLayerTopRight(map, 0, 0, map.SizeX/Constants.TerrainPatchSize-1, map.SizeY/Constants.TerrainPatchSize-1); | ||
1264 | ======= | ||
1236 | for (int y = 0; y < 16; y++) | 1265 | for (int y = 0; y < 16; y++) |
1237 | { | 1266 | { |
1238 | for (int x = 0; x < 16; x++) | 1267 | for (int x = 0; x < 16; x++) |
@@ -1240,6 +1269,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1240 | SendLayerData(x, y, map); | 1269 | SendLayerData(x, y, map); |
1241 | } | 1270 | } |
1242 | } | 1271 | } |
1272 | >>>>>>> avn/ubitvar | ||
1243 | } | 1273 | } |
1244 | catch (Exception e) | 1274 | catch (Exception e) |
1245 | { | 1275 | { |
@@ -1247,6 +1277,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1247 | } | 1277 | } |
1248 | } | 1278 | } |
1249 | 1279 | ||
1280 | <<<<<<< HEAD | ||
1281 | private void SendLayerTopRight(TerrainData map, int x1, int y1, int x2, int y2) | ||
1282 | ======= | ||
1250 | // Legacy form of invocation that passes around a bare data array. | 1283 | // Legacy form of invocation that passes around a bare data array. |
1251 | // Just ignore what was passed and use the real terrain info that is part of the scene. | 1284 | // Just ignore what was passed and use the real terrain info that is part of the scene. |
1252 | // As a HORRIBLE kludge in an attempt to not change the definition of IClientAPI, | 1285 | // As a HORRIBLE kludge in an attempt to not change the definition of IClientAPI, |
@@ -1256,6 +1289,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1256 | // as -2 and map= [3, 5, 8, 4] would mean to send two terrain heightmap patches | 1289 | // as -2 and map= [3, 5, 8, 4] would mean to send two terrain heightmap patches |
1257 | // and the patches to send are <3,5> and <8,4>. | 1290 | // and the patches to send are <3,5> and <8,4>. |
1258 | public void SendLayerData(int px, int py, float[] map) | 1291 | public void SendLayerData(int px, int py, float[] map) |
1292 | >>>>>>> avn/ubitvar | ||
1259 | { | 1293 | { |
1260 | if (px >= 0) | 1294 | if (px >= 0) |
1261 | { | 1295 | { |
@@ -1274,6 +1308,92 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1274 | 1308 | ||
1275 | // DebugSendingPatches("SendLayerData", xPatches, yPatches); | 1309 | // DebugSendingPatches("SendLayerData", xPatches, yPatches); |
1276 | 1310 | ||
1311 | <<<<<<< HEAD | ||
1312 | if (x2 - x1 > 0 && y2 - y1 > 0) | ||
1313 | SendLayerBottomLeft(map, x1, y1 + 1, x2 - 1, y2); | ||
1314 | } | ||
1315 | |||
1316 | void SendLayerBottomLeft(TerrainData map, int x1, int y1, int x2, int y2) | ||
1317 | { | ||
1318 | // Row in reverse | ||
1319 | for (int i = x2; i >= x1; i--) | ||
1320 | SendLayerData(i, y2, map); | ||
1321 | |||
1322 | // Column in reverse | ||
1323 | for (int j = y2 - 1; j >= y1; j--) | ||
1324 | SendLayerData(x1, j, map); | ||
1325 | |||
1326 | if (x2 - x1 > 0 && y2 - y1 > 0) | ||
1327 | SendLayerTopRight(map, x1 + 1, y1, x2, y2 - 1); | ||
1328 | } | ||
1329 | |||
1330 | /// <summary> | ||
1331 | /// Sends a set of four patches (x, x+1, ..., x+3) to the client | ||
1332 | /// </summary> | ||
1333 | /// <param name="map">heightmap</param> | ||
1334 | /// <param name="px">X coordinate for patches 0..12</param> | ||
1335 | /// <param name="py">Y coordinate for patches 0..15</param> | ||
1336 | // private void SendLayerPacket(float[] map, int y, int x) | ||
1337 | // { | ||
1338 | // int[] patches = new int[4]; | ||
1339 | // patches[0] = x + 0 + y * 16; | ||
1340 | // patches[1] = x + 1 + y * 16; | ||
1341 | // patches[2] = x + 2 + y * 16; | ||
1342 | // patches[3] = x + 3 + y * 16; | ||
1343 | |||
1344 | // Packet layerpack = LLClientView.TerrainManager.CreateLandPacket(map, patches); | ||
1345 | // OutPacket(layerpack, ThrottleOutPacketType.Land); | ||
1346 | // } | ||
1347 | |||
1348 | // Legacy form of invocation that passes around a bare data array. | ||
1349 | // Just ignore what was passed and use the real terrain info that is part of the scene. | ||
1350 | // As a HORRIBLE kludge in an attempt to not change the definition of IClientAPI, | ||
1351 | // there is a special form for specifying multiple terrain patches to send. | ||
1352 | // The form is to pass 'px' as negative the number of patches to send and to | ||
1353 | // pass the float array as pairs of patch X and Y coordinates. So, passing 'px' | ||
1354 | // as -2 and map= [3, 5, 8, 4] would mean to send two terrain heightmap patches | ||
1355 | // and the patches to send are <3,5> and <8,4>. | ||
1356 | public void SendLayerData(int px, int py, float[] map) | ||
1357 | { | ||
1358 | if (px >= 0) | ||
1359 | { | ||
1360 | SendLayerData(px, py, m_scene.Heightmap.GetTerrainData()); | ||
1361 | } | ||
1362 | else | ||
1363 | { | ||
1364 | int numPatches = -px; | ||
1365 | int[] xPatches = new int[numPatches]; | ||
1366 | int[] yPatches = new int[numPatches]; | ||
1367 | for (int pp = 0; pp < numPatches; pp++) | ||
1368 | { | ||
1369 | xPatches[pp] = (int)map[pp * 2]; | ||
1370 | yPatches[pp] = (int)map[pp * 2 + 1]; | ||
1371 | } | ||
1372 | |||
1373 | // DebugSendingPatches("SendLayerData", xPatches, yPatches); | ||
1374 | |||
1375 | SendLayerData(xPatches, yPatches, m_scene.Heightmap.GetTerrainData()); | ||
1376 | } | ||
1377 | } | ||
1378 | |||
1379 | private void DebugSendingPatches(string pWho, int[] pX, int[] pY) | ||
1380 | { | ||
1381 | if (m_log.IsDebugEnabled) | ||
1382 | { | ||
1383 | int numPatches = pX.Length; | ||
1384 | string Xs = ""; | ||
1385 | string Ys = ""; | ||
1386 | for (int pp = 0; pp < numPatches; pp++) | ||
1387 | { | ||
1388 | Xs += String.Format("{0}", (int)pX[pp]) + ","; | ||
1389 | Ys += String.Format("{0}", (int)pY[pp]) + ","; | ||
1390 | } | ||
1391 | m_log.DebugFormat("{0} {1}: numPatches={2}, X={3}, Y={4}", LogHeader, pWho, numPatches, Xs, Ys); | ||
1392 | } | ||
1393 | } | ||
1394 | |||
1395 | /// <summary> | ||
1396 | ======= | ||
1277 | SendLayerData(xPatches, yPatches, m_scene.Heightmap.GetTerrainData()); | 1397 | SendLayerData(xPatches, yPatches, m_scene.Heightmap.GetTerrainData()); |
1278 | } | 1398 | } |
1279 | } | 1399 | } |
@@ -1295,6 +1415,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1295 | } | 1415 | } |
1296 | 1416 | ||
1297 | /// <summary> | 1417 | /// <summary> |
1418 | >>>>>>> avn/ubitvar | ||
1298 | /// Sends a terrain packet for the point specified. | 1419 | /// Sends a terrain packet for the point specified. |
1299 | /// This is a legacy call that has refarbed the terrain into a flat map of floats. | 1420 | /// This is a legacy call that has refarbed the terrain into a flat map of floats. |
1300 | /// We just use the terrain from the region we know about. | 1421 | /// We just use the terrain from the region we know about. |
@@ -1337,6 +1458,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1337 | 1458 | ||
1338 | SendTheLayerPacket(layerpack); | 1459 | SendTheLayerPacket(layerpack); |
1339 | } | 1460 | } |
1461 | // LayerDataPacket layerpack = OpenSimTerrainCompressor.CreateLandPacket(terrData, px, py); | ||
1462 | |||
1340 | } | 1463 | } |
1341 | catch (Exception e) | 1464 | catch (Exception e) |
1342 | { | 1465 | { |
@@ -1344,9 +1467,40 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1344 | } | 1467 | } |
1345 | } | 1468 | } |
1346 | 1469 | ||
1470 | <<<<<<< HEAD | ||
1471 | // When a user edits the terrain, so much data is sent, the data queues up fast and presents a | ||
1472 | // sub optimal editing experience. To alleviate this issue, when the user edits the terrain, we | ||
1473 | // start skipping the queues until they're done editing the terrain. We also make them | ||
1474 | // unreliable because it's extremely likely that multiple packets will be sent for a terrain patch | ||
1475 | // area invalidating previous packets for that area. | ||
1476 | |||
1477 | // It's possible for an editing user to flood themselves with edited packets but the majority | ||
1478 | // of use cases are such that only a tiny percentage of users will be editing the terrain. | ||
1479 | // Other, non-editing users will see the edits much slower. | ||
1480 | |||
1481 | // One last note on this topic, by the time users are going to be editing the terrain, it's | ||
1482 | // extremely likely that the sim will have rezzed already and therefore this is not likely going | ||
1483 | // to cause any additional issues with lost packets, objects or terrain patches. | ||
1484 | |||
1485 | // m_justEditedTerrain is volatile, so test once and duplicate two affected statements so we | ||
1486 | // only have one cache miss. | ||
1487 | private void SendTheLayerPacket(LayerDataPacket layerpack) | ||
1488 | { | ||
1489 | if (m_justEditedTerrain) | ||
1490 | { | ||
1491 | layerpack.Header.Reliable = false; | ||
1492 | OutPacket(layerpack, ThrottleOutPacketType.Unknown ); | ||
1493 | } | ||
1494 | else | ||
1495 | { | ||
1496 | layerpack.Header.Reliable = true; | ||
1497 | OutPacket(layerpack, ThrottleOutPacketType.Land); | ||
1498 | } | ||
1499 | ======= | ||
1347 | private void SendTheLayerPacket(LayerDataPacket layerpack) | 1500 | private void SendTheLayerPacket(LayerDataPacket layerpack) |
1348 | { | 1501 | { |
1349 | OutPacket(layerpack, ThrottleOutPacketType.Land); | 1502 | OutPacket(layerpack, ThrottleOutPacketType.Land); |
1503 | >>>>>>> avn/ubitvar | ||
1350 | } | 1504 | } |
1351 | 1505 | ||
1352 | /// <summary> | 1506 | /// <summary> |
@@ -1355,7 +1509,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1355 | /// <param name="windSpeeds">16x16 array of wind speeds</param> | 1509 | /// <param name="windSpeeds">16x16 array of wind speeds</param> |
1356 | public virtual void SendWindData(Vector2[] windSpeeds) | 1510 | public virtual void SendWindData(Vector2[] windSpeeds) |
1357 | { | 1511 | { |
1358 | Util.FireAndForget(DoSendWindData, windSpeeds); | 1512 | Util.FireAndForget(DoSendWindData, windSpeeds, "LLClientView.SendWindData"); |
1359 | } | 1513 | } |
1360 | 1514 | ||
1361 | /// <summary> | 1515 | /// <summary> |
@@ -1364,7 +1518,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1364 | /// <param name="windSpeeds">16x16 array of cloud densities</param> | 1518 | /// <param name="windSpeeds">16x16 array of cloud densities</param> |
1365 | public virtual void SendCloudData(float[] cloudDensity) | 1519 | public virtual void SendCloudData(float[] cloudDensity) |
1366 | { | 1520 | { |
1367 | Util.FireAndForget(DoSendCloudData, cloudDensity); | 1521 | Util.FireAndForget(DoSendCloudData, cloudDensity, "LLClientView.SendCloudData"); |
1368 | } | 1522 | } |
1369 | 1523 | ||
1370 | /// <summary> | 1524 | /// <summary> |
@@ -1807,6 +1961,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1807 | newBlock.Name = Util.StringToBytes256(folder.Name); | 1961 | newBlock.Name = Util.StringToBytes256(folder.Name); |
1808 | newBlock.ParentID = folder.ParentID; | 1962 | newBlock.ParentID = folder.ParentID; |
1809 | newBlock.Type = (sbyte)folder.Type; | 1963 | newBlock.Type = (sbyte)folder.Type; |
1964 | //if (newBlock.Type == InventoryItemBase.SUITCASE_FOLDER_TYPE) | ||
1965 | // newBlock.Type = InventoryItemBase.SUITCASE_FOLDER_FAKE_TYPE; | ||
1810 | 1966 | ||
1811 | return newBlock; | 1967 | return newBlock; |
1812 | } | 1968 | } |
@@ -2056,8 +2212,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
2056 | 2212 | ||
2057 | folderBlock.FolderID = folder.ID; | 2213 | folderBlock.FolderID = folder.ID; |
2058 | folderBlock.ParentID = folder.ParentID; | 2214 | folderBlock.ParentID = folder.ParentID; |
2059 | //folderBlock.Type = -1; | ||
2060 | folderBlock.Type = (sbyte)folder.Type; | 2215 | folderBlock.Type = (sbyte)folder.Type; |
2216 | // Leaving this here for now, just in case we need to do this for a while | ||
2217 | //if (folderBlock.Type == InventoryItemBase.SUITCASE_FOLDER_TYPE) | ||
2218 | // folderBlock.Type = InventoryItemBase.SUITCASE_FOLDER_FAKE_TYPE; | ||
2061 | folderBlock.Name = Util.StringToBytes256(folder.Name); | 2219 | folderBlock.Name = Util.StringToBytes256(folder.Name); |
2062 | 2220 | ||
2063 | return folderBlock; | 2221 | return folderBlock; |
@@ -2332,9 +2490,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
2332 | { | 2490 | { |
2333 | if (agentid == AgentId) | 2491 | if (agentid == AgentId) |
2334 | { | 2492 | { |
2493 | <<<<<<< HEAD | ||
2494 | ActiveGroupId = activegroupid; | ||
2495 | ActiveGroupName = groupname; | ||
2496 | ActiveGroupPowers = grouppowers; | ||
2497 | ======= | ||
2335 | m_activeGroupID = activegroupid; | 2498 | m_activeGroupID = activegroupid; |
2336 | m_activeGroupName = groupname; | 2499 | m_activeGroupName = groupname; |
2337 | m_activeGroupPowers = grouppowers; | 2500 | m_activeGroupPowers = grouppowers; |
2501 | >>>>>>> avn/ubitvar | ||
2338 | } | 2502 | } |
2339 | 2503 | ||
2340 | AgentDataUpdatePacket sendAgentDataUpdate = (AgentDataUpdatePacket)PacketPool.Instance.GetPacket(PacketType.AgentDataUpdate); | 2504 | AgentDataUpdatePacket sendAgentDataUpdate = (AgentDataUpdatePacket)PacketPool.Instance.GetPacket(PacketType.AgentDataUpdate); |
@@ -2842,8 +3006,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
2842 | { | 3006 | { |
2843 | if (req.AssetInf.Data == null) | 3007 | if (req.AssetInf.Data == null) |
2844 | { | 3008 | { |
2845 | m_log.ErrorFormat("Cannot send asset {0} ({1}), asset data is null", | 3009 | m_log.ErrorFormat("{0} Cannot send asset {1} ({2}), asset data is null", |
2846 | req.AssetInf.ID, req.AssetInf.Metadata.ContentType); | 3010 | LogHeader, req.AssetInf.ID, req.AssetInf.Metadata.ContentType); |
2847 | return; | 3011 | return; |
2848 | } | 3012 | } |
2849 | int WearableOut = 0; | 3013 | int WearableOut = 0; |
@@ -3724,11 +3888,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
3724 | avp.Sender.IsTrial = false; | 3888 | avp.Sender.IsTrial = false; |
3725 | avp.Sender.ID = agentID; | 3889 | avp.Sender.ID = agentID; |
3726 | avp.AppearanceData = new AvatarAppearancePacket.AppearanceDataBlock[0]; | 3890 | avp.AppearanceData = new AvatarAppearancePacket.AppearanceDataBlock[0]; |
3891 | <<<<<<< HEAD | ||
3892 | avp.AppearanceHover = new AvatarAppearancePacket.AppearanceHoverBlock[0]; | ||
3893 | ======= | ||
3727 | 3894 | ||
3728 | // this need be use in future | 3895 | // this need be use in future |
3729 | // avp.AppearanceData[0].AppearanceVersion = 0; | 3896 | // avp.AppearanceData[0].AppearanceVersion = 0; |
3730 | // avp.AppearanceData[0].CofVersion = 0; | 3897 | // avp.AppearanceData[0].CofVersion = 0; |
3731 | 3898 | ||
3899 | >>>>>>> avn/ubitvar | ||
3732 | //m_log.DebugFormat("[CLIENT]: Sending appearance for {0} to {1}", agentID.ToString(), AgentId.ToString()); | 3900 | //m_log.DebugFormat("[CLIENT]: Sending appearance for {0} to {1}", agentID.ToString(), AgentId.ToString()); |
3733 | OutPacket(avp, ThrottleOutPacketType.Task | ThrottleOutPacketType.HighPriority); | 3901 | OutPacket(avp, ThrottleOutPacketType.Task | ThrottleOutPacketType.HighPriority); |
3734 | } | 3902 | } |
@@ -3846,6 +4014,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
3846 | /// </summary> | 4014 | /// </summary> |
3847 | public void SendEntityUpdate(ISceneEntity entity, PrimUpdateFlags updateFlags) | 4015 | public void SendEntityUpdate(ISceneEntity entity, PrimUpdateFlags updateFlags) |
3848 | { | 4016 | { |
4017 | <<<<<<< HEAD | ||
4018 | if (entity.UUID == m_agentId && !updateFlags.HasFlag(PrimUpdateFlags.FullUpdate)) | ||
4019 | { | ||
4020 | ImprovedTerseObjectUpdatePacket packet | ||
4021 | = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ImprovedTerseObjectUpdate); | ||
4022 | ======= | ||
3849 | if (entity is SceneObjectPart) | 4023 | if (entity is SceneObjectPart) |
3850 | { | 4024 | { |
3851 | SceneObjectPart e = (SceneObjectPart)entity; | 4025 | SceneObjectPart e = (SceneObjectPart)entity; |
@@ -3855,9 +4029,22 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
3855 | } | 4029 | } |
3856 | 4030 | ||
3857 | uint priority = m_prioritizer.GetUpdatePriority(this, entity); | 4031 | uint priority = m_prioritizer.GetUpdatePriority(this, entity); |
4032 | >>>>>>> avn/ubitvar | ||
3858 | 4033 | ||
3859 | lock (m_entityUpdates.SyncRoot) | 4034 | packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; |
3860 | m_entityUpdates.Enqueue(priority, new EntityUpdate(entity, updateFlags, m_scene.TimeDilation)); | 4035 | packet.RegionData.TimeDilation = Utils.FloatToUInt16(1, 0.0f, 1.0f); |
4036 | packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[1]; | ||
4037 | packet.ObjectData[0] = CreateImprovedTerseBlock(entity, false); | ||
4038 | OutPacket(packet, ThrottleOutPacketType.Unknown, true); | ||
4039 | } | ||
4040 | else | ||
4041 | { | ||
4042 | //double priority = m_prioritizer.GetUpdatePriority(this, entity); | ||
4043 | uint priority = m_prioritizer.GetUpdatePriority(this, entity); | ||
4044 | |||
4045 | lock (m_entityUpdates.SyncRoot) | ||
4046 | m_entityUpdates.Enqueue(priority, new EntityUpdate(entity, updateFlags, m_scene.TimeDilation)); | ||
4047 | } | ||
3861 | } | 4048 | } |
3862 | 4049 | ||
3863 | 4050 | ||
@@ -4198,6 +4385,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
4198 | 4385 | ||
4199 | OutPacket(packet, ThrottleOutPacketType.Task, true); | 4386 | OutPacket(packet, ThrottleOutPacketType.Task, true); |
4200 | } | 4387 | } |
4388 | <<<<<<< HEAD | ||
4389 | |||
4390 | // m_log.DebugFormat( | ||
4391 | // "[LLCLIENTVIEW]: Sent {0} updates in ProcessEntityUpdates() for {1} {2} in {3}", | ||
4392 | // updatesThisCall, Name, SceneAgent.IsChildAgent ? "child" : "root", Scene.Name); | ||
4393 | // | ||
4394 | #endregion Packet Sending | ||
4395 | ======= | ||
4396 | >>>>>>> avn/ubitvar | ||
4201 | } | 4397 | } |
4202 | 4398 | ||
4203 | public void ReprioritizeUpdates() | 4399 | public void ReprioritizeUpdates() |
@@ -5164,6 +5360,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
5164 | { | 5360 | { |
5165 | ScenePresence presence = (ScenePresence)entity; | 5361 | ScenePresence presence = (ScenePresence)entity; |
5166 | 5362 | ||
5363 | <<<<<<< HEAD | ||
5364 | // m_log.DebugFormat( | ||
5365 | // "[LLCLIENTVIEW]: Sending terse update to {0} with pos {1}, vel {2} in {3}", | ||
5366 | // Name, presence.OffsetPosition, presence.Velocity, m_scene.Name); | ||
5367 | ======= | ||
5167 | position = presence.OffsetPosition; | 5368 | position = presence.OffsetPosition; |
5168 | rotation = presence.Rotation; | 5369 | rotation = presence.Rotation; |
5169 | angularVelocity = presence.AngularVelocity; | 5370 | angularVelocity = presence.AngularVelocity; |
@@ -5172,6 +5373,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
5172 | attachPoint = 0; | 5373 | attachPoint = 0; |
5173 | // m_log.DebugFormat( | 5374 | // m_log.DebugFormat( |
5174 | // "[LLCLIENTVIEW]: Sending terse update to {0} with position {1} in {2}", Name, presence.OffsetPosition, m_scene.Name); | 5375 | // "[LLCLIENTVIEW]: Sending terse update to {0} with position {1} in {2}", Name, presence.OffsetPosition, m_scene.Name); |
5376 | >>>>>>> avn/ubitvar | ||
5175 | 5377 | ||
5176 | // attachPoint = presence.State; // Core: commented | 5378 | // attachPoint = presence.State; // Core: commented |
5177 | collisionPlane = presence.CollisionPlane; | 5379 | collisionPlane = presence.CollisionPlane; |
@@ -5290,9 +5492,27 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
5290 | uint parentID = data.ParentID; | 5492 | uint parentID = data.ParentID; |
5291 | 5493 | ||
5292 | // m_log.DebugFormat( | 5494 | // m_log.DebugFormat( |
5293 | // "[LLCLIENTVIEW]: Sending full update to {0} with position {1} in {2}", Name, data.OffsetPosition, m_scene.Name); | 5495 | // "[LLCLIENTVIEW]: Sending full update to {0} with pos {1}, vel {2} in {3}", Name, data.OffsetPosition, data.Velocity, m_scene.Name); |
5294 | 5496 | ||
5295 | byte[] objectData = new byte[76]; | 5497 | byte[] objectData = new byte[76]; |
5498 | <<<<<<< HEAD | ||
5499 | |||
5500 | data.CollisionPlane.ToBytes(objectData, 0); | ||
5501 | data.OffsetPosition.ToBytes(objectData, 16); | ||
5502 | data.Velocity.ToBytes(objectData, 28); | ||
5503 | // data.Acceleration.ToBytes(objectData, 40); | ||
5504 | |||
5505 | // Whilst not in mouselook, an avatar will transmit only the Z rotation as this is the only axis | ||
5506 | // it rotates around. | ||
5507 | // In mouselook, X and Y co-ordinate will also be sent but when used in Rotation, these cause unwanted | ||
5508 | // excessive up and down movements of the camera when looking up and down. | ||
5509 | // See http://opensimulator.org/mantis/view.php?id=3274 | ||
5510 | // This does not affect head movement, since this is controlled entirely by camera movement rather than | ||
5511 | // body rotation. We still need to transmit X and Y for sitting avatars but mouselook does not change | ||
5512 | // the rotation in this case. | ||
5513 | Quaternion rot = data.Rotation; | ||
5514 | ======= | ||
5515 | >>>>>>> avn/ubitvar | ||
5296 | 5516 | ||
5297 | Vector3 velocity = new Vector3(0, 0, 0); | 5517 | Vector3 velocity = new Vector3(0, 0, 0); |
5298 | Vector3 acceleration = new Vector3(0, 0, 0); | 5518 | Vector3 acceleration = new Vector3(0, 0, 0); |
@@ -5376,11 +5596,26 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
5376 | //update.JointType = 0; | 5596 | //update.JointType = 0; |
5377 | update.Material = data.Material; | 5597 | update.Material = data.Material; |
5378 | update.MediaURL = Utils.EmptyBytes; // FIXME: Support this in OpenSim | 5598 | update.MediaURL = Utils.EmptyBytes; // FIXME: Support this in OpenSim |
5599 | <<<<<<< HEAD | ||
5600 | |||
5601 | ======= | ||
5379 | /* | 5602 | /* |
5603 | >>>>>>> avn/ubitvar | ||
5380 | if (data.ParentGroup.IsAttachment) | 5604 | if (data.ParentGroup.IsAttachment) |
5381 | { | 5605 | { |
5382 | update.NameValue = Util.StringToBytes256("AttachItemID STRING RW SV " + data.ParentGroup.FromItemID); | 5606 | update.NameValue |
5607 | = Util.StringToBytes256( | ||
5608 | string.Format("AttachItemID STRING RW SV {0}", data.ParentGroup.FromItemID)); | ||
5609 | |||
5383 | update.State = (byte)((data.ParentGroup.AttachmentPoint % 16) * 16 + (data.ParentGroup.AttachmentPoint / 16)); | 5610 | update.State = (byte)((data.ParentGroup.AttachmentPoint % 16) * 16 + (data.ParentGroup.AttachmentPoint / 16)); |
5611 | |||
5612 | // m_log.DebugFormat( | ||
5613 | // "[LLCLIENTVIEW]: Sending NameValue {0} for {1} {2} to {3}", | ||
5614 | // Util.UTF8.GetString(update.NameValue), data.Name, data.LocalId, Name); | ||
5615 | // | ||
5616 | // m_log.DebugFormat( | ||
5617 | // "[LLCLIENTVIEW]: Sending state {0} for {1} {2} to {3}", | ||
5618 | // update.State, data.Name, data.LocalId, Name); | ||
5384 | } | 5619 | } |
5385 | else | 5620 | else |
5386 | { | 5621 | { |
@@ -5411,10 +5646,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
5411 | } | 5646 | } |
5412 | 5647 | ||
5413 | 5648 | ||
5414 | // m_log.DebugFormat( | ||
5415 | // "[LLCLIENTVIEW]: Sending state {0} for {1} {2} to {3}", | ||
5416 | // update.State, data.Name, data.LocalId, Name); | ||
5417 | |||
5418 | update.ObjectData = objectData; | 5649 | update.ObjectData = objectData; |
5419 | update.ParentID = data.ParentID; | 5650 | update.ParentID = data.ParentID; |
5420 | update.PathBegin = data.Shape.PathBegin; | 5651 | update.PathBegin = data.Shape.PathBegin; |
@@ -5514,8 +5745,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
5514 | 5745 | ||
5515 | public ulong GetGroupPowers(UUID groupID) | 5746 | public ulong GetGroupPowers(UUID groupID) |
5516 | { | 5747 | { |
5517 | if (groupID == m_activeGroupID) | 5748 | if (groupID == ActiveGroupId) |
5518 | return m_activeGroupPowers; | 5749 | return ActiveGroupPowers; |
5519 | 5750 | ||
5520 | if (m_groupPowers.ContainsKey(groupID)) | 5751 | if (m_groupPowers.ContainsKey(groupID)) |
5521 | return m_groupPowers[groupID]; | 5752 | return m_groupPowers[groupID]; |
@@ -5545,10 +5776,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
5545 | AddLocalPacketHandler(PacketType.ParcelBuy, HandleParcelBuyRequest, false); | 5776 | AddLocalPacketHandler(PacketType.ParcelBuy, HandleParcelBuyRequest, false); |
5546 | AddLocalPacketHandler(PacketType.UUIDGroupNameRequest, HandleUUIDGroupNameRequest); | 5777 | AddLocalPacketHandler(PacketType.UUIDGroupNameRequest, HandleUUIDGroupNameRequest); |
5547 | AddLocalPacketHandler(PacketType.ObjectGroup, HandleObjectGroupRequest); | 5778 | AddLocalPacketHandler(PacketType.ObjectGroup, HandleObjectGroupRequest); |
5548 | AddLocalPacketHandler(PacketType.GenericMessage, HandleGenericMessage); | 5779 | AddLocalPacketHandler(PacketType.GenericMessage, HandleGenericMessage, true, true); |
5549 | AddLocalPacketHandler(PacketType.AvatarPropertiesRequest, HandleAvatarPropertiesRequest); | 5780 | AddLocalPacketHandler(PacketType.AvatarPropertiesRequest, HandleAvatarPropertiesRequest, true, true); |
5550 | AddLocalPacketHandler(PacketType.ChatFromViewer, HandleChatFromViewer); | 5781 | AddLocalPacketHandler(PacketType.ChatFromViewer, HandleChatFromViewer); |
5551 | AddLocalPacketHandler(PacketType.AvatarPropertiesUpdate, HandlerAvatarPropertiesUpdate); | 5782 | AddLocalPacketHandler(PacketType.AvatarPropertiesUpdate, HandlerAvatarPropertiesUpdate, true, true); |
5552 | AddLocalPacketHandler(PacketType.ScriptDialogReply, HandlerScriptDialogReply); | 5783 | AddLocalPacketHandler(PacketType.ScriptDialogReply, HandlerScriptDialogReply); |
5553 | AddLocalPacketHandler(PacketType.ImprovedInstantMessage, HandlerImprovedInstantMessage); | 5784 | AddLocalPacketHandler(PacketType.ImprovedInstantMessage, HandlerImprovedInstantMessage); |
5554 | AddLocalPacketHandler(PacketType.AcceptFriendship, HandlerAcceptFriendship); | 5785 | AddLocalPacketHandler(PacketType.AcceptFriendship, HandlerAcceptFriendship); |
@@ -5734,8 +5965,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
5734 | AddLocalPacketHandler(PacketType.PickDelete, HandlePickDelete); | 5965 | AddLocalPacketHandler(PacketType.PickDelete, HandlePickDelete); |
5735 | AddLocalPacketHandler(PacketType.PickGodDelete, HandlePickGodDelete); | 5966 | AddLocalPacketHandler(PacketType.PickGodDelete, HandlePickGodDelete); |
5736 | AddLocalPacketHandler(PacketType.PickInfoUpdate, HandlePickInfoUpdate); | 5967 | AddLocalPacketHandler(PacketType.PickInfoUpdate, HandlePickInfoUpdate); |
5737 | AddLocalPacketHandler(PacketType.AvatarNotesUpdate, HandleAvatarNotesUpdate); | 5968 | AddLocalPacketHandler(PacketType.AvatarNotesUpdate, HandleAvatarNotesUpdate, true, true); |
5738 | AddLocalPacketHandler(PacketType.AvatarInterestsUpdate, HandleAvatarInterestsUpdate); | 5969 | AddLocalPacketHandler(PacketType.AvatarInterestsUpdate, HandleAvatarInterestsUpdate, true, true); |
5739 | AddLocalPacketHandler(PacketType.GrantUserRights, HandleGrantUserRights); | 5970 | AddLocalPacketHandler(PacketType.GrantUserRights, HandleGrantUserRights); |
5740 | AddLocalPacketHandler(PacketType.PlacesQuery, HandlePlacesQuery); | 5971 | AddLocalPacketHandler(PacketType.PlacesQuery, HandlePlacesQuery); |
5741 | AddLocalPacketHandler(PacketType.UpdateMuteListEntry, HandleUpdateMuteListEntry); | 5972 | AddLocalPacketHandler(PacketType.UpdateMuteListEntry, HandleUpdateMuteListEntry); |
@@ -7332,7 +7563,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
7332 | { | 7563 | { |
7333 | handlerObjectDuplicate(dupe.ObjectData[i].ObjectLocalID, dupe.SharedData.Offset, | 7564 | handlerObjectDuplicate(dupe.ObjectData[i].ObjectLocalID, dupe.SharedData.Offset, |
7334 | dupe.SharedData.DuplicateFlags, AgentId, | 7565 | dupe.SharedData.DuplicateFlags, AgentId, |
7335 | m_activeGroupID); | 7566 | ActiveGroupId); |
7336 | } | 7567 | } |
7337 | } | 7568 | } |
7338 | 7569 | ||
@@ -7949,7 +8180,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
7949 | if (handlerObjectDuplicateOnRay != null) | 8180 | if (handlerObjectDuplicateOnRay != null) |
7950 | { | 8181 | { |
7951 | handlerObjectDuplicateOnRay(dupeOnRay.ObjectData[i].ObjectLocalID, dupeOnRay.AgentData.DuplicateFlags, | 8182 | handlerObjectDuplicateOnRay(dupeOnRay.ObjectData[i].ObjectLocalID, dupeOnRay.AgentData.DuplicateFlags, |
7952 | AgentId, m_activeGroupID, dupeOnRay.AgentData.RayTargetID, dupeOnRay.AgentData.RayEnd, | 8183 | AgentId, ActiveGroupId, dupeOnRay.AgentData.RayTargetID, dupeOnRay.AgentData.RayEnd, |
7953 | dupeOnRay.AgentData.RayStart, dupeOnRay.AgentData.BypassRaycast, dupeOnRay.AgentData.RayEndIsIntersection, | 8184 | dupeOnRay.AgentData.RayStart, dupeOnRay.AgentData.BypassRaycast, dupeOnRay.AgentData.RayEndIsIntersection, |
7954 | dupeOnRay.AgentData.CopyCenters, dupeOnRay.AgentData.CopyRotates); | 8185 | dupeOnRay.AgentData.CopyCenters, dupeOnRay.AgentData.CopyRotates); |
7955 | } | 8186 | } |
@@ -8154,7 +8385,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
8154 | { | 8385 | { |
8155 | // This requests the asset if needed | 8386 | // This requests the asset if needed |
8156 | HandleSimInventoryTransferRequestWithPermsCheck(sender, transfer); | 8387 | HandleSimInventoryTransferRequestWithPermsCheck(sender, transfer); |
8157 | }); | 8388 | }, null, "LLClientView.HandleTransferRequest"); |
8389 | |||
8158 | return true; | 8390 | return true; |
8159 | } | 8391 | } |
8160 | } | 8392 | } |
@@ -9103,7 +9335,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
9103 | if (aCircuit != null && aCircuit.ServiceURLs != null && aCircuit.ServiceURLs.ContainsKey("AssetServerURI")) | 9335 | if (aCircuit != null && aCircuit.ServiceURLs != null && aCircuit.ServiceURLs.ContainsKey("AssetServerURI")) |
9104 | { | 9336 | { |
9105 | string assetServer = aCircuit.ServiceURLs["AssetServerURI"].ToString(); | 9337 | string assetServer = aCircuit.ServiceURLs["AssetServerURI"].ToString(); |
9106 | return ((Scene)Scene).AssetService.Get(assetServer + "/" + id); | 9338 | if (!string.IsNullOrEmpty(assetServer)) |
9339 | return ((Scene)Scene).AssetService.Get(assetServer + "/" + id); | ||
9107 | } | 9340 | } |
9108 | 9341 | ||
9109 | return null; | 9342 | return null; |
@@ -9132,7 +9365,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
9132 | if ((locX >= m_scene.RegionInfo.WorldLocX) | 9365 | if ((locX >= m_scene.RegionInfo.WorldLocX) |
9133 | && (locX < (m_scene.RegionInfo.WorldLocX + m_scene.RegionInfo.RegionSizeX)) | 9366 | && (locX < (m_scene.RegionInfo.WorldLocX + m_scene.RegionInfo.RegionSizeX)) |
9134 | && (locY >= m_scene.RegionInfo.WorldLocY) | 9367 | && (locY >= m_scene.RegionInfo.WorldLocY) |
9368 | <<<<<<< HEAD | ||
9369 | && (locY < (m_scene.RegionInfo.WorldLocY + m_scene.RegionInfo.RegionSizeY)) ) | ||
9370 | ======= | ||
9135 | && (locY < (m_scene.RegionInfo.WorldLocY + m_scene.RegionInfo.RegionSizeY))) | 9371 | && (locY < (m_scene.RegionInfo.WorldLocY + m_scene.RegionInfo.RegionSizeY))) |
9372 | >>>>>>> avn/ubitvar | ||
9136 | { | 9373 | { |
9137 | tpLocReq.Info.RegionHandle = m_scene.RegionInfo.RegionHandle; | 9374 | tpLocReq.Info.RegionHandle = m_scene.RegionInfo.RegionHandle; |
9138 | tpLocReq.Info.Position.X += locX - m_scene.RegionInfo.WorldLocX; | 9375 | tpLocReq.Info.Position.X += locX - m_scene.RegionInfo.WorldLocX; |
@@ -9977,6 +10214,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
9977 | } | 10214 | } |
9978 | return true; | 10215 | return true; |
9979 | 10216 | ||
10217 | case "kickestate": | ||
10218 | |||
10219 | if(((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) | ||
10220 | { | ||
10221 | UUID invoice = messagePacket.MethodData.Invoice; | ||
10222 | UUID SenderID = messagePacket.AgentData.AgentID; | ||
10223 | UUID Prey; | ||
10224 | |||
10225 | UUID.TryParse(Utils.BytesToString(messagePacket.ParamList[0].Parameter), out Prey); | ||
10226 | |||
10227 | OnEstateTeleportOneUserHomeRequest(this, invoice, SenderID, Prey); | ||
10228 | } | ||
10229 | return true; | ||
10230 | |||
9980 | default: | 10231 | default: |
9981 | m_log.WarnFormat( | 10232 | m_log.WarnFormat( |
9982 | "[LLCLIENTVIEW]: EstateOwnerMessage: Unknown method {0} requested for {1} in {2}", | 10233 | "[LLCLIENTVIEW]: EstateOwnerMessage: Unknown method {0} requested for {1} in {2}", |
@@ -10654,7 +10905,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
10654 | handlerDirFindQuery(this, | 10905 | handlerDirFindQuery(this, |
10655 | dirFindQueryPacket.QueryData.QueryID, | 10906 | dirFindQueryPacket.QueryData.QueryID, |
10656 | Utils.BytesToString( | 10907 | Utils.BytesToString( |
10657 | dirFindQueryPacket.QueryData.QueryText), | 10908 | dirFindQueryPacket.QueryData.QueryText).Trim(), |
10658 | dirFindQueryPacket.QueryData.QueryFlags, | 10909 | dirFindQueryPacket.QueryData.QueryFlags, |
10659 | dirFindQueryPacket.QueryData.QueryStart); | 10910 | dirFindQueryPacket.QueryData.QueryStart); |
10660 | } | 10911 | } |
@@ -12037,22 +12288,79 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
12037 | /*protected bool HandleAgentTextureCached(IClientAPI simclient, Packet packet) | 12288 | /*protected bool HandleAgentTextureCached(IClientAPI simclient, Packet packet) |
12038 | { | 12289 | { |
12039 | AgentCachedTexturePacket cachedtex = (AgentCachedTexturePacket)packet; | 12290 | AgentCachedTexturePacket cachedtex = (AgentCachedTexturePacket)packet; |
12291 | AgentCachedTextureResponsePacket cachedresp = (AgentCachedTextureResponsePacket)PacketPool.Instance.GetPacket(PacketType.AgentCachedTextureResponse); | ||
12040 | 12292 | ||
12041 | if (cachedtex.AgentData.SessionID != SessionId) | 12293 | if (cachedtex.AgentData.SessionID != SessionId) |
12042 | return false; | 12294 | return false; |
12043 | 12295 | ||
12044 | 12296 | ||
12045 | List<CachedTextureRequestArg> requestArgs = new List<CachedTextureRequestArg>(); | ||
12046 | 12297 | ||
12047 | for (int i = 0; i < cachedtex.WearableData.Length; i++) | 12298 | // TODO: don't create new blocks if recycling an old packet |
12299 | cachedresp.AgentData.AgentID = AgentId; | ||
12300 | cachedresp.AgentData.SessionID = m_sessionId; | ||
12301 | cachedresp.AgentData.SerialNum = m_cachedTextureSerial; | ||
12302 | m_cachedTextureSerial++; | ||
12303 | cachedresp.WearableData = | ||
12304 | new AgentCachedTextureResponsePacket.WearableDataBlock[cachedtex.WearableData.Length]; | ||
12305 | |||
12306 | int maxWearablesLoop = cachedtex.WearableData.Length; | ||
12307 | if (maxWearablesLoop > AvatarWearable.MAX_WEARABLES) | ||
12308 | maxWearablesLoop = AvatarWearable.MAX_WEARABLES; | ||
12309 | |||
12310 | // Find the cached baked textures for this user, if they're available | ||
12311 | |||
12312 | IAssetService cache = m_scene.AssetService; | ||
12313 | IBakedTextureModule bakedTextureModule = m_scene.RequestModuleInterface<IBakedTextureModule>(); | ||
12314 | |||
12315 | WearableCacheItem[] cacheItems = null; | ||
12316 | |||
12317 | if (bakedTextureModule != null && cache != null) | ||
12048 | { | 12318 | { |
12049 | CachedTextureRequestArg arg = new CachedTextureRequestArg(); | 12319 | ScenePresence p = m_scene.GetScenePresence(AgentId); |
12050 | arg.BakedTextureIndex = cachedtex.WearableData[i].TextureIndex; | 12320 | if (p.Appearance != null) |
12051 | arg.WearableHashID = cachedtex.WearableData[i].ID; | 12321 | { |
12052 | 12322 | if (p.Appearance.WearableCacheItems == null || p.Appearance.WearableCacheItemsDirty) | |
12053 | requestArgs.Add(arg); | 12323 | { |
12324 | try | ||
12325 | { | ||
12326 | cacheItems = bakedTextureModule.Get(AgentId); | ||
12327 | p.Appearance.WearableCacheItems = cacheItems; | ||
12328 | p.Appearance.WearableCacheItemsDirty = false; | ||
12329 | } | ||
12330 | catch (Exception) | ||
12331 | { | ||
12332 | cacheItems = null; | ||
12333 | } | ||
12334 | |||
12335 | } | ||
12336 | else if (p.Appearance.WearableCacheItems != null) | ||
12337 | { | ||
12338 | cacheItems = p.Appearance.WearableCacheItems; | ||
12339 | } | ||
12340 | } | ||
12054 | } | 12341 | } |
12055 | 12342 | ||
12343 | <<<<<<< HEAD | ||
12344 | if (cacheItems != null) | ||
12345 | { | ||
12346 | // We need to make sure the asset stored in the bake is available on this server also by its assetid before we map it to a Cacheid. | ||
12347 | // Copy the baked textures to the sim's assets cache (local only). | ||
12348 | foreach (WearableCacheItem item in cacheItems) | ||
12349 | { | ||
12350 | if (cache.GetCached(item.TextureID.ToString()) == null) | ||
12351 | { | ||
12352 | item.TextureAsset.Temporary = true; | ||
12353 | item.TextureAsset.Local = true; | ||
12354 | cache.Store(item.TextureAsset); | ||
12355 | } | ||
12356 | } | ||
12357 | |||
12358 | // Return the cached textures | ||
12359 | for (int i = 0; i < maxWearablesLoop; i++) | ||
12360 | { | ||
12361 | WearableCacheItem item = | ||
12362 | WearableCacheItem.SearchTextureIndex(cachedtex.WearableData[i].TextureIndex, cacheItems); | ||
12363 | ======= | ||
12056 | CachedTextureRequest handlerCachedTextureRequest = OnCachedTextureRequest; | 12364 | CachedTextureRequest handlerCachedTextureRequest = OnCachedTextureRequest; |
12057 | if (handlerCachedTextureRequest != null) | 12365 | if (handlerCachedTextureRequest != null) |
12058 | { | 12366 | { |
@@ -12100,14 +12408,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
12100 | for (int i = 0; i < maxWearablesLoop; i++) | 12408 | for (int i = 0; i < maxWearablesLoop; i++) |
12101 | { | 12409 | { |
12102 | int idx = cachedtex.WearableData[i].TextureIndex; | 12410 | int idx = cachedtex.WearableData[i].TextureIndex; |
12411 | >>>>>>> avn/ubitvar | ||
12103 | 12412 | ||
12104 | cachedresp.WearableData[i] = new AgentCachedTextureResponsePacket.WearableDataBlock(); | 12413 | cachedresp.WearableData[i] = new AgentCachedTextureResponsePacket.WearableDataBlock(); |
12105 | cachedresp.WearableData[i].TextureIndex = cachedtex.WearableData[i].TextureIndex; | 12414 | cachedresp.WearableData[i].TextureIndex = cachedtex.WearableData[i].TextureIndex; |
12106 | cachedresp.WearableData[i].HostName = new byte[0]; | 12415 | cachedresp.WearableData[i].HostName = new byte[0]; |
12416 | <<<<<<< HEAD | ||
12417 | if (item != null && cachedtex.WearableData[i].ID == item.CacheId) | ||
12418 | { | ||
12419 | cachedresp.WearableData[i].TextureID = item.TextureID; | ||
12420 | ======= | ||
12107 | if (cachedtex.WearableData[i].ID == cacheItems[idx].CacheId) | 12421 | if (cachedtex.WearableData[i].ID == cacheItems[idx].CacheId) |
12108 | { | 12422 | { |
12109 | cachedresp.WearableData[i].TextureID = cacheItems[idx].TextureID; | 12423 | cachedresp.WearableData[i].TextureID = cacheItems[idx].TextureID; |
12110 | cacheHits++; | 12424 | cacheHits++; |
12425 | >>>>>>> avn/ubitvar | ||
12111 | } | 12426 | } |
12112 | else | 12427 | else |
12113 | { | 12428 | { |
@@ -12117,11 +12432,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
12117 | } | 12432 | } |
12118 | else | 12433 | else |
12119 | { | 12434 | { |
12435 | <<<<<<< HEAD | ||
12436 | // Cached textures not available | ||
12437 | ======= | ||
12438 | >>>>>>> avn/ubitvar | ||
12120 | for (int i = 0; i < maxWearablesLoop; i++) | 12439 | for (int i = 0; i < maxWearablesLoop; i++) |
12121 | { | 12440 | { |
12122 | cachedresp.WearableData[i] = new AgentCachedTextureResponsePacket.WearableDataBlock(); | 12441 | cachedresp.WearableData[i] = new AgentCachedTextureResponsePacket.WearableDataBlock(); |
12123 | cachedresp.WearableData[i].TextureIndex = cachedtex.WearableData[i].TextureIndex; | 12442 | cachedresp.WearableData[i].TextureIndex = cachedtex.WearableData[i].TextureIndex; |
12124 | cachedresp.WearableData[i].TextureID = UUID.Zero; | 12443 | cachedresp.WearableData[i].TextureID = UUID.Zero; |
12444 | <<<<<<< HEAD | ||
12445 | cachedresp.WearableData[i].HostName = new byte[0]; | ||
12446 | } | ||
12447 | } | ||
12448 | |||
12449 | ======= | ||
12125 | //UUID.Parse("8334fb6e-c2f5-46ee-807d-a435f61a8d46"); | 12450 | //UUID.Parse("8334fb6e-c2f5-46ee-807d-a435f61a8d46"); |
12126 | cachedresp.WearableData[i].HostName = new byte[0]; | 12451 | cachedresp.WearableData[i].HostName = new byte[0]; |
12127 | } | 12452 | } |
@@ -12129,6 +12454,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
12129 | 12454 | ||
12130 | m_log.DebugFormat("texture cached: hits {0}", cacheHits); | 12455 | m_log.DebugFormat("texture cached: hits {0}", cacheHits); |
12131 | 12456 | ||
12457 | >>>>>>> avn/ubitvar | ||
12132 | cachedresp.Header.Zerocoded = true; | 12458 | cachedresp.Header.Zerocoded = true; |
12133 | OutPacket(cachedresp, ThrottleOutPacketType.Task); | 12459 | OutPacket(cachedresp, ThrottleOutPacketType.Task); |
12134 | 12460 | ||
@@ -12483,6 +12809,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
12483 | /// provide your own method.</param> | 12809 | /// provide your own method.</param> |
12484 | protected void OutPacket(Packet packet, ThrottleOutPacketType throttlePacketType, bool doAutomaticSplitting, UnackedPacketMethod method) | 12810 | protected void OutPacket(Packet packet, ThrottleOutPacketType throttlePacketType, bool doAutomaticSplitting, UnackedPacketMethod method) |
12485 | { | 12811 | { |
12812 | if (m_outPacketsToDrop != null) | ||
12813 | if (m_outPacketsToDrop.Contains(packet.Type.ToString())) | ||
12814 | return; | ||
12815 | |||
12486 | if (DebugPacketLevel > 0) | 12816 | if (DebugPacketLevel > 0) |
12487 | { | 12817 | { |
12488 | bool logPacket = true; | 12818 | bool logPacket = true; |
@@ -12541,6 +12871,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
12541 | /// <param name="Pack">OpenMetaverse.packet</param> | 12871 | /// <param name="Pack">OpenMetaverse.packet</param> |
12542 | public void ProcessInPacket(Packet packet) | 12872 | public void ProcessInPacket(Packet packet) |
12543 | { | 12873 | { |
12874 | if (m_inPacketsToDrop != null) | ||
12875 | if (m_inPacketsToDrop.Contains(packet.Type.ToString())) | ||
12876 | return; | ||
12877 | |||
12544 | if (DebugPacketLevel > 0) | 12878 | if (DebugPacketLevel > 0) |
12545 | { | 12879 | { |
12546 | bool logPacket = true; | 12880 | bool logPacket = true; |
@@ -12831,16 +13165,33 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
12831 | 13165 | ||
12832 | if (asset == null) | 13166 | if (asset == null) |
12833 | { | 13167 | { |
12834 | req.AssetInf = null; | 13168 | // Try the user's asset server |
12835 | req.AssetRequestSource = source; | 13169 | IInventoryAccessModule inventoryAccessModule = Scene.RequestModuleInterface<IInventoryAccessModule>(); |
12836 | req.IsTextureRequest = false; | 13170 | |
12837 | req.NumPackets = 0; | 13171 | string assetServerURL = string.Empty; |
12838 | req.Params = transferRequest.TransferInfo.Params; | 13172 | if (inventoryAccessModule.IsForeignUser(AgentId, out assetServerURL) && !string.IsNullOrEmpty(assetServerURL)) |
12839 | req.RequestAssetID = requestID; | 13173 | { |
12840 | req.TransferRequestID = transferRequest.TransferInfo.TransferID; | 13174 | if (!assetServerURL.EndsWith("/") && !assetServerURL.EndsWith("=")) |
13175 | assetServerURL = assetServerURL + "/"; | ||
13176 | |||
13177 | //m_log.DebugFormat("[LLCLIENTVIEW]: asset {0} not found in local storage. Trying user's storage.", assetServerURL + id); | ||
13178 | asset = m_scene.AssetService.Get(assetServerURL + id); | ||
13179 | } | ||
13180 | |||
13181 | if (asset == null) | ||
13182 | { | ||
13183 | req.AssetInf = null; | ||
13184 | req.AssetRequestSource = source; | ||
13185 | req.IsTextureRequest = false; | ||
13186 | req.NumPackets = 0; | ||
13187 | req.Params = transferRequest.TransferInfo.Params; | ||
13188 | req.RequestAssetID = requestID; | ||
13189 | req.TransferRequestID = transferRequest.TransferInfo.TransferID; | ||
13190 | |||
13191 | SendAssetNotFound(req); | ||
13192 | return; | ||
13193 | } | ||
12841 | 13194 | ||
12842 | SendAssetNotFound(req); | ||
12843 | return; | ||
12844 | } | 13195 | } |
12845 | 13196 | ||
12846 | if (transferRequest.TransferInfo.SourceType == (int)SourceType.Asset) | 13197 | if (transferRequest.TransferInfo.SourceType == (int)SourceType.Asset) |
@@ -12907,8 +13258,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
12907 | 13258 | ||
12908 | public struct PacketProcessor | 13259 | public struct PacketProcessor |
12909 | { | 13260 | { |
12910 | public PacketMethod method; | 13261 | /// <summary> |
12911 | public bool Async; | 13262 | /// Packet handling method. |
13263 | /// </summary> | ||
13264 | public PacketMethod method { get; set; } | ||
13265 | |||
13266 | /// <summary> | ||
13267 | /// Should this packet be handled asynchronously? | ||
13268 | /// </summary> | ||
13269 | public bool Async { get; set; } | ||
13270 | |||
13271 | /// <summary> | ||
13272 | /// If async is true, should this packet be handled in the async engine or given directly to a threadpool | ||
13273 | /// thread? | ||
13274 | /// </summary> | ||
13275 | public bool InEngine { get; set; } | ||
12912 | } | 13276 | } |
12913 | 13277 | ||
12914 | public class AsyncPacketProcess | 13278 | public class AsyncPacketProcess |
@@ -13252,5 +13616,51 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
13252 | eq.Enqueue(BuildEvent("BulkUpdateInventory", | 13616 | eq.Enqueue(BuildEvent("BulkUpdateInventory", |
13253 | llsd), AgentId); | 13617 | llsd), AgentId); |
13254 | } | 13618 | } |
13619 | |||
13620 | private HashSet<string> m_outPacketsToDrop; | ||
13621 | |||
13622 | public bool AddOutPacketToDropSet(string packetName) | ||
13623 | { | ||
13624 | if (m_outPacketsToDrop == null) | ||
13625 | m_outPacketsToDrop = new HashSet<string>(); | ||
13626 | |||
13627 | return m_outPacketsToDrop.Add(packetName); | ||
13628 | } | ||
13629 | |||
13630 | public bool RemoveOutPacketFromDropSet(string packetName) | ||
13631 | { | ||
13632 | if (m_outPacketsToDrop == null) | ||
13633 | return false; | ||
13634 | |||
13635 | return m_outPacketsToDrop.Remove(packetName); | ||
13636 | } | ||
13637 | |||
13638 | public HashSet<string> GetOutPacketDropSet() | ||
13639 | { | ||
13640 | return new HashSet<string>(m_outPacketsToDrop); | ||
13641 | } | ||
13642 | |||
13643 | private HashSet<string> m_inPacketsToDrop; | ||
13644 | |||
13645 | public bool AddInPacketToDropSet(string packetName) | ||
13646 | { | ||
13647 | if (m_inPacketsToDrop == null) | ||
13648 | m_inPacketsToDrop = new HashSet<string>(); | ||
13649 | |||
13650 | return m_inPacketsToDrop.Add(packetName); | ||
13651 | } | ||
13652 | |||
13653 | public bool RemoveInPacketFromDropSet(string packetName) | ||
13654 | { | ||
13655 | if (m_inPacketsToDrop == null) | ||
13656 | return false; | ||
13657 | |||
13658 | return m_inPacketsToDrop.Remove(packetName); | ||
13659 | } | ||
13660 | |||
13661 | public HashSet<string> GetInPacketDropSet() | ||
13662 | { | ||
13663 | return new HashSet<string>(m_inPacketsToDrop); | ||
13664 | } | ||
13255 | } | 13665 | } |
13256 | } | 13666 | } |
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs index 4b541e6..9293882 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs | |||
@@ -76,6 +76,33 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
76 | /// or removed, this number must also change</summary> | 76 | /// or removed, this number must also change</summary> |
77 | const int THROTTLE_CATEGORY_COUNT = 8; | 77 | const int THROTTLE_CATEGORY_COUNT = 8; |
78 | 78 | ||
79 | /// <summary> | ||
80 | /// Controls whether information is logged about each outbound packet immediately before it is sent. For debug purposes. | ||
81 | /// </summary> | ||
82 | /// <remarks>Any level above 0 will turn on logging.</remarks> | ||
83 | public int DebugDataOutLevel { get; set; } | ||
84 | |||
85 | /// <summary> | ||
86 | /// Controls whether information is logged about each outbound packet immediately before it is sent. For debug purposes. | ||
87 | /// </summary> | ||
88 | /// <remarks>Any level above 0 will turn on logging.</remarks> | ||
89 | public int ThrottleDebugLevel | ||
90 | { | ||
91 | get | ||
92 | { | ||
93 | return m_throttleDebugLevel; | ||
94 | } | ||
95 | |||
96 | set | ||
97 | { | ||
98 | m_throttleDebugLevel = value; | ||
99 | m_throttleClient.DebugLevel = m_throttleDebugLevel; | ||
100 | foreach (TokenBucket tb in m_throttleCategories) | ||
101 | tb.DebugLevel = m_throttleDebugLevel; | ||
102 | } | ||
103 | } | ||
104 | private int m_throttleDebugLevel; | ||
105 | |||
79 | /// <summary>Fired when updated networking stats are produced for this client</summary> | 106 | /// <summary>Fired when updated networking stats are produced for this client</summary> |
80 | public event PacketStats OnPacketStats; | 107 | public event PacketStats OnPacketStats; |
81 | /// <summary>Fired when the queue for a packet category is empty. This event can be | 108 | /// <summary>Fired when the queue for a packet category is empty. This event can be |
@@ -92,8 +119,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
92 | public readonly uint CircuitCode; | 119 | public readonly uint CircuitCode; |
93 | /// <summary>Sequence numbers of packets we've received (for duplicate checking)</summary> | 120 | /// <summary>Sequence numbers of packets we've received (for duplicate checking)</summary> |
94 | public readonly IncomingPacketHistoryCollection PacketArchive = new IncomingPacketHistoryCollection(200); | 121 | public readonly IncomingPacketHistoryCollection PacketArchive = new IncomingPacketHistoryCollection(200); |
122 | |||
123 | /// <summary> | ||
124 | /// If true then we take action in response to unacked reliably sent packets such as resending the packet. | ||
125 | /// </summary> | ||
126 | public bool ProcessUnackedSends { get; set; } | ||
127 | |||
95 | /// <summary>Packets we have sent that need to be ACKed by the client</summary> | 128 | /// <summary>Packets we have sent that need to be ACKed by the client</summary> |
96 | public readonly UnackedPacketCollection NeedAcks = new UnackedPacketCollection(); | 129 | public readonly UnackedPacketCollection NeedAcks = new UnackedPacketCollection(); |
130 | |||
97 | /// <summary>ACKs that are queued up, waiting to be sent to the client</summary> | 131 | /// <summary>ACKs that are queued up, waiting to be sent to the client</summary> |
98 | public readonly DoubleLocklessQueue<uint> PendingAcks = new DoubleLocklessQueue<uint>(); | 132 | public readonly DoubleLocklessQueue<uint> PendingAcks = new DoubleLocklessQueue<uint>(); |
99 | 133 | ||
@@ -216,11 +250,22 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
216 | if (maxRTO != 0) | 250 | if (maxRTO != 0) |
217 | m_maxRTO = maxRTO; | 251 | m_maxRTO = maxRTO; |
218 | 252 | ||
253 | <<<<<<< HEAD | ||
254 | ProcessUnackedSends = true; | ||
255 | |||
256 | // Create a token bucket throttle for this client that has the scene token bucket as a parent | ||
257 | m_throttleClient | ||
258 | = new AdaptiveTokenBucket( | ||
259 | string.Format("adaptive throttle for {0} in {1}", AgentID, server.Scene.Name), | ||
260 | parentThrottle, 0, rates.Total, rates.MinimumAdaptiveThrottleRate, rates.AdaptiveThrottlesEnabled); | ||
261 | |||
262 | ======= | ||
219 | m_burstTime = rates.BrustTime; | 263 | m_burstTime = rates.BrustTime; |
220 | float m_burst = rates.ClientMaxRate * m_burstTime; | 264 | float m_burst = rates.ClientMaxRate * m_burstTime; |
221 | 265 | ||
222 | // Create a token bucket throttle for this client that has the scene token bucket as a parent | 266 | // Create a token bucket throttle for this client that has the scene token bucket as a parent |
223 | m_throttleClient = new AdaptiveTokenBucket(parentThrottle, rates.ClientMaxRate, m_burst, rates.AdaptiveThrottlesEnabled); | 267 | m_throttleClient = new AdaptiveTokenBucket(parentThrottle, rates.ClientMaxRate, m_burst, rates.AdaptiveThrottlesEnabled); |
268 | >>>>>>> avn/ubitvar | ||
224 | // Create an array of token buckets for this clients different throttle categories | 269 | // Create an array of token buckets for this clients different throttle categories |
225 | m_throttleCategories = new TokenBucket[THROTTLE_CATEGORY_COUNT]; | 270 | m_throttleCategories = new TokenBucket[THROTTLE_CATEGORY_COUNT]; |
226 | 271 | ||
@@ -233,9 +278,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
233 | ThrottleOutPacketType type = (ThrottleOutPacketType)i; | 278 | ThrottleOutPacketType type = (ThrottleOutPacketType)i; |
234 | 279 | ||
235 | // Initialize the packet outboxes, where packets sit while they are waiting for tokens | 280 | // Initialize the packet outboxes, where packets sit while they are waiting for tokens |
281 | <<<<<<< HEAD | ||
282 | m_packetOutboxes[i] = new OpenSim.Framework.LocklessQueue<OutgoingPacket>(); | ||
283 | |||
284 | // Initialize the token buckets that control the throttling for each category | ||
285 | m_throttleCategories[i] | ||
286 | = new TokenBucket( | ||
287 | string.Format("{0} throttle for {1} in {2}", type, AgentID, server.Scene.Name), | ||
288 | m_throttleClient, rates.GetRate(type), 0); | ||
289 | ======= | ||
236 | m_packetOutboxes[i] = new DoubleLocklessQueue<OutgoingPacket>(); | 290 | m_packetOutboxes[i] = new DoubleLocklessQueue<OutgoingPacket>(); |
237 | // Initialize the token buckets that control the throttling for each category | 291 | // Initialize the token buckets that control the throttling for each category |
238 | m_throttleCategories[i] = new TokenBucket(m_throttleClient, rates.GetRate(type), m_burst); | 292 | m_throttleCategories[i] = new TokenBucket(m_throttleClient, rates.GetRate(type), m_burst); |
293 | >>>>>>> avn/ubitvar | ||
239 | } | 294 | } |
240 | 295 | ||
241 | // Default the retransmission timeout to one second | 296 | // Default the retransmission timeout to one second |
@@ -282,6 +337,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
282 | m_info.assetThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Asset].DripRate; | 337 | m_info.assetThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Asset].DripRate; |
283 | m_info.textureThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Texture].DripRate; | 338 | m_info.textureThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Texture].DripRate; |
284 | m_info.totalThrottle = (int)m_throttleClient.DripRate; | 339 | m_info.totalThrottle = (int)m_throttleClient.DripRate; |
340 | <<<<<<< HEAD | ||
341 | m_info.targetThrottle = (int)m_throttleClient.TargetDripRate; | ||
342 | m_info.maxThrottle = (int)m_throttleClient.MaxDripRate; | ||
343 | ======= | ||
344 | >>>>>>> avn/ubitvar | ||
285 | 345 | ||
286 | return m_info; | 346 | return m_info; |
287 | } | 347 | } |
@@ -299,6 +359,33 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
299 | } | 359 | } |
300 | 360 | ||
301 | /// <summary> | 361 | /// <summary> |
362 | /// Get the total number of pakcets queued for this client. | ||
363 | /// </summary> | ||
364 | /// <returns></returns> | ||
365 | public int GetTotalPacketsQueuedCount() | ||
366 | { | ||
367 | int total = 0; | ||
368 | |||
369 | for (int i = 0; i <= (int)ThrottleOutPacketType.Asset; i++) | ||
370 | total += m_packetOutboxes[i].Count; | ||
371 | |||
372 | return total; | ||
373 | } | ||
374 | |||
375 | /// <summary> | ||
376 | /// Get the number of packets queued for the given throttle type. | ||
377 | /// </summary> | ||
378 | /// <returns></returns> | ||
379 | /// <param name="throttleType"></param> | ||
380 | public int GetPacketsQueuedCount(ThrottleOutPacketType throttleType) | ||
381 | { | ||
382 | if ((int)throttleType > 0) | ||
383 | return m_packetOutboxes[(int)throttleType].Count; | ||
384 | else | ||
385 | return 0; | ||
386 | } | ||
387 | |||
388 | /// <summary> | ||
302 | /// Return statistics information about client packet queues. | 389 | /// Return statistics information about client packet queues. |
303 | /// </summary> | 390 | /// </summary> |
304 | /// <remarks> | 391 | /// <remarks> |
@@ -373,6 +460,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
373 | int texture = (int)(BitConverter.ToSingle(adjData, pos) * scale); pos += 4; | 460 | int texture = (int)(BitConverter.ToSingle(adjData, pos) * scale); pos += 4; |
374 | int asset = (int)(BitConverter.ToSingle(adjData, pos) * scale); | 461 | int asset = (int)(BitConverter.ToSingle(adjData, pos) * scale); |
375 | 462 | ||
463 | if (ThrottleDebugLevel > 0) | ||
464 | { | ||
465 | long total = resend + land + wind + cloud + task + texture + asset; | ||
466 | m_log.DebugFormat( | ||
467 | "[LLUDPCLIENT]: {0} is setting throttles in {1} to Resend={2}, Land={3}, Wind={4}, Cloud={5}, Task={6}, Texture={7}, Asset={8}, TOTAL = {9}", | ||
468 | AgentID, m_udpServer.Scene.Name, resend, land, wind, cloud, task, texture, asset, total); | ||
469 | } | ||
470 | |||
376 | // Make sure none of the throttles are set below our packet MTU, | 471 | // Make sure none of the throttles are set below our packet MTU, |
377 | // otherwise a throttle could become permanently clogged | 472 | // otherwise a throttle could become permanently clogged |
378 | 473 | ||
@@ -391,6 +486,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
391 | // the task queue (e.g. object updates) | 486 | // the task queue (e.g. object updates) |
392 | task = task + (int)(m_cannibalrate * texture); | 487 | task = task + (int)(m_cannibalrate * texture); |
393 | texture = (int)((1 - m_cannibalrate) * texture); | 488 | texture = (int)((1 - m_cannibalrate) * texture); |
489 | <<<<<<< HEAD | ||
490 | |||
491 | //int total = resend + land + wind + cloud + task + texture + asset; | ||
492 | |||
493 | if (ThrottleDebugLevel > 0) | ||
494 | { | ||
495 | long total = resend + land + wind + cloud + task + texture + asset; | ||
496 | m_log.DebugFormat( | ||
497 | "[LLUDPCLIENT]: {0} is setting throttles in {1} to Resend={2}, Land={3}, Wind={4}, Cloud={5}, Task={6}, Texture={7}, Asset={8}, TOTAL = {9}", | ||
498 | AgentID, m_udpServer.Scene.Name, resend, land, wind, cloud, task, texture, asset, total); | ||
499 | } | ||
500 | ======= | ||
394 | 501 | ||
395 | int total = resend + land + wind + cloud + task + texture + asset; | 502 | int total = resend + land + wind + cloud + task + texture + asset; |
396 | 503 | ||
@@ -398,8 +505,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
398 | 505 | ||
399 | //m_log.DebugFormat("[LLUDPCLIENT]: {0} is setting throttles. Resend={1}, Land={2}, Wind={3}, Cloud={4}, Task={5}, Texture={6}, Asset={7}, Total={8}", | 506 | //m_log.DebugFormat("[LLUDPCLIENT]: {0} is setting throttles. Resend={1}, Land={2}, Wind={3}, Cloud={4}, Task={5}, Texture={6}, Asset={7}, Total={8}", |
400 | // AgentID, resend, land, wind, cloud, task, texture, asset, total); | 507 | // AgentID, resend, land, wind, cloud, task, texture, asset, total); |
508 | >>>>>>> avn/ubitvar | ||
401 | 509 | ||
402 | // Update the token buckets with new throttle values | 510 | // Update the token buckets with new throttle values |
511 | if (m_throttleClient.AdaptiveEnabled) | ||
512 | { | ||
513 | long total = resend + land + wind + cloud + task + texture + asset; | ||
514 | m_throttleClient.TargetDripRate = total; | ||
515 | } | ||
516 | |||
403 | TokenBucket bucket; | 517 | TokenBucket bucket; |
404 | 518 | ||
405 | bucket = m_throttleCategories[(int)ThrottleOutPacketType.Resend]; | 519 | bucket = m_throttleCategories[(int)ThrottleOutPacketType.Resend]; |
@@ -744,8 +858,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
744 | 858 | ||
745 | if (HasUpdates(categories)) | 859 | if (HasUpdates(categories)) |
746 | { | 860 | { |
747 | // Asynchronously run the callback | 861 | if (!m_udpServer.OqrEngine.IsRunning) |
748 | Util.FireAndForget(FireQueueEmpty, categories); | 862 | { |
863 | // Asynchronously run the callback | ||
864 | Util.FireAndForget(FireQueueEmpty, categories, "LLUDPClient.BeginFireQueueEmpty"); | ||
865 | } | ||
866 | else | ||
867 | { | ||
868 | m_udpServer.OqrEngine.QueueJob(AgentID.ToString(), () => FireQueueEmpty(categories)); | ||
869 | } | ||
749 | } | 870 | } |
750 | else | 871 | else |
751 | { | 872 | { |
@@ -764,10 +885,22 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
764 | /// <param name="o">Throttle categories to fire the callback for, | 885 | /// <param name="o">Throttle categories to fire the callback for, |
765 | /// stored as an object to match the WaitCallback delegate | 886 | /// stored as an object to match the WaitCallback delegate |
766 | /// signature</param> | 887 | /// signature</param> |
767 | private void FireQueueEmpty(object o) | 888 | public void FireQueueEmpty(object o) |
768 | { | 889 | { |
890 | <<<<<<< HEAD | ||
891 | // m_log.DebugFormat("[LLUDPCLIENT]: FireQueueEmpty for {0} in {1}", AgentID, m_udpServer.Scene.Name); | ||
892 | |||
893 | // int start = Environment.TickCount & Int32.MaxValue; | ||
894 | // const int MIN_CALLBACK_MS = 30; | ||
895 | |||
896 | // if (m_udpServer.IsRunningOutbound) | ||
897 | // { | ||
898 | ThrottleOutPacketTypeFlags categories = (ThrottleOutPacketTypeFlags)o; | ||
899 | QueueEmpty callback = OnQueueEmpty; | ||
900 | ======= | ||
769 | ThrottleOutPacketTypeFlags categories = (ThrottleOutPacketTypeFlags)o; | 901 | ThrottleOutPacketTypeFlags categories = (ThrottleOutPacketTypeFlags)o; |
770 | QueueEmpty callback = OnQueueEmpty; | 902 | QueueEmpty callback = OnQueueEmpty; |
903 | >>>>>>> avn/ubitvar | ||
771 | 904 | ||
772 | if (callback != null) | 905 | if (callback != null) |
773 | { | 906 | { |
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs index b5f9da8..41e19fd 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs | |||
@@ -34,7 +34,6 @@ using System.Net.Sockets; | |||
34 | using System.Reflection; | 34 | using System.Reflection; |
35 | using System.Threading; | 35 | using System.Threading; |
36 | using log4net; | 36 | using log4net; |
37 | using NDesk.Options; | ||
38 | using Nini.Config; | 37 | using Nini.Config; |
39 | using OpenMetaverse.Packets; | 38 | using OpenMetaverse.Packets; |
40 | using OpenSim.Framework; | 39 | using OpenSim.Framework; |
@@ -181,9 +180,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
181 | scene.Name, | 180 | scene.Name, |
182 | StatType.Pull, | 181 | StatType.Pull, |
183 | MeasuresOfInterest.None, | 182 | MeasuresOfInterest.None, |
184 | stat => stat.Value = m_udpServer.AverageReceiveTicksForLastSamplePeriod / TimeSpan.TicksPerMillisecond, | 183 | stat => stat.Value = m_udpServer.AverageReceiveTicksForLastSamplePeriod, |
185 | // stat => | 184 | // stat => |
186 | // stat.Value = Math.Round(m_udpServer.AverageReceiveTicksForLastSamplePeriod / TimeSpan.TicksPerMillisecond, 7), | 185 | // stat.Value = Math.Round(m_udpServer.AverageReceiveTicksForLastSamplePeriod, 7), |
187 | StatVerbosity.Debug)); | 186 | StatVerbosity.Debug)); |
188 | } | 187 | } |
189 | 188 | ||
@@ -222,6 +221,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
222 | /// </summary> | 221 | /// </summary> |
223 | public int DefaultClientPacketDebugLevel { get; set; } | 222 | public int DefaultClientPacketDebugLevel { get; set; } |
224 | 223 | ||
224 | /// <summary> | ||
225 | /// If set then all inbound agent updates are discarded. For debugging purposes. | ||
226 | /// discard agent update. | ||
227 | /// </summary> | ||
228 | public bool DiscardInboundAgentUpdates { get; set; } | ||
229 | |||
225 | /// <summary>The measured resolution of Environment.TickCount</summary> | 230 | /// <summary>The measured resolution of Environment.TickCount</summary> |
226 | public readonly float TickCountResolution; | 231 | public readonly float TickCountResolution; |
227 | 232 | ||
@@ -240,19 +245,22 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
240 | 245 | ||
241 | private DoubleQueue<IncomingPacket> packetInbox = new DoubleQueue<IncomingPacket>(); | 246 | private DoubleQueue<IncomingPacket> packetInbox = new DoubleQueue<IncomingPacket>(); |
242 | 247 | ||
243 | /// <summary></summary> | ||
244 | //private UDPClientCollection m_clients = new UDPClientCollection(); | ||
245 | /// <summary>Bandwidth throttle for this UDP server</summary> | 248 | /// <summary>Bandwidth throttle for this UDP server</summary> |
246 | protected TokenBucket m_throttle; | 249 | public TokenBucket Throttle { get; private set; } |
247 | 250 | ||
248 | /// <summary>Bandwidth throttle rates for this UDP server</summary> | 251 | /// <summary>Per client throttle rates enforced by this server</summary> |
252 | /// <remarks> | ||
253 | /// If the total rate is non-zero, then this is the maximum total throttle setting that any client can ever have. | ||
254 | /// The other rates (resend, asset, etc.) are the defaults for a new client and can be changed (and usually | ||
255 | /// do get changed immediately). They do not need to sum to the total. | ||
256 | /// </remarks> | ||
249 | public ThrottleRates ThrottleRates { get; private set; } | 257 | public ThrottleRates ThrottleRates { get; private set; } |
250 | 258 | ||
251 | /// <summary>Manages authentication for agent circuits</summary> | 259 | /// <summary>Manages authentication for agent circuits</summary> |
252 | private AgentCircuitManager m_circuitManager; | 260 | private AgentCircuitManager m_circuitManager; |
253 | 261 | ||
254 | /// <summary>Reference to the scene this UDP server is attached to</summary> | 262 | /// <summary>Reference to the scene this UDP server is attached to</summary> |
255 | protected Scene m_scene; | 263 | public Scene Scene { get; private set; } |
256 | 264 | ||
257 | /// <summary>The X/Y coordinates of the scene this UDP server is attached to</summary> | 265 | /// <summary>The X/Y coordinates of the scene this UDP server is attached to</summary> |
258 | private Location m_location; | 266 | private Location m_location; |
@@ -375,6 +383,22 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
375 | /// </summary> | 383 | /// </summary> |
376 | private IClientAPI m_currentIncomingClient; | 384 | private IClientAPI m_currentIncomingClient; |
377 | 385 | ||
386 | /// <summary> | ||
387 | /// Queue some low priority but potentially high volume async requests so that they don't overwhelm available | ||
388 | /// threadpool threads. | ||
389 | /// </summary> | ||
390 | public JobEngine IpahEngine { get; private set; } | ||
391 | |||
392 | /// <summary> | ||
393 | /// Run queue empty processing within a single persistent thread. | ||
394 | /// </summary> | ||
395 | /// <remarks> | ||
396 | /// This is the alternative to having every | ||
397 | /// connection schedule its own job in the threadpool which causes performance problems when there are many | ||
398 | /// connections. | ||
399 | /// </remarks> | ||
400 | public JobEngine OqrEngine { get; private set; } | ||
401 | |||
378 | public LLUDPServer( | 402 | public LLUDPServer( |
379 | IPAddress listenIP, ref uint port, int proxyPortOffsetParm, bool allow_alternate_port, | 403 | IPAddress listenIP, ref uint port, int proxyPortOffsetParm, bool allow_alternate_port, |
380 | IConfigSource configSource, AgentCircuitManager circuitManager) | 404 | IConfigSource configSource, AgentCircuitManager circuitManager) |
@@ -449,7 +473,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
449 | } | 473 | } |
450 | #endregion BinaryStats | 474 | #endregion BinaryStats |
451 | 475 | ||
476 | <<<<<<< HEAD | ||
477 | // FIXME: Can't add info here because don't know scene yet. | ||
478 | // m_throttle | ||
479 | // = new TokenBucket( | ||
480 | // string.Format("server throttle bucket for {0}", Scene.Name), null, sceneThrottleBps); | ||
481 | |||
482 | Throttle = new TokenBucket("server throttle bucket", null, 0, sceneThrottleBps); | ||
483 | |||
484 | ======= | ||
452 | m_throttle = new TokenBucket(null, sceneThrottleBps, sceneThrottleBps * 10e-3f); | 485 | m_throttle = new TokenBucket(null, sceneThrottleBps, sceneThrottleBps * 10e-3f); |
486 | >>>>>>> avn/ubitvar | ||
453 | ThrottleRates = new ThrottleRates(configSource); | 487 | ThrottleRates = new ThrottleRates(configSource); |
454 | 488 | ||
455 | Random rnd = new Random(Util.EnvironmentTickCount()); | 489 | Random rnd = new Random(Util.EnvironmentTickCount()); |
@@ -463,11 +497,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
463 | { | 497 | { |
464 | StartInbound(); | 498 | StartInbound(); |
465 | StartOutbound(); | 499 | StartOutbound(); |
500 | IpahEngine.Start(); | ||
501 | OqrEngine.Start(); | ||
466 | 502 | ||
467 | m_elapsedMSSinceLastStatReport = Environment.TickCount; | 503 | m_elapsedMSSinceLastStatReport = Environment.TickCount; |
468 | } | 504 | } |
469 | 505 | ||
470 | private void StartInbound() | 506 | public void StartInbound() |
471 | { | 507 | { |
472 | m_log.InfoFormat( | 508 | m_log.InfoFormat( |
473 | "[LLUDPSERVER]: Starting inbound packet processing for the LLUDP server in {0} mode with UsePools = {1}", | 509 | "[LLUDPSERVER]: Starting inbound packet processing for the LLUDP server in {0} mode with UsePools = {1}", |
@@ -476,9 +512,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
476 | base.StartInbound(m_recvBufferSize, m_asyncPacketHandling); | 512 | base.StartInbound(m_recvBufferSize, m_asyncPacketHandling); |
477 | 513 | ||
478 | // This thread will process the packets received that are placed on the packetInbox | 514 | // This thread will process the packets received that are placed on the packetInbox |
479 | Watchdog.StartThread( | 515 | WorkManager.StartThread( |
480 | IncomingPacketHandler, | 516 | IncomingPacketHandler, |
481 | string.Format("Incoming Packets ({0})", m_scene.RegionInfo.RegionName), | 517 | string.Format("Incoming Packets ({0})", Scene.Name), |
482 | ThreadPriority.Normal, | 518 | ThreadPriority.Normal, |
483 | false, | 519 | false, |
484 | true, | 520 | true, |
@@ -486,15 +522,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
486 | Watchdog.DEFAULT_WATCHDOG_TIMEOUT_MS); | 522 | Watchdog.DEFAULT_WATCHDOG_TIMEOUT_MS); |
487 | } | 523 | } |
488 | 524 | ||
489 | private new void StartOutbound() | 525 | public override void StartOutbound() |
490 | { | 526 | { |
491 | m_log.Info("[LLUDPSERVER]: Starting outbound packet processing for the LLUDP server"); | 527 | m_log.Info("[LLUDPSERVER]: Starting outbound packet processing for the LLUDP server"); |
492 | 528 | ||
493 | base.StartOutbound(); | 529 | base.StartOutbound(); |
494 | 530 | ||
495 | Watchdog.StartThread( | 531 | WorkManager.StartThread( |
496 | OutgoingPacketHandler, | 532 | OutgoingPacketHandler, |
497 | string.Format("Outgoing Packets ({0})", m_scene.RegionInfo.RegionName), | 533 | string.Format("Outgoing Packets ({0})", Scene.Name), |
498 | ThreadPriority.Normal, | 534 | ThreadPriority.Normal, |
499 | false, | 535 | false, |
500 | true, | 536 | true, |
@@ -504,12 +540,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
504 | 540 | ||
505 | public void Stop() | 541 | public void Stop() |
506 | { | 542 | { |
507 | m_log.Info("[LLUDPSERVER]: Shutting down the LLUDP server for " + m_scene.RegionInfo.RegionName); | 543 | m_log.Info("[LLUDPSERVER]: Shutting down the LLUDP server for " + Scene.Name); |
508 | base.StopOutbound(); | 544 | base.StopOutbound(); |
509 | base.StopInbound(); | 545 | base.StopInbound(); |
546 | IpahEngine.Stop(); | ||
547 | OqrEngine.Stop(); | ||
510 | } | 548 | } |
511 | 549 | ||
512 | protected override bool EnablePools() | 550 | public override bool EnablePools() |
513 | { | 551 | { |
514 | if (!UsePools) | 552 | if (!UsePools) |
515 | { | 553 | { |
@@ -523,7 +561,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
523 | return false; | 561 | return false; |
524 | } | 562 | } |
525 | 563 | ||
526 | protected override bool DisablePools() | 564 | public override bool DisablePools() |
527 | { | 565 | { |
528 | if (UsePools) | 566 | if (UsePools) |
529 | { | 567 | { |
@@ -543,7 +581,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
543 | /// This is a seperate method so that it can be called once we have an m_scene to distinguish different scene | 581 | /// This is a seperate method so that it can be called once we have an m_scene to distinguish different scene |
544 | /// stats. | 582 | /// stats. |
545 | /// </summary> | 583 | /// </summary> |
546 | private void EnablePoolStats() | 584 | protected internal void EnablePoolStats() |
547 | { | 585 | { |
548 | m_poolCountStat | 586 | m_poolCountStat |
549 | = new Stat( | 587 | = new Stat( |
@@ -552,7 +590,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
552 | "The number of objects currently stored within the UDPPacketBuffer pool", | 590 | "The number of objects currently stored within the UDPPacketBuffer pool", |
553 | "", | 591 | "", |
554 | "clientstack", | 592 | "clientstack", |
555 | m_scene.Name, | 593 | Scene.Name, |
556 | StatType.Pull, | 594 | StatType.Pull, |
557 | stat => stat.Value = Pool.Count, | 595 | stat => stat.Value = Pool.Count, |
558 | StatVerbosity.Debug); | 596 | StatVerbosity.Debug); |
@@ -566,7 +604,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
566 | "The number of objects currently stored within the incoming packet pool", | 604 | "The number of objects currently stored within the incoming packet pool", |
567 | "", | 605 | "", |
568 | "clientstack", | 606 | "clientstack", |
569 | m_scene.Name, | 607 | Scene.Name, |
570 | StatType.Pull, | 608 | StatType.Pull, |
571 | stat => stat.Value = m_incomingPacketPool.Count, | 609 | stat => stat.Value = m_incomingPacketPool.Count, |
572 | StatVerbosity.Debug); | 610 | StatVerbosity.Debug); |
@@ -577,7 +615,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
577 | /// <summary> | 615 | /// <summary> |
578 | /// Disables pool stats. | 616 | /// Disables pool stats. |
579 | /// </summary> | 617 | /// </summary> |
580 | private void DisablePoolStats() | 618 | protected internal void DisablePoolStats() |
581 | { | 619 | { |
582 | StatsManager.DeregisterStat(m_poolCountStat); | 620 | StatsManager.DeregisterStat(m_poolCountStat); |
583 | m_poolCountStat = null; | 621 | m_poolCountStat = null; |
@@ -610,7 +648,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
610 | 648 | ||
611 | public void AddScene(IScene scene) | 649 | public void AddScene(IScene scene) |
612 | { | 650 | { |
613 | if (m_scene != null) | 651 | if (Scene != null) |
614 | { | 652 | { |
615 | m_log.Error("[LLUDPSERVER]: AddScene() called on an LLUDPServer that already has a scene"); | 653 | m_log.Error("[LLUDPSERVER]: AddScene() called on an LLUDPServer that already has a scene"); |
616 | return; | 654 | return; |
@@ -622,8 +660,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
622 | return; | 660 | return; |
623 | } | 661 | } |
624 | 662 | ||
625 | m_scene = (Scene)scene; | 663 | Scene = (Scene)scene; |
626 | m_location = new Location(m_scene.RegionInfo.RegionHandle); | 664 | m_location = new Location(Scene.RegionInfo.RegionHandle); |
665 | |||
666 | IpahEngine | ||
667 | = new JobEngine( | ||
668 | string.Format("Incoming Packet Async Handling Engine ({0})", Scene.Name), | ||
669 | "INCOMING PACKET ASYNC HANDLING ENGINE"); | ||
670 | |||
671 | OqrEngine | ||
672 | = new JobEngine( | ||
673 | string.Format("Outgoing Queue Refill Engine ({0})", Scene.Name), | ||
674 | "OUTGOING QUEUE REFILL ENGINE"); | ||
627 | 675 | ||
628 | StatsManager.RegisterStat( | 676 | StatsManager.RegisterStat( |
629 | new Stat( | 677 | new Stat( |
@@ -646,7 +694,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
646 | "Packets reused", | 694 | "Packets reused", |
647 | "Number of packets reused out of all requests to the packet pool", | 695 | "Number of packets reused out of all requests to the packet pool", |
648 | "clientstack", | 696 | "clientstack", |
649 | m_scene.Name, | 697 | Scene.Name, |
650 | StatType.Pull, | 698 | StatType.Pull, |
651 | stat => | 699 | stat => |
652 | { PercentageStat pstat = (PercentageStat)stat; | 700 | { PercentageStat pstat = (PercentageStat)stat; |
@@ -660,7 +708,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
660 | "Packet data blocks reused", | 708 | "Packet data blocks reused", |
661 | "Number of data blocks reused out of all requests to the packet pool", | 709 | "Number of data blocks reused out of all requests to the packet pool", |
662 | "clientstack", | 710 | "clientstack", |
663 | m_scene.Name, | 711 | Scene.Name, |
664 | StatType.Pull, | 712 | StatType.Pull, |
665 | stat => | 713 | stat => |
666 | { PercentageStat pstat = (PercentageStat)stat; | 714 | { PercentageStat pstat = (PercentageStat)stat; |
@@ -675,7 +723,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
675 | "The number of objects currently stored within the packet pool", | 723 | "The number of objects currently stored within the packet pool", |
676 | "", | 724 | "", |
677 | "clientstack", | 725 | "clientstack", |
678 | m_scene.Name, | 726 | Scene.Name, |
679 | StatType.Pull, | 727 | StatType.Pull, |
680 | stat => stat.Value = PacketPool.Instance.PacketsPooled, | 728 | stat => stat.Value = PacketPool.Instance.PacketsPooled, |
681 | StatVerbosity.Debug)); | 729 | StatVerbosity.Debug)); |
@@ -687,16 +735,59 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
687 | "The number of objects currently stored within the packet data block pool", | 735 | "The number of objects currently stored within the packet data block pool", |
688 | "", | 736 | "", |
689 | "clientstack", | 737 | "clientstack", |
690 | m_scene.Name, | 738 | Scene.Name, |
691 | StatType.Pull, | 739 | StatType.Pull, |
692 | stat => stat.Value = PacketPool.Instance.BlocksPooled, | 740 | stat => stat.Value = PacketPool.Instance.BlocksPooled, |
693 | StatVerbosity.Debug)); | 741 | StatVerbosity.Debug)); |
742 | |||
743 | StatsManager.RegisterStat( | ||
744 | new Stat( | ||
745 | "OutgoingPacketsQueuedCount", | ||
746 | "Packets queued for outgoing send", | ||
747 | "Number of queued outgoing packets across all connections", | ||
748 | "", | ||
749 | "clientstack", | ||
750 | Scene.Name, | ||
751 | StatType.Pull, | ||
752 | MeasuresOfInterest.AverageChangeOverTime, | ||
753 | stat => stat.Value = GetTotalQueuedOutgoingPackets(), | ||
754 | StatVerbosity.Info)); | ||
755 | |||
756 | StatsManager.RegisterStat( | ||
757 | new Stat( | ||
758 | "IncomingPacketAsyncRequestsWaiting", | ||
759 | "Number of incoming packets waiting for async processing in engine.", | ||
760 | "", | ||
761 | "", | ||
762 | "clientstack", | ||
763 | Scene.Name, | ||
764 | StatType.Pull, | ||
765 | MeasuresOfInterest.None, | ||
766 | stat => stat.Value = IpahEngine.JobsWaiting, | ||
767 | StatVerbosity.Debug)); | ||
768 | |||
769 | StatsManager.RegisterStat( | ||
770 | new Stat( | ||
771 | "OQRERequestsWaiting", | ||
772 | "Number of outgong queue refill requests waiting for processing.", | ||
773 | "", | ||
774 | "", | ||
775 | "clientstack", | ||
776 | Scene.Name, | ||
777 | StatType.Pull, | ||
778 | MeasuresOfInterest.None, | ||
779 | stat => stat.Value = OqrEngine.JobsWaiting, | ||
780 | StatVerbosity.Debug)); | ||
694 | 781 | ||
695 | // We delay enabling pool stats to AddScene() instead of Initialize() so that we can distinguish pool stats by | 782 | // We delay enabling pool stats to AddScene() instead of Initialize() so that we can distinguish pool stats by |
696 | // scene name | 783 | // scene name |
697 | if (UsePools) | 784 | if (UsePools) |
698 | EnablePoolStats(); | 785 | EnablePoolStats(); |
699 | 786 | ||
787 | <<<<<<< HEAD | ||
788 | LLUDPServerCommands commands = new LLUDPServerCommands(MainConsole.Instance, this); | ||
789 | commands.Register(); | ||
790 | ======= | ||
700 | MainConsole.Instance.Commands.AddCommand( | 791 | MainConsole.Instance.Commands.AddCommand( |
701 | "Debug", false, "debug lludp packet", | 792 | "Debug", false, "debug lludp packet", |
702 | "debug lludp packet [--default] <level> [<avatar-first-name> <avatar-last-name>]", | 793 | "debug lludp packet [--default] <level> [<avatar-first-name> <avatar-last-name>]", |
@@ -837,96 +928,29 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
837 | 928 | ||
838 | if (subCommand == "out" || subCommand == "all") | 929 | if (subCommand == "out" || subCommand == "all") |
839 | StartOutbound(); | 930 | StartOutbound(); |
931 | >>>>>>> avn/ubitvar | ||
840 | } | 932 | } |
841 | 933 | ||
842 | private void HandleStopCommand(string module, string[] args) | 934 | public bool HandlesRegion(Location x) |
843 | { | 935 | { |
844 | if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_scene) | 936 | return x == m_location; |
845 | return; | ||
846 | |||
847 | if (args.Length != 4) | ||
848 | { | ||
849 | MainConsole.Instance.Output("Usage: debug lludp stop <in|out|all>"); | ||
850 | return; | ||
851 | } | ||
852 | |||
853 | string subCommand = args[3]; | ||
854 | |||
855 | if (subCommand == "in" || subCommand == "all") | ||
856 | StopInbound(); | ||
857 | |||
858 | if (subCommand == "out" || subCommand == "all") | ||
859 | StopOutbound(); | ||
860 | } | 937 | } |
861 | 938 | ||
862 | private void HandlePoolCommand(string module, string[] args) | 939 | public int GetTotalQueuedOutgoingPackets() |
863 | { | 940 | { |
864 | if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_scene) | 941 | int total = 0; |
865 | return; | ||
866 | 942 | ||
867 | if (args.Length != 4) | 943 | foreach (ScenePresence sp in Scene.GetScenePresences()) |
868 | { | ||
869 | MainConsole.Instance.Output("Usage: debug lludp pool <on|off>"); | ||
870 | return; | ||
871 | } | ||
872 | |||
873 | string enabled = args[3]; | ||
874 | |||
875 | if (enabled == "on") | ||
876 | { | ||
877 | if (EnablePools()) | ||
878 | { | ||
879 | EnablePoolStats(); | ||
880 | MainConsole.Instance.OutputFormat("Packet pools enabled on {0}", m_scene.Name); | ||
881 | } | ||
882 | } | ||
883 | else if (enabled == "off") | ||
884 | { | 944 | { |
885 | if (DisablePools()) | 945 | // XXX: Need a better way to determine which IClientAPIs have UDPClients (NPCs do not, for instance). |
946 | if (sp.ControllingClient is LLClientView) | ||
886 | { | 947 | { |
887 | DisablePoolStats(); | 948 | LLUDPClient udpClient = ((LLClientView)sp.ControllingClient).UDPClient; |
888 | MainConsole.Instance.OutputFormat("Packet pools disabled on {0}", m_scene.Name); | 949 | total += udpClient.GetTotalPacketsQueuedCount(); |
889 | } | 950 | } |
890 | } | 951 | } |
891 | else | ||
892 | { | ||
893 | MainConsole.Instance.Output("Usage: debug lludp pool <on|off>"); | ||
894 | } | ||
895 | } | ||
896 | |||
897 | bool m_discardAgentUpdates; | ||
898 | |||
899 | private void HandleAgentUpdateCommand(string module, string[] args) | ||
900 | { | ||
901 | if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_scene) | ||
902 | return; | ||
903 | |||
904 | m_discardAgentUpdates = !m_discardAgentUpdates; | ||
905 | |||
906 | MainConsole.Instance.OutputFormat( | ||
907 | "Discard AgentUpdates now {0} for {1}", m_discardAgentUpdates, m_scene.Name); | ||
908 | } | ||
909 | |||
910 | private void HandleStatusCommand(string module, string[] args) | ||
911 | { | ||
912 | if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_scene) | ||
913 | return; | ||
914 | |||
915 | MainConsole.Instance.OutputFormat( | ||
916 | "IN LLUDP packet processing for {0} is {1}", m_scene.Name, IsRunningInbound ? "enabled" : "disabled"); | ||
917 | 952 | ||
918 | MainConsole.Instance.OutputFormat( | 953 | return total; |
919 | "OUT LLUDP packet processing for {0} is {1}", m_scene.Name, IsRunningOutbound ? "enabled" : "disabled"); | ||
920 | |||
921 | MainConsole.Instance.OutputFormat("LLUDP pools in {0} are {1}", m_scene.Name, UsePools ? "on" : "off"); | ||
922 | |||
923 | MainConsole.Instance.OutputFormat( | ||
924 | "Packet debug level for new clients is {0}", DefaultClientPacketDebugLevel); | ||
925 | } | ||
926 | |||
927 | public bool HandlesRegion(Location x) | ||
928 | { | ||
929 | return x == m_location; | ||
930 | } | 954 | } |
931 | 955 | ||
932 | // public void BroadcastPacket(Packet packet, ThrottleOutPacketType category, bool sendToPausedAgents, bool allowSplitting) | 956 | // public void BroadcastPacket(Packet packet, ThrottleOutPacketType category, bool sendToPausedAgents, bool allowSplitting) |
@@ -999,7 +1023,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
999 | for (int i = 0; i < packetCount; i++) | 1023 | for (int i = 0; i < packetCount; i++) |
1000 | { | 1024 | { |
1001 | byte[] data = datas[i]; | 1025 | byte[] data = datas[i]; |
1002 | |||
1003 | if (!SendPacketData(udpClient, data, packet.Type, category, method)) | 1026 | if (!SendPacketData(udpClient, data, packet.Type, category, method)) |
1004 | packetQueued = true; | 1027 | packetQueued = true; |
1005 | } | 1028 | } |
@@ -1007,7 +1030,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1007 | else | 1030 | else |
1008 | { | 1031 | { |
1009 | byte[] data = packet.ToBytes(); | 1032 | byte[] data = packet.ToBytes(); |
1010 | packetQueued = SendPacketData(udpClient, data, packet.Type, category, method); | 1033 | if (!SendPacketData(udpClient, data, packet.Type, category, method)) |
1034 | packetQueued = true; | ||
1011 | } | 1035 | } |
1012 | 1036 | ||
1013 | PacketPool.Instance.ReturnPacket(packet); | 1037 | PacketPool.Instance.ReturnPacket(packet); |
@@ -1094,20 +1118,44 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1094 | } | 1118 | } |
1095 | 1119 | ||
1096 | OutgoingPacket outgoingPacket = new OutgoingPacket(udpClient, buffer, category, null); | 1120 | OutgoingPacket outgoingPacket = new OutgoingPacket(udpClient, buffer, category, null); |
1121 | |||
1097 | // If we were not provided a method for handling unacked, use the UDPServer default method | 1122 | // If we were not provided a method for handling unacked, use the UDPServer default method |
1098 | outgoingPacket.UnackedMethod = ((method == null) ? delegate(OutgoingPacket oPacket) { ResendUnacked(oPacket); } : method); | 1123 | if ((outgoingPacket.Buffer.Data[0] & Helpers.MSG_RELIABLE) != 0) |
1124 | outgoingPacket.UnackedMethod = ((method == null) ? delegate(OutgoingPacket oPacket) { ResendUnacked(oPacket); } : method); | ||
1099 | 1125 | ||
1100 | // If a Linden Lab 1.23.5 client receives an update packet after a kill packet for an object, it will | 1126 | // If a Linden Lab 1.23.5 client receives an update packet after a kill packet for an object, it will |
1101 | // continue to display the deleted object until relog. Therefore, we need to always queue a kill object | 1127 | // continue to display the deleted object until relog. Therefore, we need to always queue a kill object |
1102 | // packet so that it isn't sent before a queued update packet. | 1128 | // packet so that it isn't sent before a queued update packet. |
1129 | <<<<<<< HEAD | ||
1130 | bool forceQueue = (type == PacketType.KillObject); | ||
1131 | |||
1132 | // if (type == PacketType.ImprovedTerseObjectUpdate) | ||
1133 | // { | ||
1134 | // m_log.DebugFormat("Direct send ITOU to {0} in {1}", udpClient.AgentID, Scene.Name); | ||
1135 | // SendPacketFinal(outgoingPacket); | ||
1136 | // return false; | ||
1137 | // } | ||
1138 | // else | ||
1139 | // { | ||
1140 | if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket, forceQueue)) | ||
1141 | ======= | ||
1103 | bool requestQueue = type == PacketType.KillObject; | 1142 | bool requestQueue = type == PacketType.KillObject; |
1104 | if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket, requestQueue, highPriority)) | 1143 | if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket, requestQueue, highPriority)) |
1144 | >>>>>>> avn/ubitvar | ||
1105 | { | 1145 | { |
1106 | SendPacketFinal(outgoingPacket); | 1146 | SendPacketFinal(outgoingPacket); |
1107 | return true; | 1147 | return true; |
1108 | } | 1148 | } |
1149 | <<<<<<< HEAD | ||
1150 | else | ||
1151 | { | ||
1152 | return false; | ||
1153 | } | ||
1154 | // } | ||
1155 | ======= | ||
1109 | 1156 | ||
1110 | return false; | 1157 | return false; |
1158 | >>>>>>> avn/ubitvar | ||
1111 | 1159 | ||
1112 | #endregion Queue or Send | 1160 | #endregion Queue or Send |
1113 | } | 1161 | } |
@@ -1184,7 +1232,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1184 | // Fire this out on a different thread so that we don't hold up outgoing packet processing for | 1232 | // Fire this out on a different thread so that we don't hold up outgoing packet processing for |
1185 | // everybody else if this is being called due to an ack timeout. | 1233 | // everybody else if this is being called due to an ack timeout. |
1186 | // This is the same as processing as the async process of a logout request. | 1234 | // This is the same as processing as the async process of a logout request. |
1187 | Util.FireAndForget(o => DeactivateClientDueToTimeout(client, timeoutTicks)); | 1235 | Util.FireAndForget( |
1236 | o => DeactivateClientDueToTimeout(client, timeoutTicks), null, "LLUDPServer.DeactivateClientDueToTimeout"); | ||
1188 | 1237 | ||
1189 | return; | 1238 | return; |
1190 | } | 1239 | } |
@@ -1280,7 +1329,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1280 | Utils.UIntToBytesBig(sequenceNumber, buffer.Data, 1); | 1329 | Utils.UIntToBytesBig(sequenceNumber, buffer.Data, 1); |
1281 | outgoingPacket.SequenceNumber = sequenceNumber; | 1330 | outgoingPacket.SequenceNumber = sequenceNumber; |
1282 | 1331 | ||
1283 | if (isReliable) | 1332 | if (udpClient.ProcessUnackedSends && isReliable) |
1284 | { | 1333 | { |
1285 | // Add this packet to the list of ACK responses we are waiting on from the server | 1334 | // Add this packet to the list of ACK responses we are waiting on from the server |
1286 | udpClient.NeedAcks.Add(outgoingPacket); | 1335 | udpClient.NeedAcks.Add(outgoingPacket); |
@@ -1304,6 +1353,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1304 | // is 100% correct | 1353 | // is 100% correct |
1305 | PacketsSentCount++; | 1354 | PacketsSentCount++; |
1306 | 1355 | ||
1356 | if (udpClient.DebugDataOutLevel > 0) | ||
1357 | m_log.DebugFormat( | ||
1358 | "[LLUDPSERVER]: Sending packet #{0} (rel: {1}, res: {2}) to {3} from {4}", | ||
1359 | outgoingPacket.SequenceNumber, isReliable, isResend, udpClient.AgentID, Scene.Name); | ||
1360 | |||
1307 | // Put the UDP payload on the wire | 1361 | // Put the UDP payload on the wire |
1308 | AsyncBeginSend(buffer); | 1362 | AsyncBeginSend(buffer); |
1309 | 1363 | ||
@@ -1419,8 +1473,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1419 | if (m_pendingCache.Contains(endPoint)) | 1473 | if (m_pendingCache.Contains(endPoint)) |
1420 | return; | 1474 | return; |
1421 | 1475 | ||
1476 | <<<<<<< HEAD | ||
1477 | Util.FireAndForget(HandleUseCircuitCode, array, "LLUDPServer.HandleUseCircuitCode"); | ||
1478 | ======= | ||
1422 | m_pendingCache.AddOrUpdate(endPoint, new Queue<UDPPacketBuffer>(), 60); | 1479 | m_pendingCache.AddOrUpdate(endPoint, new Queue<UDPPacketBuffer>(), 60); |
1423 | } | 1480 | } |
1481 | >>>>>>> avn/ubitvar | ||
1424 | 1482 | ||
1425 | // We need to copy the endpoint so that it doesn't get changed when another thread reuses the | 1483 | // We need to copy the endpoint so that it doesn't get changed when another thread reuses the |
1426 | // buffer. | 1484 | // buffer. |
@@ -1449,9 +1507,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1449 | // Send ack straight away to let the viewer know that we got it. | 1507 | // Send ack straight away to let the viewer know that we got it. |
1450 | SendAckImmediate(endPoint, packet.Header.Sequence); | 1508 | SendAckImmediate(endPoint, packet.Header.Sequence); |
1451 | 1509 | ||
1510 | <<<<<<< HEAD | ||
1511 | Util.FireAndForget( | ||
1512 | HandleCompleteMovementIntoRegion, array, "LLUDPServer.HandleCompleteMovementIntoRegion"); | ||
1513 | ======= | ||
1452 | // We need to copy the endpoint so that it doesn't get changed when another thread reuses the | 1514 | // We need to copy the endpoint so that it doesn't get changed when another thread reuses the |
1453 | // buffer. | 1515 | // buffer. |
1454 | object[] array = new object[] { new IPEndPoint(endPoint.Address, endPoint.Port), packet }; | 1516 | object[] array = new object[] { new IPEndPoint(endPoint.Address, endPoint.Port), packet }; |
1517 | >>>>>>> avn/ubitvar | ||
1455 | 1518 | ||
1456 | Util.FireAndForget(HandleCompleteMovementIntoRegion, array); | 1519 | Util.FireAndForget(HandleCompleteMovementIntoRegion, array); |
1457 | 1520 | ||
@@ -1461,7 +1524,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1461 | } | 1524 | } |
1462 | 1525 | ||
1463 | // Determine which agent this packet came from | 1526 | // Determine which agent this packet came from |
1527 | <<<<<<< HEAD | ||
1528 | IClientAPI client; | ||
1529 | if (!Scene.TryGetClient(endPoint, out client) || !(client is LLClientView)) | ||
1530 | ======= | ||
1464 | if (client == null || !(client is LLClientView)) | 1531 | if (client == null || !(client is LLClientView)) |
1532 | >>>>>>> avn/ubitvar | ||
1465 | { | 1533 | { |
1466 | //m_log.Debug("[LLUDPSERVER]: Received a " + packet.Type + " packet from an unrecognized source: " + address + " in " + m_scene.RegionInfo.RegionName); | 1534 | //m_log.Debug("[LLUDPSERVER]: Received a " + packet.Type + " packet from an unrecognized source: " + address + " in " + m_scene.RegionInfo.RegionName); |
1467 | 1535 | ||
@@ -1493,30 +1561,37 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1493 | 1561 | ||
1494 | #region ACK Receiving | 1562 | #region ACK Receiving |
1495 | 1563 | ||
1496 | // Handle appended ACKs | 1564 | if (udpClient.ProcessUnackedSends) |
1497 | if (packet.Header.AppendedAcks && packet.Header.AckList != null) | ||
1498 | { | 1565 | { |
1499 | // m_log.DebugFormat( | 1566 | // Handle appended ACKs |
1500 | // "[LLUDPSERVER]: Handling {0} appended acks from {1} in {2}", | 1567 | if (packet.Header.AppendedAcks && packet.Header.AckList != null) |
1501 | // packet.Header.AckList.Length, client.Name, m_scene.Name); | 1568 | { |
1569 | // m_log.DebugFormat( | ||
1570 | // "[LLUDPSERVER]: Handling {0} appended acks from {1} in {2}", | ||
1571 | // packet.Header.AckList.Length, client.Name, m_scene.Name); | ||
1502 | 1572 | ||
1503 | for (int i = 0; i < packet.Header.AckList.Length; i++) | 1573 | for (int i = 0; i < packet.Header.AckList.Length; i++) |
1504 | udpClient.NeedAcks.Acknowledge(packet.Header.AckList[i], now, packet.Header.Resent); | 1574 | udpClient.NeedAcks.Acknowledge(packet.Header.AckList[i], now, packet.Header.Resent); |
1505 | } | 1575 | } |
1506 | 1576 | ||
1507 | // Handle PacketAck packets | 1577 | // Handle PacketAck packets |
1508 | if (packet.Type == PacketType.PacketAck) | 1578 | if (packet.Type == PacketType.PacketAck) |
1509 | { | 1579 | { |
1510 | PacketAckPacket ackPacket = (PacketAckPacket)packet; | 1580 | PacketAckPacket ackPacket = (PacketAckPacket)packet; |
1511 | 1581 | ||
1512 | // m_log.DebugFormat( | 1582 | // m_log.DebugFormat( |
1513 | // "[LLUDPSERVER]: Handling {0} packet acks for {1} in {2}", | 1583 | // "[LLUDPSERVER]: Handling {0} packet acks for {1} in {2}", |
1514 | // ackPacket.Packets.Length, client.Name, m_scene.Name); | 1584 | // ackPacket.Packets.Length, client.Name, m_scene.Name); |
1515 | 1585 | ||
1516 | for (int i = 0; i < ackPacket.Packets.Length; i++) | 1586 | for (int i = 0; i < ackPacket.Packets.Length; i++) |
1517 | udpClient.NeedAcks.Acknowledge(ackPacket.Packets[i].ID, now, packet.Header.Resent); | 1587 | udpClient.NeedAcks.Acknowledge(ackPacket.Packets[i].ID, now, packet.Header.Resent); |
1518 | 1588 | ||
1519 | // We don't need to do anything else with PacketAck packets | 1589 | // We don't need to do anything else with PacketAck packets |
1590 | return; | ||
1591 | } | ||
1592 | } | ||
1593 | else if (packet.Type == PacketType.PacketAck) | ||
1594 | { | ||
1520 | return; | 1595 | return; |
1521 | } | 1596 | } |
1522 | 1597 | ||
@@ -1577,7 +1652,28 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1577 | LogPacketHeader(true, udpClient.CircuitCode, 0, packet.Type, (ushort)packet.Length); | 1652 | LogPacketHeader(true, udpClient.CircuitCode, 0, packet.Type, (ushort)packet.Length); |
1578 | #endregion BinaryStats | 1653 | #endregion BinaryStats |
1579 | 1654 | ||
1655 | <<<<<<< HEAD | ||
1656 | if (packet.Type == PacketType.AgentUpdate) | ||
1657 | { | ||
1658 | if (DiscardInboundAgentUpdates) | ||
1659 | return; | ||
1660 | |||
1661 | ((LLClientView)client).TotalAgentUpdates++; | ||
1662 | |||
1663 | AgentUpdatePacket agentUpdate = (AgentUpdatePacket)packet; | ||
1664 | |||
1665 | LLClientView llClient = client as LLClientView; | ||
1666 | if (agentUpdate.AgentData.SessionID != client.SessionId | ||
1667 | || agentUpdate.AgentData.AgentID != client.AgentId | ||
1668 | || !(llClient == null || llClient.CheckAgentUpdateSignificance(agentUpdate.AgentData)) ) | ||
1669 | { | ||
1670 | PacketPool.Instance.ReturnPacket(packet); | ||
1671 | return; | ||
1672 | } | ||
1673 | } | ||
1674 | ======= | ||
1580 | // AgentUpdate mess removed from here | 1675 | // AgentUpdate mess removed from here |
1676 | >>>>>>> avn/ubitvar | ||
1581 | 1677 | ||
1582 | #region Ping Check Handling | 1678 | #region Ping Check Handling |
1583 | 1679 | ||
@@ -1752,7 +1848,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1752 | 1848 | ||
1753 | m_log.DebugFormat( | 1849 | m_log.DebugFormat( |
1754 | "[LLUDPSERVER]: Handling UseCircuitCode request for circuit {0} to {1} from IP {2}", | 1850 | "[LLUDPSERVER]: Handling UseCircuitCode request for circuit {0} to {1} from IP {2}", |
1755 | uccp.CircuitCode.Code, m_scene.RegionInfo.RegionName, endPoint); | 1851 | uccp.CircuitCode.Code, Scene.RegionInfo.RegionName, endPoint); |
1756 | 1852 | ||
1757 | AuthenticateResponse sessionInfo; | 1853 | AuthenticateResponse sessionInfo; |
1758 | if (IsClientAuthorized(uccp, out sessionInfo)) | 1854 | if (IsClientAuthorized(uccp, out sessionInfo)) |
@@ -1812,10 +1908,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1812 | // We only want to send initial data to new clients, not ones which are being converted from child to root. | 1908 | // We only want to send initial data to new clients, not ones which are being converted from child to root. |
1813 | if (client != null) | 1909 | if (client != null) |
1814 | { | 1910 | { |
1911 | <<<<<<< HEAD | ||
1912 | AgentCircuitData aCircuit = Scene.AuthenticateHandler.GetAgentCircuitData(uccp.CircuitCode.Code); | ||
1913 | ======= | ||
1914 | >>>>>>> avn/ubitvar | ||
1815 | bool tp = (aCircuit.teleportFlags > 0); | 1915 | bool tp = (aCircuit.teleportFlags > 0); |
1816 | // Let's delay this for TP agents, otherwise the viewer doesn't know where to get resources from | 1916 | // Let's delay this for TP agents, otherwise the viewer doesn't know where to get resources from |
1817 | if (!tp) | 1917 | if (!tp && !client.SceneAgent.SentInitialDataToClient) |
1818 | client.SceneAgent.SendInitialDataToMe(); | 1918 | client.SceneAgent.SendInitialDataToClient(); |
1819 | } | 1919 | } |
1820 | } | 1920 | } |
1821 | else | 1921 | else |
@@ -1823,11 +1923,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1823 | // Don't create clients for unauthorized requesters. | 1923 | // Don't create clients for unauthorized requesters. |
1824 | m_log.WarnFormat( | 1924 | m_log.WarnFormat( |
1825 | "[LLUDPSERVER]: Ignoring connection request for {0} to {1} with unknown circuit code {2} from IP {3}", | 1925 | "[LLUDPSERVER]: Ignoring connection request for {0} to {1} with unknown circuit code {2} from IP {3}", |
1926 | <<<<<<< HEAD | ||
1927 | uccp.CircuitCode.ID, Scene.RegionInfo.RegionName, uccp.CircuitCode.Code, endPoint); | ||
1928 | } | ||
1929 | |||
1930 | ======= | ||
1826 | uccp.CircuitCode.ID, m_scene.RegionInfo.RegionName, uccp.CircuitCode.Code, endPoint); | 1931 | uccp.CircuitCode.ID, m_scene.RegionInfo.RegionName, uccp.CircuitCode.Code, endPoint); |
1827 | 1932 | ||
1828 | lock (m_pendingCache) | 1933 | lock (m_pendingCache) |
1829 | m_pendingCache.Remove(endPoint); | 1934 | m_pendingCache.Remove(endPoint); |
1830 | } | 1935 | } |
1936 | >>>>>>> avn/ubitvar | ||
1831 | // m_log.DebugFormat( | 1937 | // m_log.DebugFormat( |
1832 | // "[LLUDPSERVER]: Handling UseCircuitCode request from {0} took {1}ms", | 1938 | // "[LLUDPSERVER]: Handling UseCircuitCode request from {0} took {1}ms", |
1833 | // buffer.RemoteEndPoint, (DateTime.Now - startTime).Milliseconds); | 1939 | // buffer.RemoteEndPoint, (DateTime.Now - startTime).Milliseconds); |
@@ -1857,7 +1963,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1857 | CompleteAgentMovementPacket packet = (CompleteAgentMovementPacket)array[1]; | 1963 | CompleteAgentMovementPacket packet = (CompleteAgentMovementPacket)array[1]; |
1858 | 1964 | ||
1859 | m_log.DebugFormat( | 1965 | m_log.DebugFormat( |
1860 | "[LLUDPSERVER]: Handling CompleteAgentMovement request from {0} in {1}", endPoint, m_scene.Name); | 1966 | "[LLUDPSERVER]: Handling CompleteAgentMovement request from {0} in {1}", endPoint, Scene.Name); |
1861 | 1967 | ||
1862 | // Determine which agent this packet came from | 1968 | // Determine which agent this packet came from |
1863 | // We need to wait here because in when using the OpenSimulator V2 teleport protocol to travel to a destination | 1969 | // We need to wait here because in when using the OpenSimulator V2 teleport protocol to travel to a destination |
@@ -1868,7 +1974,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1868 | int count = 40; | 1974 | int count = 40; |
1869 | while (count-- > 0) | 1975 | while (count-- > 0) |
1870 | { | 1976 | { |
1871 | if (m_scene.TryGetClient(endPoint, out client)) | 1977 | if (Scene.TryGetClient(endPoint, out client)) |
1872 | { | 1978 | { |
1873 | if (!client.IsActive) | 1979 | if (!client.IsActive) |
1874 | { | 1980 | { |
@@ -1877,7 +1983,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1877 | // not yet been established). | 1983 | // not yet been established). |
1878 | m_log.DebugFormat( | 1984 | m_log.DebugFormat( |
1879 | "[LLUDPSERVER]: Received a CompleteAgentMovement from {0} for {1} in {2} but client is not active yet. Waiting.", | 1985 | "[LLUDPSERVER]: Received a CompleteAgentMovement from {0} for {1} in {2} but client is not active yet. Waiting.", |
1880 | endPoint, client.Name, m_scene.Name); | 1986 | endPoint, client.Name, Scene.Name); |
1881 | } | 1987 | } |
1882 | else if (client.SceneAgent == null) | 1988 | else if (client.SceneAgent == null) |
1883 | { | 1989 | { |
@@ -1889,7 +1995,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1889 | // the client manager | 1995 | // the client manager |
1890 | m_log.DebugFormat( | 1996 | m_log.DebugFormat( |
1891 | "[LLUDPSERVER]: Received a CompleteAgentMovement from {0} for {1} in {2} but client SceneAgent not set yet. Waiting.", | 1997 | "[LLUDPSERVER]: Received a CompleteAgentMovement from {0} for {1} in {2} but client SceneAgent not set yet. Waiting.", |
1892 | endPoint, client.Name, m_scene.Name); | 1998 | endPoint, client.Name, Scene.Name); |
1893 | } | 1999 | } |
1894 | else | 2000 | else |
1895 | { | 2001 | { |
@@ -1900,7 +2006,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1900 | { | 2006 | { |
1901 | m_log.DebugFormat( | 2007 | m_log.DebugFormat( |
1902 | "[LLUDPSERVER]: Received a CompleteAgentMovement from {0} in {1} but no client exists yet. Waiting.", | 2008 | "[LLUDPSERVER]: Received a CompleteAgentMovement from {0} in {1} but no client exists yet. Waiting.", |
1903 | endPoint, m_scene.Name); | 2009 | endPoint, Scene.Name); |
1904 | } | 2010 | } |
1905 | 2011 | ||
1906 | Thread.Sleep(200); | 2012 | Thread.Sleep(200); |
@@ -1910,7 +2016,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1910 | { | 2016 | { |
1911 | m_log.DebugFormat( | 2017 | m_log.DebugFormat( |
1912 | "[LLUDPSERVER]: No client found for CompleteAgentMovement from {0} in {1} after wait. Dropping.", | 2018 | "[LLUDPSERVER]: No client found for CompleteAgentMovement from {0} in {1} after wait. Dropping.", |
1913 | endPoint, m_scene.Name); | 2019 | endPoint, Scene.Name); |
1914 | 2020 | ||
1915 | return; | 2021 | return; |
1916 | } | 2022 | } |
@@ -1922,7 +2028,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1922 | // purposes. | 2028 | // purposes. |
1923 | m_log.DebugFormat( | 2029 | m_log.DebugFormat( |
1924 | "[LLUDPSERVER]: Received a CompleteAgentMovement from {0} for {1} in {2} but client is not active after wait. Dropping.", | 2030 | "[LLUDPSERVER]: Received a CompleteAgentMovement from {0} for {1} in {2} but client is not active after wait. Dropping.", |
1925 | endPoint, client.Name, m_scene.Name); | 2031 | endPoint, client.Name, Scene.Name); |
1926 | 2032 | ||
1927 | return; | 2033 | return; |
1928 | } | 2034 | } |
@@ -2019,8 +2125,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
2019 | // consistently, this lock could probably be removed. | 2125 | // consistently, this lock could probably be removed. |
2020 | lock (this) | 2126 | lock (this) |
2021 | { | 2127 | { |
2022 | if (!m_scene.TryGetClient(agentID, out client)) | 2128 | if (!Scene.TryGetClient(agentID, out client)) |
2023 | { | 2129 | { |
2130 | <<<<<<< HEAD | ||
2131 | LLUDPClient udpClient = new LLUDPClient(this, ThrottleRates, Throttle, circuitCode, agentID, remoteEndPoint, m_defaultRTO, m_maxRTO); | ||
2132 | ======= | ||
2024 | createNew = true; | 2133 | createNew = true; |
2025 | } | 2134 | } |
2026 | else | 2135 | else |
@@ -2035,8 +2144,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
2035 | if (createNew) | 2144 | if (createNew) |
2036 | { | 2145 | { |
2037 | LLUDPClient udpClient = new LLUDPClient(this, ThrottleRates, m_throttle, circuitCode, agentID, remoteEndPoint, m_defaultRTO, m_maxRTO); | 2146 | LLUDPClient udpClient = new LLUDPClient(this, ThrottleRates, m_throttle, circuitCode, agentID, remoteEndPoint, m_defaultRTO, m_maxRTO); |
2147 | >>>>>>> avn/ubitvar | ||
2038 | 2148 | ||
2039 | client = new LLClientView(m_scene, this, udpClient, sessionInfo, agentID, sessionID, circuitCode); | 2149 | client = new LLClientView(Scene, this, udpClient, sessionInfo, agentID, sessionID, circuitCode); |
2040 | client.OnLogout += LogoutHandler; | 2150 | client.OnLogout += LogoutHandler; |
2041 | client.DebugPacketLevel = DefaultClientPacketDebugLevel; | 2151 | client.DebugPacketLevel = DefaultClientPacketDebugLevel; |
2042 | 2152 | ||
@@ -2064,23 +2174,35 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
2064 | { | 2174 | { |
2065 | ClientLogoutsDueToNoReceives++; | 2175 | ClientLogoutsDueToNoReceives++; |
2066 | 2176 | ||
2177 | <<<<<<< HEAD | ||
2178 | m_log.WarnFormat( | ||
2179 | "[LLUDPSERVER]: No packets received from {0} agent of {1} for {2}ms in {3}. Disconnecting.", | ||
2180 | client.SceneAgent.IsChildAgent ? "child" : "root", client.Name, timeoutTicks, Scene.Name); | ||
2181 | ======= | ||
2067 | if (client.SceneAgent != null) | 2182 | if (client.SceneAgent != null) |
2068 | { | 2183 | { |
2069 | m_log.WarnFormat( | 2184 | m_log.WarnFormat( |
2070 | "[LLUDPSERVER]: No packets received from {0} agent of {1} for {2}ms in {3}. Disconnecting.", | 2185 | "[LLUDPSERVER]: No packets received from {0} agent of {1} for {2}ms in {3}. Disconnecting.", |
2071 | client.SceneAgent.IsChildAgent ? "child" : "root", client.Name, timeoutTicks, m_scene.Name); | 2186 | client.SceneAgent.IsChildAgent ? "child" : "root", client.Name, timeoutTicks, m_scene.Name); |
2187 | >>>>>>> avn/ubitvar | ||
2072 | 2188 | ||
2073 | if (!client.SceneAgent.IsChildAgent) | 2189 | if (!client.SceneAgent.IsChildAgent) |
2074 | client.Kick("Simulator logged you out due to connection timeout."); | 2190 | client.Kick("Simulator logged you out due to connection timeout."); |
2075 | } | 2191 | } |
2076 | } | 2192 | } |
2077 | 2193 | ||
2194 | <<<<<<< HEAD | ||
2195 | Scene.CloseAgent(client.AgentId, true); | ||
2196 | ======= | ||
2078 | if (!m_scene.CloseAgent(client.AgentId, true)) | 2197 | if (!m_scene.CloseAgent(client.AgentId, true)) |
2079 | client.Close(true,true); | 2198 | client.Close(true,true); |
2199 | >>>>>>> avn/ubitvar | ||
2080 | } | 2200 | } |
2081 | 2201 | ||
2082 | private void IncomingPacketHandler() | 2202 | private void IncomingPacketHandler() |
2083 | { | 2203 | { |
2204 | Thread.CurrentThread.Priority = ThreadPriority.Highest; | ||
2205 | |||
2084 | // Set this culture for the thread that incoming packets are received | 2206 | // Set this culture for the thread that incoming packets are received |
2085 | // on to en-US to avoid number parsing issues | 2207 | // on to en-US to avoid number parsing issues |
2086 | Culture.SetCurrentCulture(); | 2208 | Culture.SetCurrentCulture(); |
@@ -2127,6 +2249,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
2127 | 2249 | ||
2128 | private void OutgoingPacketHandler() | 2250 | private void OutgoingPacketHandler() |
2129 | { | 2251 | { |
2252 | Thread.CurrentThread.Priority = ThreadPriority.Highest; | ||
2253 | |||
2130 | // Set this culture for the thread that outgoing packets are sent | 2254 | // Set this culture for the thread that outgoing packets are sent |
2131 | // on to en-US to avoid number parsing issues | 2255 | // on to en-US to avoid number parsing issues |
2132 | Culture.SetCurrentCulture(); | 2256 | Culture.SetCurrentCulture(); |
@@ -2190,7 +2314,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
2190 | 2314 | ||
2191 | // Handle outgoing packets, resends, acknowledgements, and pings for each | 2315 | // Handle outgoing packets, resends, acknowledgements, and pings for each |
2192 | // client. m_packetSent will be set to true if a packet is sent | 2316 | // client. m_packetSent will be set to true if a packet is sent |
2193 | m_scene.ForEachClient(clientPacketHandler); | 2317 | Scene.ForEachClient(clientPacketHandler); |
2194 | 2318 | ||
2195 | m_currentOutgoingClient = null; | 2319 | m_currentOutgoingClient = null; |
2196 | 2320 | ||
@@ -2227,7 +2351,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
2227 | 2351 | ||
2228 | if (udpClient.IsConnected) | 2352 | if (udpClient.IsConnected) |
2229 | { | 2353 | { |
2230 | if (m_resendUnacked) | 2354 | if (udpClient.ProcessUnackedSends && m_resendUnacked) |
2231 | HandleUnacked(llClient); | 2355 | HandleUnacked(llClient); |
2232 | 2356 | ||
2233 | if (m_sendAcks) | 2357 | if (m_sendAcks) |
@@ -2356,7 +2480,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
2356 | watch1.Reset(); | 2480 | watch1.Reset(); |
2357 | 2481 | ||
2358 | // reuse this -- it's every ~100ms | 2482 | // reuse this -- it's every ~100ms |
2359 | if (m_scene.EmergencyMonitoring && nticks % 100 == 0) | 2483 | if (Scene.EmergencyMonitoring && nticks % 100 == 0) |
2360 | { | 2484 | { |
2361 | m_log.InfoFormat("[LLUDPSERVER]: avg processing ticks: {0} avg unacked: {1} avg acks: {2} avg ping: {3} avg dequeue: {4} (TickCountRes: {5} sent: {6} notsent: {7})", | 2485 | m_log.InfoFormat("[LLUDPSERVER]: avg processing ticks: {0} avg unacked: {1} avg acks: {2} avg ping: {3} avg dequeue: {4} (TickCountRes: {5} sent: {6} notsent: {7})", |
2362 | avgProcessingTicks, avgResendUnackedTicks, avgSendAcksTicks, avgSendPingTicks, avgDequeueTicks, TickCountResolution, npacksSent, npackNotSent); | 2486 | avgProcessingTicks, avgResendUnackedTicks, avgSendAcksTicks, avgSendPingTicks, avgDequeueTicks, TickCountResolution, npacksSent, npackNotSent); |
@@ -2400,6 +2524,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
2400 | { | 2524 | { |
2401 | m_currentIncomingClient = null; | 2525 | m_currentIncomingClient = null; |
2402 | } | 2526 | } |
2527 | <<<<<<< HEAD | ||
2528 | } | ||
2529 | else | ||
2530 | { | ||
2531 | m_log.DebugFormat( | ||
2532 | "[LLUDPSERVER]: Dropped incoming {0} for dead client {1} in {2}", | ||
2533 | packet.Type, client.Name, Scene.RegionInfo.RegionName); | ||
2534 | } | ||
2535 | ======= | ||
2403 | // } | 2536 | // } |
2404 | // else | 2537 | // else |
2405 | // { | 2538 | // { |
@@ -2407,6 +2540,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
2407 | // "[LLUDPSERVER]: Dropped incoming {0} for dead client {1} in {2}", | 2540 | // "[LLUDPSERVER]: Dropped incoming {0} for dead client {1} in {2}", |
2408 | // packet.Type, client.Name, m_scene.RegionInfo.RegionName); | 2541 | // packet.Type, client.Name, m_scene.RegionInfo.RegionName); |
2409 | // } | 2542 | // } |
2543 | >>>>>>> avn/ubitvar | ||
2410 | 2544 | ||
2411 | IncomingPacketsProcessed++; | 2545 | IncomingPacketsProcessed++; |
2412 | } | 2546 | } |
@@ -2418,7 +2552,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
2418 | if (!client.IsLoggingOut) | 2552 | if (!client.IsLoggingOut) |
2419 | { | 2553 | { |
2420 | client.IsLoggingOut = true; | 2554 | client.IsLoggingOut = true; |
2421 | m_scene.CloseAgent(client.AgentId, false); | 2555 | Scene.CloseAgent(client.AgentId, false); |
2422 | } | 2556 | } |
2423 | } | 2557 | } |
2424 | } | 2558 | } |
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServerCommands.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServerCommands.cs new file mode 100644 index 0000000..ac6c0b4 --- /dev/null +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServerCommands.cs | |||
@@ -0,0 +1,901 @@ | |||
1 | /* | ||
2 | * Copyright (c) Contributors, http://opensimulator.org/ | ||
3 | * See CONTRIBUTORS.TXT for a full list of copyright holders. | ||
4 | * | ||
5 | * Redistribution and use in source and binary forms, with or without | ||
6 | * modification, are permitted provided that the following conditions are met: | ||
7 | * * Redistributions of source code must retain the above copyright | ||
8 | * notice, this list of conditions and the following disclaimer. | ||
9 | * * Redistributions in binary form must reproduce the above copyright | ||
10 | * notice, this list of conditions and the following disclaimer in the | ||
11 | * documentation and/or other materials provided with the distribution. | ||
12 | * * Neither the name of the OpenSimulator Project nor the | ||
13 | * names of its contributors may be used to endorse or promote products | ||
14 | * derived from this software without specific prior written permission. | ||
15 | * | ||
16 | * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY | ||
17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
19 | * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY | ||
20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||
21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||
23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
26 | */ | ||
27 | |||
28 | using System; | ||
29 | using System.Collections.Generic; | ||
30 | using System.Text; | ||
31 | using NDesk.Options; | ||
32 | using OpenSim.Framework; | ||
33 | using OpenSim.Framework.Console; | ||
34 | using OpenSim.Region.Framework.Scenes; | ||
35 | |||
36 | namespace OpenSim.Region.ClientStack.LindenUDP | ||
37 | { | ||
38 | public class LLUDPServerCommands | ||
39 | { | ||
40 | private ICommandConsole m_console; | ||
41 | private LLUDPServer m_udpServer; | ||
42 | |||
43 | public LLUDPServerCommands(ICommandConsole console, LLUDPServer udpServer) | ||
44 | { | ||
45 | m_console = console; | ||
46 | m_udpServer = udpServer; | ||
47 | } | ||
48 | |||
49 | public void Register() | ||
50 | { | ||
51 | m_console.Commands.AddCommand( | ||
52 | "Comms", false, "show server throttles", | ||
53 | "show server throttles", | ||
54 | "Show information about server throttles", | ||
55 | HandleShowServerThrottlesCommand); | ||
56 | |||
57 | m_console.Commands.AddCommand( | ||
58 | "Debug", false, "debug lludp packet", | ||
59 | "debug lludp packet [--default | --all] <level> [<avatar-first-name> <avatar-last-name>]", | ||
60 | "Turn on packet debugging. This logs information when the client stack hands a processed packet off to downstream code or when upstream code first requests that a certain packet be sent.", | ||
61 | "If level > 255 then all incoming and outgoing packets are logged.\n" | ||
62 | + "If level <= 255 then incoming AgentUpdate and outgoing SimStats and SimulatorViewerTimeMessage packets are not logged.\n" | ||
63 | + "If level <= 200 then incoming RequestImage and outgoing ImagePacket, ImageData, LayerData and CoarseLocationUpdate packets are not logged.\n" | ||
64 | + "If level <= 100 then incoming ViewerEffect and AgentAnimation and outgoing ViewerEffect and AvatarAnimation packets are not logged.\n" | ||
65 | + "If level <= 50 then outgoing ImprovedTerseObjectUpdate packets are not logged.\n" | ||
66 | + "If level <= 0 then no packets are logged.\n" | ||
67 | + "If --default is specified then the level becomes the default logging level for all subsequent agents.\n" | ||
68 | + "If --all is specified then the level becomes the default logging level for all current and subsequent agents.\n" | ||
69 | + "In these cases, you cannot also specify an avatar name.\n" | ||
70 | + "If an avatar name is given then only packets from that avatar are logged.", | ||
71 | HandlePacketCommand); | ||
72 | |||
73 | m_console.Commands.AddCommand( | ||
74 | "Debug", false, "debug lludp data out", | ||
75 | "debug lludp data out <level> <avatar-first-name> <avatar-last-name>\"", | ||
76 | "Turn on debugging for final outgoing data to the given user's client.", | ||
77 | "This operates at a much lower level than the packet command and prints out available details when the data is actually sent.\n" | ||
78 | + "If level > 0 then information about all outgoing UDP data for this avatar is logged.\n" | ||
79 | + "If level <= 0 then no information about outgoing UDP data for this avatar is logged.", | ||
80 | HandleDataCommand); | ||
81 | |||
82 | m_console.Commands.AddCommand( | ||
83 | "Debug", false, "debug lludp drop", | ||
84 | "debug lludp drop <in|out> <add|remove> <packet-name>", | ||
85 | "Drop all in or outbound packets that match the given name", | ||
86 | "For test purposes.", | ||
87 | HandleDropCommand); | ||
88 | |||
89 | m_console.Commands.AddCommand( | ||
90 | "Debug", | ||
91 | false, | ||
92 | "debug lludp start", | ||
93 | "debug lludp start <in|out|all>", | ||
94 | "Control LLUDP packet processing.", | ||
95 | "No effect if packet processing has already started.\n" | ||
96 | + "in - start inbound processing.\n" | ||
97 | + "out - start outbound processing.\n" | ||
98 | + "all - start in and outbound processing.\n", | ||
99 | HandleStartCommand); | ||
100 | |||
101 | m_console.Commands.AddCommand( | ||
102 | "Debug", | ||
103 | false, | ||
104 | "debug lludp stop", | ||
105 | "debug lludp stop <in|out|all>", | ||
106 | "Stop LLUDP packet processing.", | ||
107 | "No effect if packet processing has already stopped.\n" | ||
108 | + "in - stop inbound processing.\n" | ||
109 | + "out - stop outbound processing.\n" | ||
110 | + "all - stop in and outbound processing.\n", | ||
111 | HandleStopCommand); | ||
112 | |||
113 | m_console.Commands.AddCommand( | ||
114 | "Debug", | ||
115 | false, | ||
116 | "debug lludp pool", | ||
117 | "debug lludp pool <on|off>", | ||
118 | "Turn object pooling within the lludp component on or off.", | ||
119 | HandlePoolCommand); | ||
120 | |||
121 | m_console.Commands.AddCommand( | ||
122 | "Debug", | ||
123 | false, | ||
124 | "debug lludp status", | ||
125 | "debug lludp status", | ||
126 | "Return status of LLUDP packet processing.", | ||
127 | HandleStatusCommand); | ||
128 | |||
129 | m_console.Commands.AddCommand( | ||
130 | "Debug", | ||
131 | false, | ||
132 | "debug lludp throttles log", | ||
133 | "debug lludp throttles log <level> [<avatar-first-name> <avatar-last-name>]", | ||
134 | "Change debug logging level for throttles.", | ||
135 | "If level >= 0 then throttle debug logging is performed.\n" | ||
136 | + "If level <= 0 then no throttle debug logging is performed.", | ||
137 | HandleThrottleCommand); | ||
138 | |||
139 | m_console.Commands.AddCommand( | ||
140 | "Debug", | ||
141 | false, | ||
142 | "debug lludp throttles get", | ||
143 | "debug lludp throttles get [<avatar-first-name> <avatar-last-name>]", | ||
144 | "Return debug settings for throttles.", | ||
145 | "adaptive - true/false, controls adaptive throttle setting.\n" | ||
146 | + "request - request drip rate in kbps.\n" | ||
147 | + "max - the max kbps throttle allowed for the specified existing clients. Use 'debug lludp get new-client-throttle-max' to see the setting for new clients.\n", | ||
148 | HandleThrottleGetCommand); | ||
149 | |||
150 | m_console.Commands.AddCommand( | ||
151 | "Debug", | ||
152 | false, | ||
153 | "debug lludp throttles set", | ||
154 | "debug lludp throttles set <param> <value> [<avatar-first-name> <avatar-last-name>]", | ||
155 | "Set a throttle parameter for the given client.", | ||
156 | "adaptive - true/false, controls adaptive throttle setting.\n" | ||
157 | + "current - current drip rate in kbps.\n" | ||
158 | + "request - requested drip rate in kbps.\n" | ||
159 | + "max - the max kbps throttle allowed for the specified existing clients. Use 'debug lludp set new-client-throttle-max' to change the settings for new clients.\n", | ||
160 | HandleThrottleSetCommand); | ||
161 | |||
162 | m_console.Commands.AddCommand( | ||
163 | "Debug", | ||
164 | false, | ||
165 | "debug lludp get", | ||
166 | "debug lludp get", | ||
167 | "Get debug parameters for the server.", | ||
168 | "max-scene-throttle - the current max cumulative kbps provided for this scene to clients.\n" | ||
169 | + "max-new-client-throttle - the max kbps throttle allowed to new clients. Use 'debug lludp throttles get max' to see the settings for existing clients.", | ||
170 | HandleGetCommand); | ||
171 | |||
172 | m_console.Commands.AddCommand( | ||
173 | "Debug", | ||
174 | false, | ||
175 | "debug lludp set", | ||
176 | "debug lludp set <param> <value>", | ||
177 | "Set a parameter for the server.", | ||
178 | "max-scene-throttle - the current max cumulative kbps provided for this scene to clients.\n" | ||
179 | + "max-new-client-throttle - the max kbps throttle allowed to each new client. Use 'debug lludp throttles set max' to set for existing clients.", | ||
180 | HandleSetCommand); | ||
181 | |||
182 | m_console.Commands.AddCommand( | ||
183 | "Debug", | ||
184 | false, | ||
185 | "debug lludp toggle agentupdate", | ||
186 | "debug lludp toggle agentupdate", | ||
187 | "Toggle whether agentupdate packets are processed or simply discarded.", | ||
188 | HandleAgentUpdateCommand); | ||
189 | |||
190 | MainConsole.Instance.Commands.AddCommand( | ||
191 | "Debug", | ||
192 | false, | ||
193 | "debug lludp oqre", | ||
194 | "debug lludp oqre <start|stop|status>", | ||
195 | "Start, stop or get status of OutgoingQueueRefillEngine.", | ||
196 | "If stopped then refill requests are processed directly via the threadpool.", | ||
197 | HandleOqreCommand); | ||
198 | |||
199 | m_console.Commands.AddCommand( | ||
200 | "Debug", | ||
201 | false, | ||
202 | "debug lludp client get", | ||
203 | "debug lludp client get [<avatar-first-name> <avatar-last-name>]", | ||
204 | "Get debug parameters for the client. If no name is given then all client information is returned.", | ||
205 | "process-unacked-sends - Do we take action if a sent reliable packet has not been acked.", | ||
206 | HandleClientGetCommand); | ||
207 | |||
208 | m_console.Commands.AddCommand( | ||
209 | "Debug", | ||
210 | false, | ||
211 | "debug lludp client set", | ||
212 | "debug lludp client set <param> <value> [<avatar-first-name> <avatar-last-name>]", | ||
213 | "Set a debug parameter for a particular client. If no name is given then the value is set on all clients.", | ||
214 | "process-unacked-sends - Do we take action if a sent reliable packet has not been acked.", | ||
215 | HandleClientSetCommand); | ||
216 | } | ||
217 | |||
218 | private void HandleShowServerThrottlesCommand(string module, string[] args) | ||
219 | { | ||
220 | if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_udpServer.Scene) | ||
221 | return; | ||
222 | |||
223 | m_console.OutputFormat("Throttles for {0}", m_udpServer.Scene.Name); | ||
224 | ConsoleDisplayList cdl = new ConsoleDisplayList(); | ||
225 | cdl.AddRow("Adaptive throttles", m_udpServer.ThrottleRates.AdaptiveThrottlesEnabled); | ||
226 | |||
227 | long maxSceneDripRate = m_udpServer.Throttle.MaxDripRate; | ||
228 | cdl.AddRow( | ||
229 | "Max scene throttle", | ||
230 | maxSceneDripRate != 0 ? string.Format("{0} kbps", maxSceneDripRate * 8 / 1000) : "unset"); | ||
231 | |||
232 | int maxClientDripRate = m_udpServer.ThrottleRates.Total; | ||
233 | cdl.AddRow( | ||
234 | "Max new client throttle", | ||
235 | maxClientDripRate != 0 ? string.Format("{0} kbps", maxClientDripRate * 8 / 1000) : "unset"); | ||
236 | |||
237 | m_console.Output(cdl.ToString()); | ||
238 | |||
239 | m_console.OutputFormat("{0}\n", GetServerThrottlesReport(m_udpServer)); | ||
240 | } | ||
241 | |||
242 | private string GetServerThrottlesReport(LLUDPServer udpServer) | ||
243 | { | ||
244 | StringBuilder report = new StringBuilder(); | ||
245 | |||
246 | report.AppendFormat( | ||
247 | "{0,7} {1,8} {2,7} {3,7} {4,7} {5,7} {6,9} {7,7}\n", | ||
248 | "Total", | ||
249 | "Resend", | ||
250 | "Land", | ||
251 | "Wind", | ||
252 | "Cloud", | ||
253 | "Task", | ||
254 | "Texture", | ||
255 | "Asset"); | ||
256 | |||
257 | report.AppendFormat( | ||
258 | "{0,7} {1,8} {2,7} {3,7} {4,7} {5,7} {6,9} {7,7}\n", | ||
259 | "kb/s", | ||
260 | "kb/s", | ||
261 | "kb/s", | ||
262 | "kb/s", | ||
263 | "kb/s", | ||
264 | "kb/s", | ||
265 | "kb/s", | ||
266 | "kb/s"); | ||
267 | |||
268 | ThrottleRates throttleRates = udpServer.ThrottleRates; | ||
269 | report.AppendFormat( | ||
270 | "{0,7} {1,8} {2,7} {3,7} {4,7} {5,7} {6,9} {7,7}", | ||
271 | (throttleRates.Total * 8) / 1000, | ||
272 | (throttleRates.Resend * 8) / 1000, | ||
273 | (throttleRates.Land * 8) / 1000, | ||
274 | (throttleRates.Wind * 8) / 1000, | ||
275 | (throttleRates.Cloud * 8) / 1000, | ||
276 | (throttleRates.Task * 8) / 1000, | ||
277 | (throttleRates.Texture * 8) / 1000, | ||
278 | (throttleRates.Asset * 8) / 1000); | ||
279 | |||
280 | return report.ToString(); | ||
281 | } | ||
282 | |||
283 | protected string GetColumnEntry(string entry, int maxLength, int columnPadding) | ||
284 | { | ||
285 | return string.Format( | ||
286 | "{0,-" + maxLength + "}{1,-" + columnPadding + "}", | ||
287 | entry.Length > maxLength ? entry.Substring(0, maxLength) : entry, | ||
288 | ""); | ||
289 | } | ||
290 | |||
291 | private void HandleDataCommand(string module, string[] args) | ||
292 | { | ||
293 | if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_udpServer.Scene) | ||
294 | return; | ||
295 | |||
296 | if (args.Length != 7) | ||
297 | { | ||
298 | MainConsole.Instance.OutputFormat("Usage: debug lludp data out <true|false> <avatar-first-name> <avatar-last-name>"); | ||
299 | return; | ||
300 | } | ||
301 | |||
302 | int level; | ||
303 | if (!ConsoleUtil.TryParseConsoleInt(MainConsole.Instance, args[4], out level)) | ||
304 | return; | ||
305 | |||
306 | string firstName = args[5]; | ||
307 | string lastName = args[6]; | ||
308 | |||
309 | m_udpServer.Scene.ForEachScenePresence(sp => | ||
310 | { | ||
311 | if (sp.Firstname == firstName && sp.Lastname == lastName) | ||
312 | { | ||
313 | MainConsole.Instance.OutputFormat( | ||
314 | "Data debug for {0} ({1}) set to {2} in {3}", | ||
315 | sp.Name, sp.IsChildAgent ? "child" : "root", level, m_udpServer.Scene.Name); | ||
316 | |||
317 | ((LLClientView)sp.ControllingClient).UDPClient.DebugDataOutLevel = level; | ||
318 | } | ||
319 | }); | ||
320 | } | ||
321 | |||
322 | private void HandleThrottleCommand(string module, string[] args) | ||
323 | { | ||
324 | if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_udpServer.Scene) | ||
325 | return; | ||
326 | |||
327 | bool all = args.Length == 5; | ||
328 | bool one = args.Length == 7; | ||
329 | |||
330 | if (!all && !one) | ||
331 | { | ||
332 | MainConsole.Instance.OutputFormat( | ||
333 | "Usage: debug lludp throttles log <level> [<avatar-first-name> <avatar-last-name>]"); | ||
334 | return; | ||
335 | } | ||
336 | |||
337 | int level; | ||
338 | if (!ConsoleUtil.TryParseConsoleInt(MainConsole.Instance, args[4], out level)) | ||
339 | return; | ||
340 | |||
341 | string firstName = null; | ||
342 | string lastName = null; | ||
343 | |||
344 | if (one) | ||
345 | { | ||
346 | firstName = args[5]; | ||
347 | lastName = args[6]; | ||
348 | } | ||
349 | |||
350 | m_udpServer.Scene.ForEachScenePresence(sp => | ||
351 | { | ||
352 | if (all || (sp.Firstname == firstName && sp.Lastname == lastName)) | ||
353 | { | ||
354 | MainConsole.Instance.OutputFormat( | ||
355 | "Throttle log level for {0} ({1}) set to {2} in {3}", | ||
356 | sp.Name, sp.IsChildAgent ? "child" : "root", level, m_udpServer.Scene.Name); | ||
357 | |||
358 | ((LLClientView)sp.ControllingClient).UDPClient.ThrottleDebugLevel = level; | ||
359 | } | ||
360 | }); | ||
361 | } | ||
362 | |||
363 | private void HandleThrottleSetCommand(string module, string[] args) | ||
364 | { | ||
365 | if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_udpServer.Scene) | ||
366 | return; | ||
367 | |||
368 | bool all = args.Length == 6; | ||
369 | bool one = args.Length == 8; | ||
370 | |||
371 | if (!all && !one) | ||
372 | { | ||
373 | MainConsole.Instance.OutputFormat( | ||
374 | "Usage: debug lludp throttles set <param> <value> [<avatar-first-name> <avatar-last-name>]"); | ||
375 | return; | ||
376 | } | ||
377 | |||
378 | string param = args[4]; | ||
379 | string rawValue = args[5]; | ||
380 | |||
381 | string firstName = null; | ||
382 | string lastName = null; | ||
383 | |||
384 | if (one) | ||
385 | { | ||
386 | firstName = args[6]; | ||
387 | lastName = args[7]; | ||
388 | } | ||
389 | |||
390 | if (param == "adaptive") | ||
391 | { | ||
392 | bool newValue; | ||
393 | if (!ConsoleUtil.TryParseConsoleBool(MainConsole.Instance, rawValue, out newValue)) | ||
394 | return; | ||
395 | |||
396 | m_udpServer.Scene.ForEachScenePresence(sp => | ||
397 | { | ||
398 | if (all || (sp.Firstname == firstName && sp.Lastname == lastName)) | ||
399 | { | ||
400 | MainConsole.Instance.OutputFormat( | ||
401 | "Setting param {0} to {1} for {2} ({3}) in {4}", | ||
402 | param, newValue, sp.Name, sp.IsChildAgent ? "child" : "root", m_udpServer.Scene.Name); | ||
403 | |||
404 | LLUDPClient udpClient = ((LLClientView)sp.ControllingClient).UDPClient; | ||
405 | udpClient.FlowThrottle.AdaptiveEnabled = newValue; | ||
406 | // udpClient.FlowThrottle.MaxDripRate = 0; | ||
407 | // udpClient.FlowThrottle.AdjustedDripRate = 0; | ||
408 | } | ||
409 | }); | ||
410 | } | ||
411 | else if (param == "request") | ||
412 | { | ||
413 | int newValue; | ||
414 | if (!ConsoleUtil.TryParseConsoleInt(MainConsole.Instance, rawValue, out newValue)) | ||
415 | return; | ||
416 | |||
417 | int newCurrentThrottleKbps = newValue * 1000 / 8; | ||
418 | |||
419 | m_udpServer.Scene.ForEachScenePresence(sp => | ||
420 | { | ||
421 | if (all || (sp.Firstname == firstName && sp.Lastname == lastName)) | ||
422 | { | ||
423 | MainConsole.Instance.OutputFormat( | ||
424 | "Setting param {0} to {1} for {2} ({3}) in {4}", | ||
425 | param, newValue, sp.Name, sp.IsChildAgent ? "child" : "root", m_udpServer.Scene.Name); | ||
426 | |||
427 | LLUDPClient udpClient = ((LLClientView)sp.ControllingClient).UDPClient; | ||
428 | udpClient.FlowThrottle.RequestedDripRate = newCurrentThrottleKbps; | ||
429 | } | ||
430 | }); | ||
431 | } | ||
432 | else if (param == "max") | ||
433 | { | ||
434 | int newValue; | ||
435 | if (!ConsoleUtil.TryParseConsoleInt(MainConsole.Instance, rawValue, out newValue)) | ||
436 | return; | ||
437 | |||
438 | int newThrottleMaxKbps = newValue * 1000 / 8; | ||
439 | |||
440 | m_udpServer.Scene.ForEachScenePresence(sp => | ||
441 | { | ||
442 | if (all || (sp.Firstname == firstName && sp.Lastname == lastName)) | ||
443 | { | ||
444 | MainConsole.Instance.OutputFormat( | ||
445 | "Setting param {0} to {1} for {2} ({3}) in {4}", | ||
446 | param, newValue, sp.Name, sp.IsChildAgent ? "child" : "root", m_udpServer.Scene.Name); | ||
447 | |||
448 | LLUDPClient udpClient = ((LLClientView)sp.ControllingClient).UDPClient; | ||
449 | udpClient.FlowThrottle.MaxDripRate = newThrottleMaxKbps; | ||
450 | } | ||
451 | }); | ||
452 | } | ||
453 | } | ||
454 | |||
455 | private void HandleThrottleGetCommand(string module, string[] args) | ||
456 | { | ||
457 | if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_udpServer.Scene) | ||
458 | return; | ||
459 | |||
460 | bool all = args.Length == 4; | ||
461 | bool one = args.Length == 6; | ||
462 | |||
463 | if (!all && !one) | ||
464 | { | ||
465 | MainConsole.Instance.OutputFormat( | ||
466 | "Usage: debug lludp throttles get [<avatar-first-name> <avatar-last-name>]"); | ||
467 | return; | ||
468 | } | ||
469 | |||
470 | string firstName = null; | ||
471 | string lastName = null; | ||
472 | |||
473 | if (one) | ||
474 | { | ||
475 | firstName = args[4]; | ||
476 | lastName = args[5]; | ||
477 | } | ||
478 | |||
479 | m_udpServer.Scene.ForEachScenePresence(sp => | ||
480 | { | ||
481 | if (all || (sp.Firstname == firstName && sp.Lastname == lastName)) | ||
482 | { | ||
483 | m_console.OutputFormat( | ||
484 | "Status for {0} ({1}) in {2}", | ||
485 | sp.Name, sp.IsChildAgent ? "child" : "root", m_udpServer.Scene.Name); | ||
486 | |||
487 | LLUDPClient udpClient = ((LLClientView)sp.ControllingClient).UDPClient; | ||
488 | |||
489 | ConsoleDisplayList cdl = new ConsoleDisplayList(); | ||
490 | cdl.AddRow("adaptive", udpClient.FlowThrottle.AdaptiveEnabled); | ||
491 | cdl.AddRow("current", string.Format("{0} kbps", udpClient.FlowThrottle.DripRate * 8 / 1000)); | ||
492 | cdl.AddRow("request", string.Format("{0} kbps", udpClient.FlowThrottle.RequestedDripRate * 8 / 1000)); | ||
493 | cdl.AddRow("max", string.Format("{0} kbps", udpClient.FlowThrottle.MaxDripRate * 8 / 1000)); | ||
494 | |||
495 | m_console.Output(cdl.ToString()); | ||
496 | } | ||
497 | }); | ||
498 | } | ||
499 | |||
500 | private void HandleGetCommand(string module, string[] args) | ||
501 | { | ||
502 | if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_udpServer.Scene) | ||
503 | return; | ||
504 | |||
505 | m_console.OutputFormat("Debug settings for {0}", m_udpServer.Scene.Name); | ||
506 | ConsoleDisplayList cdl = new ConsoleDisplayList(); | ||
507 | |||
508 | long maxSceneDripRate = m_udpServer.Throttle.MaxDripRate; | ||
509 | cdl.AddRow( | ||
510 | "max-scene-throttle", | ||
511 | maxSceneDripRate != 0 ? string.Format("{0} kbps", maxSceneDripRate * 8 / 1000) : "unset"); | ||
512 | |||
513 | int maxClientDripRate = m_udpServer.ThrottleRates.Total; | ||
514 | cdl.AddRow( | ||
515 | "max-new-client-throttle", | ||
516 | maxClientDripRate != 0 ? string.Format("{0} kbps", maxClientDripRate * 8 / 1000) : "unset"); | ||
517 | |||
518 | m_console.Output(cdl.ToString()); | ||
519 | } | ||
520 | |||
521 | private void HandleSetCommand(string module, string[] args) | ||
522 | { | ||
523 | if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_udpServer.Scene) | ||
524 | return; | ||
525 | |||
526 | if (args.Length != 5) | ||
527 | { | ||
528 | MainConsole.Instance.OutputFormat("Usage: debug lludp set <param> <value>"); | ||
529 | return; | ||
530 | } | ||
531 | |||
532 | string param = args[3]; | ||
533 | string rawValue = args[4]; | ||
534 | |||
535 | int newValue; | ||
536 | |||
537 | if (param == "max-scene-throttle") | ||
538 | { | ||
539 | if (!ConsoleUtil.TryParseConsoleInt(MainConsole.Instance, rawValue, out newValue)) | ||
540 | return; | ||
541 | |||
542 | m_udpServer.Throttle.MaxDripRate = newValue * 1000 / 8; | ||
543 | } | ||
544 | else if (param == "max-new-client-throttle") | ||
545 | { | ||
546 | if (!ConsoleUtil.TryParseConsoleInt(MainConsole.Instance, rawValue, out newValue)) | ||
547 | return; | ||
548 | |||
549 | m_udpServer.ThrottleRates.Total = newValue * 1000 / 8; | ||
550 | } | ||
551 | else | ||
552 | { | ||
553 | return; | ||
554 | } | ||
555 | |||
556 | m_console.OutputFormat("{0} set to {1} in {2}", param, rawValue, m_udpServer.Scene.Name); | ||
557 | } | ||
558 | |||
559 | private void HandleClientGetCommand(string module, string[] args) | ||
560 | { | ||
561 | if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_udpServer.Scene) | ||
562 | return; | ||
563 | |||
564 | if (args.Length != 4 && args.Length != 6) | ||
565 | { | ||
566 | MainConsole.Instance.OutputFormat("Usage: debug lludp client get [<avatar-first-name> <avatar-last-name>]"); | ||
567 | return; | ||
568 | } | ||
569 | |||
570 | string name = null; | ||
571 | |||
572 | if (args.Length == 6) | ||
573 | name = string.Format("{0} {1}", args[4], args[5]); | ||
574 | |||
575 | m_udpServer.Scene.ForEachScenePresence( | ||
576 | sp => | ||
577 | { | ||
578 | if ((name == null || sp.Name == name) && sp.ControllingClient is LLClientView) | ||
579 | { | ||
580 | LLUDPClient udpClient = ((LLClientView)sp.ControllingClient).UDPClient; | ||
581 | |||
582 | m_console.OutputFormat( | ||
583 | "Client debug parameters for {0} ({1}) in {2}", | ||
584 | sp.Name, sp.IsChildAgent ? "child" : "root", m_udpServer.Scene.Name); | ||
585 | |||
586 | ConsoleDisplayList cdl = new ConsoleDisplayList(); | ||
587 | cdl.AddRow("process-unacked-sends", udpClient.ProcessUnackedSends); | ||
588 | |||
589 | m_console.Output(cdl.ToString()); | ||
590 | } | ||
591 | }); | ||
592 | } | ||
593 | |||
594 | private void HandleClientSetCommand(string module, string[] args) | ||
595 | { | ||
596 | if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_udpServer.Scene) | ||
597 | return; | ||
598 | |||
599 | if (args.Length != 6 && args.Length != 8) | ||
600 | { | ||
601 | MainConsole.Instance.OutputFormat("Usage: debug lludp client set <param> <value> [<avatar-first-name> <avatar-last-name>]"); | ||
602 | return; | ||
603 | } | ||
604 | |||
605 | string param = args[4]; | ||
606 | string rawValue = args[5]; | ||
607 | |||
608 | string name = null; | ||
609 | |||
610 | if (args.Length == 8) | ||
611 | name = string.Format("{0} {1}", args[6], args[7]); | ||
612 | |||
613 | if (param == "process-unacked-sends") | ||
614 | { | ||
615 | bool newValue; | ||
616 | |||
617 | if (!ConsoleUtil.TryParseConsoleBool(MainConsole.Instance, rawValue, out newValue)) | ||
618 | return; | ||
619 | |||
620 | m_udpServer.Scene.ForEachScenePresence( | ||
621 | sp => | ||
622 | { | ||
623 | if ((name == null || sp.Name == name) && sp.ControllingClient is LLClientView) | ||
624 | { | ||
625 | LLUDPClient udpClient = ((LLClientView)sp.ControllingClient).UDPClient; | ||
626 | udpClient.ProcessUnackedSends = newValue; | ||
627 | |||
628 | m_console.OutputFormat("{0} set to {1} for {2} in {3}", param, newValue, sp.Name, m_udpServer.Scene.Name); | ||
629 | } | ||
630 | }); | ||
631 | } | ||
632 | } | ||
633 | |||
634 | private void HandlePacketCommand(string module, string[] args) | ||
635 | { | ||
636 | if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_udpServer.Scene) | ||
637 | return; | ||
638 | |||
639 | bool setAsDefaultLevel = false; | ||
640 | bool setAll = false; | ||
641 | OptionSet optionSet = new OptionSet() | ||
642 | .Add("default", o => setAsDefaultLevel = (o != null)) | ||
643 | .Add("all", o => setAll = (o != null)); | ||
644 | List<string> filteredArgs = optionSet.Parse(args); | ||
645 | |||
646 | string name = null; | ||
647 | |||
648 | if (filteredArgs.Count == 6) | ||
649 | { | ||
650 | if (!(setAsDefaultLevel || setAll)) | ||
651 | { | ||
652 | name = string.Format("{0} {1}", filteredArgs[4], filteredArgs[5]); | ||
653 | } | ||
654 | else | ||
655 | { | ||
656 | MainConsole.Instance.OutputFormat("ERROR: Cannot specify a user name when setting default/all logging level"); | ||
657 | return; | ||
658 | } | ||
659 | } | ||
660 | |||
661 | if (filteredArgs.Count > 3) | ||
662 | { | ||
663 | int newDebug; | ||
664 | if (int.TryParse(filteredArgs[3], out newDebug)) | ||
665 | { | ||
666 | if (setAsDefaultLevel || setAll) | ||
667 | { | ||
668 | m_udpServer.DefaultClientPacketDebugLevel = newDebug; | ||
669 | |||
670 | MainConsole.Instance.OutputFormat( | ||
671 | "Packet debug for {0} clients set to {1} in {2}", | ||
672 | (setAll ? "all" : "future"), m_udpServer.DefaultClientPacketDebugLevel, m_udpServer.Scene.Name); | ||
673 | |||
674 | if (setAll) | ||
675 | { | ||
676 | m_udpServer.Scene.ForEachScenePresence(sp => | ||
677 | { | ||
678 | MainConsole.Instance.OutputFormat( | ||
679 | "Packet debug for {0} ({1}) set to {2} in {3}", | ||
680 | sp.Name, sp.IsChildAgent ? "child" : "root", newDebug, m_udpServer.Scene.Name); | ||
681 | |||
682 | sp.ControllingClient.DebugPacketLevel = newDebug; | ||
683 | }); | ||
684 | } | ||
685 | } | ||
686 | else | ||
687 | { | ||
688 | m_udpServer.Scene.ForEachScenePresence(sp => | ||
689 | { | ||
690 | if (name == null || sp.Name == name) | ||
691 | { | ||
692 | MainConsole.Instance.OutputFormat( | ||
693 | "Packet debug for {0} ({1}) set to {2} in {3}", | ||
694 | sp.Name, sp.IsChildAgent ? "child" : "root", newDebug, m_udpServer.Scene.Name); | ||
695 | |||
696 | sp.ControllingClient.DebugPacketLevel = newDebug; | ||
697 | } | ||
698 | }); | ||
699 | } | ||
700 | } | ||
701 | else | ||
702 | { | ||
703 | MainConsole.Instance.Output("Usage: debug lludp packet [--default | --all] 0..255 [<first-name> <last-name>]"); | ||
704 | } | ||
705 | } | ||
706 | } | ||
707 | |||
708 | private void HandleDropCommand(string module, string[] args) | ||
709 | { | ||
710 | if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_udpServer.Scene) | ||
711 | return; | ||
712 | |||
713 | if (args.Length != 6) | ||
714 | { | ||
715 | MainConsole.Instance.Output("Usage: debug lludp drop <in|out> <add|remove> <packet-name>"); | ||
716 | return; | ||
717 | } | ||
718 | |||
719 | string direction = args[3]; | ||
720 | string subCommand = args[4]; | ||
721 | string packetName = args[5]; | ||
722 | |||
723 | if (subCommand == "add") | ||
724 | { | ||
725 | MainConsole.Instance.OutputFormat( | ||
726 | "Adding packet {0} to {1} drop list for all connections in {2}", | ||
727 | direction, packetName, m_udpServer.Scene.Name); | ||
728 | |||
729 | m_udpServer.Scene.ForEachScenePresence( | ||
730 | sp => | ||
731 | { | ||
732 | LLClientView llcv = (LLClientView)sp.ControllingClient; | ||
733 | |||
734 | if (direction == "in") | ||
735 | llcv.AddInPacketToDropSet(packetName); | ||
736 | else if (direction == "out") | ||
737 | llcv.AddOutPacketToDropSet(packetName); | ||
738 | } | ||
739 | ); | ||
740 | } | ||
741 | else if (subCommand == "remove") | ||
742 | { | ||
743 | MainConsole.Instance.OutputFormat( | ||
744 | "Removing packet {0} from {1} drop list for all connections in {2}", | ||
745 | direction, packetName, m_udpServer.Scene.Name); | ||
746 | |||
747 | m_udpServer.Scene.ForEachScenePresence( | ||
748 | sp => | ||
749 | { | ||
750 | LLClientView llcv = (LLClientView)sp.ControllingClient; | ||
751 | |||
752 | if (direction == "in") | ||
753 | llcv.RemoveInPacketFromDropSet(packetName); | ||
754 | else if (direction == "out") | ||
755 | llcv.RemoveOutPacketFromDropSet(packetName); | ||
756 | } | ||
757 | ); | ||
758 | } | ||
759 | } | ||
760 | |||
761 | private void HandleStartCommand(string module, string[] args) | ||
762 | { | ||
763 | if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_udpServer.Scene) | ||
764 | return; | ||
765 | |||
766 | if (args.Length != 4) | ||
767 | { | ||
768 | MainConsole.Instance.Output("Usage: debug lludp start <in|out|all>"); | ||
769 | return; | ||
770 | } | ||
771 | |||
772 | string subCommand = args[3]; | ||
773 | |||
774 | if (subCommand == "in" || subCommand == "all") | ||
775 | m_udpServer.StartInbound(); | ||
776 | |||
777 | if (subCommand == "out" || subCommand == "all") | ||
778 | m_udpServer.StartOutbound(); | ||
779 | } | ||
780 | |||
781 | private void HandleStopCommand(string module, string[] args) | ||
782 | { | ||
783 | if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_udpServer.Scene) | ||
784 | return; | ||
785 | |||
786 | if (args.Length != 4) | ||
787 | { | ||
788 | MainConsole.Instance.Output("Usage: debug lludp stop <in|out|all>"); | ||
789 | return; | ||
790 | } | ||
791 | |||
792 | string subCommand = args[3]; | ||
793 | |||
794 | if (subCommand == "in" || subCommand == "all") | ||
795 | m_udpServer.StopInbound(); | ||
796 | |||
797 | if (subCommand == "out" || subCommand == "all") | ||
798 | m_udpServer.StopOutbound(); | ||
799 | } | ||
800 | |||
801 | private void HandlePoolCommand(string module, string[] args) | ||
802 | { | ||
803 | if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_udpServer.Scene) | ||
804 | return; | ||
805 | |||
806 | if (args.Length != 4) | ||
807 | { | ||
808 | MainConsole.Instance.Output("Usage: debug lludp pool <on|off>"); | ||
809 | return; | ||
810 | } | ||
811 | |||
812 | string enabled = args[3]; | ||
813 | |||
814 | if (enabled == "on") | ||
815 | { | ||
816 | if (m_udpServer.EnablePools()) | ||
817 | { | ||
818 | m_udpServer.EnablePoolStats(); | ||
819 | MainConsole.Instance.OutputFormat("Packet pools enabled on {0}", m_udpServer.Scene.Name); | ||
820 | } | ||
821 | } | ||
822 | else if (enabled == "off") | ||
823 | { | ||
824 | if (m_udpServer.DisablePools()) | ||
825 | { | ||
826 | m_udpServer.DisablePoolStats(); | ||
827 | MainConsole.Instance.OutputFormat("Packet pools disabled on {0}", m_udpServer.Scene.Name); | ||
828 | } | ||
829 | } | ||
830 | else | ||
831 | { | ||
832 | MainConsole.Instance.Output("Usage: debug lludp pool <on|off>"); | ||
833 | } | ||
834 | } | ||
835 | |||
836 | private void HandleAgentUpdateCommand(string module, string[] args) | ||
837 | { | ||
838 | if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_udpServer.Scene) | ||
839 | return; | ||
840 | |||
841 | m_udpServer.DiscardInboundAgentUpdates = !m_udpServer.DiscardInboundAgentUpdates; | ||
842 | |||
843 | MainConsole.Instance.OutputFormat( | ||
844 | "Discard AgentUpdates now {0} for {1}", m_udpServer.DiscardInboundAgentUpdates, m_udpServer.Scene.Name); | ||
845 | } | ||
846 | |||
847 | private void HandleStatusCommand(string module, string[] args) | ||
848 | { | ||
849 | if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_udpServer.Scene) | ||
850 | return; | ||
851 | |||
852 | MainConsole.Instance.OutputFormat( | ||
853 | "IN LLUDP packet processing for {0} is {1}", m_udpServer.Scene.Name, m_udpServer.IsRunningInbound ? "enabled" : "disabled"); | ||
854 | |||
855 | MainConsole.Instance.OutputFormat( | ||
856 | "OUT LLUDP packet processing for {0} is {1}", m_udpServer.Scene.Name, m_udpServer.IsRunningOutbound ? "enabled" : "disabled"); | ||
857 | |||
858 | MainConsole.Instance.OutputFormat("LLUDP pools in {0} are {1}", m_udpServer.Scene.Name, m_udpServer.UsePools ? "on" : "off"); | ||
859 | |||
860 | MainConsole.Instance.OutputFormat( | ||
861 | "Packet debug level for new clients is {0}", m_udpServer.DefaultClientPacketDebugLevel); | ||
862 | } | ||
863 | |||
864 | private void HandleOqreCommand(string module, string[] args) | ||
865 | { | ||
866 | if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_udpServer.Scene) | ||
867 | return; | ||
868 | |||
869 | if (args.Length != 4) | ||
870 | { | ||
871 | MainConsole.Instance.Output("Usage: debug lludp oqre <stop|start|status>"); | ||
872 | return; | ||
873 | } | ||
874 | |||
875 | string subCommand = args[3]; | ||
876 | |||
877 | if (subCommand == "stop") | ||
878 | { | ||
879 | m_udpServer.OqrEngine.Stop(); | ||
880 | MainConsole.Instance.OutputFormat("Stopped OQRE for {0}", m_udpServer.Scene.Name); | ||
881 | } | ||
882 | else if (subCommand == "start") | ||
883 | { | ||
884 | m_udpServer.OqrEngine.Start(); | ||
885 | MainConsole.Instance.OutputFormat("Started OQRE for {0}", m_udpServer.Scene.Name); | ||
886 | } | ||
887 | else if (subCommand == "status") | ||
888 | { | ||
889 | MainConsole.Instance.OutputFormat("OQRE in {0}", m_udpServer.Scene.Name); | ||
890 | MainConsole.Instance.OutputFormat("Running: {0}", m_udpServer.OqrEngine.IsRunning); | ||
891 | MainConsole.Instance.OutputFormat( | ||
892 | "Requests waiting: {0}", | ||
893 | m_udpServer.OqrEngine.IsRunning ? m_udpServer.OqrEngine.JobsWaiting.ToString() : "n/a"); | ||
894 | } | ||
895 | else | ||
896 | { | ||
897 | MainConsole.Instance.OutputFormat("Unrecognized OQRE subcommand {0}", subCommand); | ||
898 | } | ||
899 | } | ||
900 | } | ||
901 | } \ No newline at end of file | ||
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs index 0030dee..7171974 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs | |||
@@ -107,6 +107,62 @@ namespace OpenMetaverse | |||
107 | /// </summary> | 107 | /// </summary> |
108 | public float AverageReceiveTicksForLastSamplePeriod { get; private set; } | 108 | public float AverageReceiveTicksForLastSamplePeriod { get; private set; } |
109 | 109 | ||
110 | #region PacketDropDebugging | ||
111 | /// <summary> | ||
112 | /// For debugging purposes only... random number generator for dropping | ||
113 | /// outbound packets. | ||
114 | /// </summary> | ||
115 | private Random m_dropRandomGenerator = new Random(); | ||
116 | |||
117 | /// <summary> | ||
118 | /// For debugging purposes only... parameters for a simplified | ||
119 | /// model of packet loss with bursts, overall drop rate should | ||
120 | /// be roughly 1 - m_dropLengthProbability / (m_dropProbabiliy + m_dropLengthProbability) | ||
121 | /// which is about 1% for parameters 0.0015 and 0.15 | ||
122 | /// </summary> | ||
123 | private double m_dropProbability = 0.0030; | ||
124 | private double m_dropLengthProbability = 0.15; | ||
125 | private bool m_dropState = false; | ||
126 | |||
127 | /// <summary> | ||
128 | /// For debugging purposes only... parameters to control the time | ||
129 | /// duration over which packet loss bursts can occur, if no packets | ||
130 | /// have been sent for m_dropResetTicks milliseconds, then reset the | ||
131 | /// state of the packet dropper to its default. | ||
132 | /// </summary> | ||
133 | private int m_dropLastTick = 0; | ||
134 | private int m_dropResetTicks = 500; | ||
135 | |||
136 | /// <summary> | ||
137 | /// Debugging code used to simulate dropped packets with bursts | ||
138 | /// </summary> | ||
139 | private bool DropOutgoingPacket() | ||
140 | { | ||
141 | double rnum = m_dropRandomGenerator.NextDouble(); | ||
142 | |||
143 | // if the connection has been idle for awhile (more than m_dropResetTicks) then | ||
144 | // reset the state to the default state, don't continue a burst | ||
145 | int curtick = Util.EnvironmentTickCount(); | ||
146 | if (Util.EnvironmentTickCountSubtract(curtick, m_dropLastTick) > m_dropResetTicks) | ||
147 | m_dropState = false; | ||
148 | |||
149 | m_dropLastTick = curtick; | ||
150 | |||
151 | // if we are dropping packets, then the probability of dropping | ||
152 | // this packet is the probability that we stay in the burst | ||
153 | if (m_dropState) | ||
154 | { | ||
155 | m_dropState = (rnum < (1.0 - m_dropLengthProbability)) ? true : false; | ||
156 | } | ||
157 | else | ||
158 | { | ||
159 | m_dropState = (rnum < m_dropProbability) ? true : false; | ||
160 | } | ||
161 | |||
162 | return m_dropState; | ||
163 | } | ||
164 | #endregion PacketDropDebugging | ||
165 | |||
110 | /// <summary> | 166 | /// <summary> |
111 | /// Default constructor | 167 | /// Default constructor |
112 | /// </summary> | 168 | /// </summary> |
@@ -117,6 +173,10 @@ namespace OpenMetaverse | |||
117 | { | 173 | { |
118 | m_localBindAddress = bindAddress; | 174 | m_localBindAddress = bindAddress; |
119 | m_udpPort = port; | 175 | m_udpPort = port; |
176 | |||
177 | // for debugging purposes only, initializes the random number generator | ||
178 | // used for simulating packet loss | ||
179 | // m_dropRandomGenerator = new Random(); | ||
120 | } | 180 | } |
121 | 181 | ||
122 | /// <summary> | 182 | /// <summary> |
@@ -135,7 +195,7 @@ namespace OpenMetaverse | |||
135 | /// manner (not throwing an exception when the remote side resets the | 195 | /// manner (not throwing an exception when the remote side resets the |
136 | /// connection). This call is ignored on Mono where the flag is not | 196 | /// connection). This call is ignored on Mono where the flag is not |
137 | /// necessary</remarks> | 197 | /// necessary</remarks> |
138 | public void StartInbound(int recvBufferSize, bool asyncPacketHandling) | 198 | public virtual void StartInbound(int recvBufferSize, bool asyncPacketHandling) |
139 | { | 199 | { |
140 | m_asyncPacketHandling = asyncPacketHandling; | 200 | m_asyncPacketHandling = asyncPacketHandling; |
141 | 201 | ||
@@ -158,6 +218,17 @@ namespace OpenMetaverse | |||
158 | 218 | ||
159 | try | 219 | try |
160 | { | 220 | { |
221 | if (m_udpSocket.Ttl < 128) | ||
222 | { | ||
223 | m_udpSocket.Ttl = 128; | ||
224 | } | ||
225 | } | ||
226 | catch (SocketException) | ||
227 | { | ||
228 | m_log.Debug("[UDPBASE]: Failed to increase default TTL"); | ||
229 | } | ||
230 | try | ||
231 | { | ||
161 | // This udp socket flag is not supported under mono, | 232 | // This udp socket flag is not supported under mono, |
162 | // so we'll catch the exception and continue | 233 | // so we'll catch the exception and continue |
163 | m_udpSocket.IOControl(SIO_UDP_CONNRESET, new byte[] { 0 }, null); | 234 | m_udpSocket.IOControl(SIO_UDP_CONNRESET, new byte[] { 0 }, null); |
@@ -168,6 +239,12 @@ namespace OpenMetaverse | |||
168 | m_log.Debug("[UDPBASE]: SIO_UDP_CONNRESET flag not supported on this platform, ignoring"); | 239 | m_log.Debug("[UDPBASE]: SIO_UDP_CONNRESET flag not supported on this platform, ignoring"); |
169 | } | 240 | } |
170 | 241 | ||
242 | // On at least Mono 3.2.8, multiple UDP sockets can bind to the same port by default. At the moment | ||
243 | // we never want two regions to listen on the same port as they cannot demultiplex each other's messages, | ||
244 | // leading to a confusing bug. | ||
245 | // By default, Windows does not allow two sockets to bind to the same port. | ||
246 | m_udpSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, false); | ||
247 | |||
171 | if (recvBufferSize != 0) | 248 | if (recvBufferSize != 0) |
172 | m_udpSocket.ReceiveBufferSize = recvBufferSize; | 249 | m_udpSocket.ReceiveBufferSize = recvBufferSize; |
173 | 250 | ||
@@ -185,14 +262,14 @@ namespace OpenMetaverse | |||
185 | /// <summary> | 262 | /// <summary> |
186 | /// Start outbound UDP packet handling. | 263 | /// Start outbound UDP packet handling. |
187 | /// </summary> | 264 | /// </summary> |
188 | public void StartOutbound() | 265 | public virtual void StartOutbound() |
189 | { | 266 | { |
190 | m_log.DebugFormat("[UDPBASE]: Starting outbound UDP loop"); | 267 | m_log.DebugFormat("[UDPBASE]: Starting outbound UDP loop"); |
191 | 268 | ||
192 | IsRunningOutbound = true; | 269 | IsRunningOutbound = true; |
193 | } | 270 | } |
194 | 271 | ||
195 | public void StopInbound() | 272 | public virtual void StopInbound() |
196 | { | 273 | { |
197 | if (IsRunningInbound) | 274 | if (IsRunningInbound) |
198 | { | 275 | { |
@@ -203,14 +280,14 @@ namespace OpenMetaverse | |||
203 | } | 280 | } |
204 | } | 281 | } |
205 | 282 | ||
206 | public void StopOutbound() | 283 | public virtual void StopOutbound() |
207 | { | 284 | { |
208 | m_log.DebugFormat("[UDPBASE]: Stopping outbound UDP loop"); | 285 | m_log.DebugFormat("[UDPBASE]: Stopping outbound UDP loop"); |
209 | 286 | ||
210 | IsRunningOutbound = false; | 287 | IsRunningOutbound = false; |
211 | } | 288 | } |
212 | 289 | ||
213 | protected virtual bool EnablePools() | 290 | public virtual bool EnablePools() |
214 | { | 291 | { |
215 | if (!UsePools) | 292 | if (!UsePools) |
216 | { | 293 | { |
@@ -224,7 +301,7 @@ namespace OpenMetaverse | |||
224 | return false; | 301 | return false; |
225 | } | 302 | } |
226 | 303 | ||
227 | protected virtual bool DisablePools() | 304 | public virtual bool DisablePools() |
228 | { | 305 | { |
229 | if (UsePools) | 306 | if (UsePools) |
230 | { | 307 | { |
@@ -389,6 +466,12 @@ namespace OpenMetaverse | |||
389 | { | 466 | { |
390 | // if (IsRunningOutbound) | 467 | // if (IsRunningOutbound) |
391 | // { | 468 | // { |
469 | |||
470 | // This is strictly for debugging purposes to simulate dropped | ||
471 | // packets when testing throttles & retransmission code | ||
472 | // if (DropOutgoingPacket()) | ||
473 | // return; | ||
474 | |||
392 | try | 475 | try |
393 | { | 476 | { |
394 | m_udpSocket.BeginSendTo( | 477 | m_udpSocket.BeginSendTo( |
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/Properties/AssemblyInfo.cs b/OpenSim/Region/ClientStack/Linden/UDP/Properties/AssemblyInfo.cs index f8d0c02..8795c0c 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/Properties/AssemblyInfo.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/Properties/AssemblyInfo.cs | |||
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices; | |||
29 | // Build Number | 29 | // Build Number |
30 | // Revision | 30 | // Revision |
31 | // | 31 | // |
32 | [assembly: AssemblyVersion("0.8.0.*")] | 32 | [assembly: AssemblyVersion("0.8.2.*")] |
33 | 33 | ||
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs b/OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs index 9700224..a935dd2 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs | |||
@@ -36,7 +36,6 @@ using OpenSim.Framework; | |||
36 | using OpenSim.Framework.Monitoring; | 36 | using OpenSim.Framework.Monitoring; |
37 | using OpenSim.Region.Framework.Scenes; | 37 | using OpenSim.Region.Framework.Scenes; |
38 | using OpenSim.Tests.Common; | 38 | using OpenSim.Tests.Common; |
39 | using OpenSim.Tests.Common.Mock; | ||
40 | 39 | ||
41 | namespace OpenSim.Region.ClientStack.LindenUDP.Tests | 40 | namespace OpenSim.Region.ClientStack.LindenUDP.Tests |
42 | { | 41 | { |
@@ -47,7 +46,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests | |||
47 | public class BasicCircuitTests : OpenSimTestCase | 46 | public class BasicCircuitTests : OpenSimTestCase |
48 | { | 47 | { |
49 | private Scene m_scene; | 48 | private Scene m_scene; |
50 | private TestLLUDPServer m_udpServer; | ||
51 | 49 | ||
52 | [TestFixtureSetUp] | 50 | [TestFixtureSetUp] |
53 | public void FixtureInit() | 51 | public void FixtureInit() |
@@ -73,72 +71,23 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests | |||
73 | StatsManager.SimExtraStats = new SimExtraStatsCollector(); | 71 | StatsManager.SimExtraStats = new SimExtraStatsCollector(); |
74 | } | 72 | } |
75 | 73 | ||
76 | /// <summary> | 74 | // /// <summary> |
77 | /// Build an object name packet for test purposes | 75 | // /// Build an object name packet for test purposes |
78 | /// </summary> | 76 | // /// </summary> |
79 | /// <param name="objectLocalId"></param> | 77 | // /// <param name="objectLocalId"></param> |
80 | /// <param name="objectName"></param> | 78 | // /// <param name="objectName"></param> |
81 | private ObjectNamePacket BuildTestObjectNamePacket(uint objectLocalId, string objectName) | 79 | // private ObjectNamePacket BuildTestObjectNamePacket(uint objectLocalId, string objectName) |
82 | { | 80 | // { |
83 | ObjectNamePacket onp = new ObjectNamePacket(); | 81 | // ObjectNamePacket onp = new ObjectNamePacket(); |
84 | ObjectNamePacket.ObjectDataBlock odb = new ObjectNamePacket.ObjectDataBlock(); | 82 | // ObjectNamePacket.ObjectDataBlock odb = new ObjectNamePacket.ObjectDataBlock(); |
85 | odb.LocalID = objectLocalId; | 83 | // odb.LocalID = objectLocalId; |
86 | odb.Name = Utils.StringToBytes(objectName); | 84 | // odb.Name = Utils.StringToBytes(objectName); |
87 | onp.ObjectData = new ObjectNamePacket.ObjectDataBlock[] { odb }; | 85 | // onp.ObjectData = new ObjectNamePacket.ObjectDataBlock[] { odb }; |
88 | onp.Header.Zerocoded = false; | 86 | // onp.Header.Zerocoded = false; |
89 | 87 | // | |
90 | return onp; | 88 | // return onp; |
91 | } | 89 | // } |
92 | 90 | // | |
93 | private void AddUdpServer() | ||
94 | { | ||
95 | AddUdpServer(new IniConfigSource()); | ||
96 | } | ||
97 | |||
98 | private void AddUdpServer(IniConfigSource configSource) | ||
99 | { | ||
100 | uint port = 0; | ||
101 | AgentCircuitManager acm = m_scene.AuthenticateHandler; | ||
102 | |||
103 | m_udpServer = new TestLLUDPServer(IPAddress.Any, ref port, 0, false, configSource, acm); | ||
104 | m_udpServer.AddScene(m_scene); | ||
105 | } | ||
106 | |||
107 | /// <summary> | ||
108 | /// Used by tests that aren't testing this stage. | ||
109 | /// </summary> | ||
110 | private ScenePresence AddClient() | ||
111 | { | ||
112 | UUID myAgentUuid = TestHelpers.ParseTail(0x1); | ||
113 | UUID mySessionUuid = TestHelpers.ParseTail(0x2); | ||
114 | uint myCircuitCode = 123456; | ||
115 | IPEndPoint testEp = new IPEndPoint(IPAddress.Loopback, 999); | ||
116 | |||
117 | UseCircuitCodePacket uccp = new UseCircuitCodePacket(); | ||
118 | |||
119 | UseCircuitCodePacket.CircuitCodeBlock uccpCcBlock | ||
120 | = new UseCircuitCodePacket.CircuitCodeBlock(); | ||
121 | uccpCcBlock.Code = myCircuitCode; | ||
122 | uccpCcBlock.ID = myAgentUuid; | ||
123 | uccpCcBlock.SessionID = mySessionUuid; | ||
124 | uccp.CircuitCode = uccpCcBlock; | ||
125 | |||
126 | byte[] uccpBytes = uccp.ToBytes(); | ||
127 | UDPPacketBuffer upb = new UDPPacketBuffer(testEp, uccpBytes.Length); | ||
128 | upb.DataLength = uccpBytes.Length; // God knows why this isn't set by the constructor. | ||
129 | Buffer.BlockCopy(uccpBytes, 0, upb.Data, 0, uccpBytes.Length); | ||
130 | |||
131 | AgentCircuitData acd = new AgentCircuitData(); | ||
132 | acd.AgentID = myAgentUuid; | ||
133 | acd.SessionID = mySessionUuid; | ||
134 | |||
135 | m_scene.AuthenticateHandler.AddNewCircuit(myCircuitCode, acd); | ||
136 | |||
137 | m_udpServer.PacketReceived(upb); | ||
138 | |||
139 | return m_scene.GetScenePresence(myAgentUuid); | ||
140 | } | ||
141 | |||
142 | /// <summary> | 91 | /// <summary> |
143 | /// Test adding a client to the stack | 92 | /// Test adding a client to the stack |
144 | /// </summary> | 93 | /// </summary> |
@@ -148,7 +97,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests | |||
148 | TestHelpers.InMethod(); | 97 | TestHelpers.InMethod(); |
149 | // TestHelpers.EnableLogging(); | 98 | // TestHelpers.EnableLogging(); |
150 | 99 | ||
151 | AddUdpServer(); | 100 | TestLLUDPServer udpServer = ClientStackHelpers.AddUdpServer(m_scene); |
152 | 101 | ||
153 | UUID myAgentUuid = TestHelpers.ParseTail(0x1); | 102 | UUID myAgentUuid = TestHelpers.ParseTail(0x1); |
154 | UUID mySessionUuid = TestHelpers.ParseTail(0x2); | 103 | UUID mySessionUuid = TestHelpers.ParseTail(0x2); |
@@ -169,7 +118,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests | |||
169 | upb.DataLength = uccpBytes.Length; // God knows why this isn't set by the constructor. | 118 | upb.DataLength = uccpBytes.Length; // God knows why this isn't set by the constructor. |
170 | Buffer.BlockCopy(uccpBytes, 0, upb.Data, 0, uccpBytes.Length); | 119 | Buffer.BlockCopy(uccpBytes, 0, upb.Data, 0, uccpBytes.Length); |
171 | 120 | ||
172 | m_udpServer.PacketReceived(upb); | 121 | udpServer.PacketReceived(upb); |
173 | 122 | ||
174 | // Presence shouldn't exist since the circuit manager doesn't know about this circuit for authentication yet | 123 | // Presence shouldn't exist since the circuit manager doesn't know about this circuit for authentication yet |
175 | Assert.That(m_scene.GetScenePresence(myAgentUuid), Is.Null); | 124 | Assert.That(m_scene.GetScenePresence(myAgentUuid), Is.Null); |
@@ -180,15 +129,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests | |||
180 | 129 | ||
181 | m_scene.AuthenticateHandler.AddNewCircuit(myCircuitCode, acd); | 130 | m_scene.AuthenticateHandler.AddNewCircuit(myCircuitCode, acd); |
182 | 131 | ||
183 | m_udpServer.PacketReceived(upb); | 132 | udpServer.PacketReceived(upb); |
184 | 133 | ||
185 | // Should succeed now | 134 | // Should succeed now |
186 | ScenePresence sp = m_scene.GetScenePresence(myAgentUuid); | 135 | ScenePresence sp = m_scene.GetScenePresence(myAgentUuid); |
187 | Assert.That(sp.UUID, Is.EqualTo(myAgentUuid)); | 136 | Assert.That(sp.UUID, Is.EqualTo(myAgentUuid)); |
188 | 137 | ||
189 | Assert.That(m_udpServer.PacketsSent.Count, Is.EqualTo(1)); | 138 | Assert.That(udpServer.PacketsSent.Count, Is.EqualTo(1)); |
190 | 139 | ||
191 | Packet packet = m_udpServer.PacketsSent[0]; | 140 | Packet packet = udpServer.PacketsSent[0]; |
192 | Assert.That(packet, Is.InstanceOf(typeof(PacketAckPacket))); | 141 | Assert.That(packet, Is.InstanceOf(typeof(PacketAckPacket))); |
193 | 142 | ||
194 | PacketAckPacket ackPacket = packet as PacketAckPacket; | 143 | PacketAckPacket ackPacket = packet as PacketAckPacket; |
@@ -200,15 +149,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests | |||
200 | public void TestLogoutClientDueToAck() | 149 | public void TestLogoutClientDueToAck() |
201 | { | 150 | { |
202 | TestHelpers.InMethod(); | 151 | TestHelpers.InMethod(); |
203 | TestHelpers.EnableLogging(); | 152 | // TestHelpers.EnableLogging(); |
204 | 153 | ||
205 | IniConfigSource ics = new IniConfigSource(); | 154 | IniConfigSource ics = new IniConfigSource(); |
206 | IConfig config = ics.AddConfig("ClientStack.LindenUDP"); | 155 | IConfig config = ics.AddConfig("ClientStack.LindenUDP"); |
207 | config.Set("AckTimeout", -1); | 156 | config.Set("AckTimeout", -1); |
208 | AddUdpServer(ics); | 157 | TestLLUDPServer udpServer = ClientStackHelpers.AddUdpServer(m_scene, ics); |
158 | |||
159 | ScenePresence sp | ||
160 | = ClientStackHelpers.AddChildClient( | ||
161 | m_scene, udpServer, TestHelpers.ParseTail(0x1), TestHelpers.ParseTail(0x2), 123456); | ||
209 | 162 | ||
210 | ScenePresence sp = AddClient(); | 163 | udpServer.ClientOutgoingPacketHandler(sp.ControllingClient, true, false, false); |
211 | m_udpServer.ClientOutgoingPacketHandler(sp.ControllingClient, true, false, false); | ||
212 | 164 | ||
213 | ScenePresence spAfterAckTimeout = m_scene.GetScenePresence(sp.UUID); | 165 | ScenePresence spAfterAckTimeout = m_scene.GetScenePresence(sp.UUID); |
214 | Assert.That(spAfterAckTimeout, Is.Null); | 166 | Assert.That(spAfterAckTimeout, Is.Null); |
@@ -233,7 +185,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests | |||
233 | // testLLUDPServer.RemoveClientCircuit(myCircuitCode); | 185 | // testLLUDPServer.RemoveClientCircuit(myCircuitCode); |
234 | // Assert.IsFalse(testLLUDPServer.HasCircuit(myCircuitCode)); | 186 | // Assert.IsFalse(testLLUDPServer.HasCircuit(myCircuitCode)); |
235 | // | 187 | // |
236 | // // Check that removing a non-existant circuit doesn't have any bad effects | 188 | // // Check that removing a non-existent circuit doesn't have any bad effects |
237 | // testLLUDPServer.RemoveClientCircuit(101); | 189 | // testLLUDPServer.RemoveClientCircuit(101); |
238 | // Assert.IsFalse(testLLUDPServer.HasCircuit(101)); | 190 | // Assert.IsFalse(testLLUDPServer.HasCircuit(101)); |
239 | // } | 191 | // } |
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/Tests/LLImageManagerTests.cs b/OpenSim/Region/ClientStack/Linden/UDP/Tests/LLImageManagerTests.cs index 575e54c..6c57e6d 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/Tests/LLImageManagerTests.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/Tests/LLImageManagerTests.cs | |||
@@ -39,7 +39,6 @@ using OpenSim.Framework; | |||
39 | using OpenSim.Region.CoreModules.Agent.TextureSender; | 39 | using OpenSim.Region.CoreModules.Agent.TextureSender; |
40 | using OpenSim.Region.Framework.Scenes; | 40 | using OpenSim.Region.Framework.Scenes; |
41 | using OpenSim.Tests.Common; | 41 | using OpenSim.Tests.Common; |
42 | using OpenSim.Tests.Common.Mock; | ||
43 | 42 | ||
44 | namespace OpenSim.Region.ClientStack.LindenUDP.Tests | 43 | namespace OpenSim.Region.ClientStack.LindenUDP.Tests |
45 | { | 44 | { |
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/Tests/PacketHandlerTests.cs b/OpenSim/Region/ClientStack/Linden/UDP/Tests/PacketHandlerTests.cs index 5f73a94..92f1fc3 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/Tests/PacketHandlerTests.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/Tests/PacketHandlerTests.cs | |||
@@ -30,7 +30,6 @@ using NUnit.Framework; | |||
30 | using OpenMetaverse; | 30 | using OpenMetaverse; |
31 | using OpenMetaverse.Packets; | 31 | using OpenMetaverse.Packets; |
32 | using OpenSim.Framework; | 32 | using OpenSim.Framework; |
33 | using OpenSim.Tests.Common.Mock; | ||
34 | using OpenSim.Tests.Common; | 33 | using OpenSim.Tests.Common; |
35 | 34 | ||
36 | namespace OpenSim.Region.ClientStack.LindenUDP.Tests | 35 | namespace OpenSim.Region.ClientStack.LindenUDP.Tests |
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/Tests/ThrottleTests.cs b/OpenSim/Region/ClientStack/Linden/UDP/Tests/ThrottleTests.cs new file mode 100644 index 0000000..3c82a78 --- /dev/null +++ b/OpenSim/Region/ClientStack/Linden/UDP/Tests/ThrottleTests.cs | |||
@@ -0,0 +1,427 @@ | |||
1 | /* | ||
2 | * Copyright (c) Contributors, http://opensimulator.org/ | ||
3 | * See CONTRIBUTORS.TXT for a full list of copyright holders. | ||
4 | * | ||
5 | * Redistribution and use in source and binary forms, with or without | ||
6 | * modification, are permitted provided that the following conditions are met: | ||
7 | * * Redistributions of source code must retain the above copyright | ||
8 | * notice, this list of conditions and the following disclaimer. | ||
9 | * * Redistributions in binary form must reproduce the above copyright | ||
10 | * notice, this list of conditions and the following disclaimer in the | ||
11 | * documentation and/or other materials provided with the distribution. | ||
12 | * * Neither the name of the OpenSimulator Project nor the | ||
13 | * names of its contributors may be used to endorse or promote products | ||
14 | * derived from this software without specific prior written permission. | ||
15 | * | ||
16 | * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY | ||
17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
19 | * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY | ||
20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||
21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||
23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
26 | */ | ||
27 | |||
28 | using System; | ||
29 | using Nini.Config; | ||
30 | using NUnit.Framework; | ||
31 | using OpenMetaverse.Packets; | ||
32 | using OpenSim.Framework; | ||
33 | using OpenSim.Region.Framework.Scenes; | ||
34 | using OpenSim.Tests.Common; | ||
35 | |||
36 | namespace OpenSim.Region.ClientStack.LindenUDP.Tests | ||
37 | { | ||
38 | [TestFixture] | ||
39 | public class ThrottleTests : OpenSimTestCase | ||
40 | { | ||
41 | [TestFixtureSetUp] | ||
42 | public void FixtureInit() | ||
43 | { | ||
44 | // Don't allow tests to be bamboozled by asynchronous events. Execute everything on the same thread. | ||
45 | Util.FireAndForgetMethod = FireAndForgetMethod.RegressionTest; | ||
46 | } | ||
47 | |||
48 | [TestFixtureTearDown] | ||
49 | public void TearDown() | ||
50 | { | ||
51 | // We must set this back afterwards, otherwise later tests will fail since they're expecting multiple | ||
52 | // threads. Possibly, later tests should be rewritten so none of them require async stuff (which regression | ||
53 | // tests really shouldn't). | ||
54 | Util.FireAndForgetMethod = Util.DefaultFireAndForgetMethod; | ||
55 | } | ||
56 | |||
57 | [Test] | ||
58 | public void TestSetRequestDripRate() | ||
59 | { | ||
60 | TestHelpers.InMethod(); | ||
61 | |||
62 | TokenBucket tb = new TokenBucket("tb", null, 5000, 0); | ||
63 | AssertRates(tb, 5000, 0, 5000, 0); | ||
64 | |||
65 | tb.RequestedDripRate = 4000; | ||
66 | AssertRates(tb, 4000, 0, 4000, 0); | ||
67 | |||
68 | tb.RequestedDripRate = 6000; | ||
69 | AssertRates(tb, 6000, 0, 6000, 0); | ||
70 | } | ||
71 | |||
72 | [Test] | ||
73 | public void TestSetRequestDripRateWithMax() | ||
74 | { | ||
75 | TestHelpers.InMethod(); | ||
76 | |||
77 | TokenBucket tb = new TokenBucket("tb", null, 5000, 10000); | ||
78 | AssertRates(tb, 5000, 0, 5000, 10000); | ||
79 | |||
80 | tb.RequestedDripRate = 4000; | ||
81 | AssertRates(tb, 4000, 0, 4000, 10000); | ||
82 | |||
83 | tb.RequestedDripRate = 6000; | ||
84 | AssertRates(tb, 6000, 0, 6000, 10000); | ||
85 | |||
86 | tb.RequestedDripRate = 12000; | ||
87 | AssertRates(tb, 10000, 0, 10000, 10000); | ||
88 | } | ||
89 | |||
90 | [Test] | ||
91 | public void TestSetRequestDripRateWithChildren() | ||
92 | { | ||
93 | TestHelpers.InMethod(); | ||
94 | |||
95 | TokenBucket tbParent = new TokenBucket("tbParent", null, 0, 0); | ||
96 | TokenBucket tbChild1 = new TokenBucket("tbChild1", tbParent, 3000, 0); | ||
97 | TokenBucket tbChild2 = new TokenBucket("tbChild2", tbParent, 5000, 0); | ||
98 | |||
99 | AssertRates(tbParent, 8000, 8000, 8000, 0); | ||
100 | AssertRates(tbChild1, 3000, 0, 3000, 0); | ||
101 | AssertRates(tbChild2, 5000, 0, 5000, 0); | ||
102 | |||
103 | // Test: Setting a parent request greater than total children requests. | ||
104 | tbParent.RequestedDripRate = 10000; | ||
105 | |||
106 | AssertRates(tbParent, 10000, 8000, 8000, 0); | ||
107 | AssertRates(tbChild1, 3000, 0, 3000, 0); | ||
108 | AssertRates(tbChild2, 5000, 0, 5000, 0); | ||
109 | |||
110 | // Test: Setting a parent request lower than total children requests. | ||
111 | tbParent.RequestedDripRate = 6000; | ||
112 | |||
113 | AssertRates(tbParent, 6000, 8000, 6000, 0); | ||
114 | AssertRates(tbChild1, 3000, 0, 6000 / 8 * 3, 0); | ||
115 | AssertRates(tbChild2, 5000, 0, 6000 / 8 * 5, 0); | ||
116 | } | ||
117 | |||
118 | private void AssertRates( | ||
119 | TokenBucket tb, double requestedDripRate, double totalDripRequest, double dripRate, double maxDripRate) | ||
120 | { | ||
121 | Assert.AreEqual((int)requestedDripRate, tb.RequestedDripRate, "Requested drip rate"); | ||
122 | Assert.AreEqual((int)totalDripRequest, tb.TotalDripRequest, "Total drip request"); | ||
123 | Assert.AreEqual((int)dripRate, tb.DripRate, "Drip rate"); | ||
124 | Assert.AreEqual((int)maxDripRate, tb.MaxDripRate, "Max drip rate"); | ||
125 | } | ||
126 | |||
127 | [Test] | ||
128 | public void TestClientThrottleSetNoLimit() | ||
129 | { | ||
130 | TestHelpers.InMethod(); | ||
131 | // TestHelpers.EnableLogging(); | ||
132 | |||
133 | Scene scene = new SceneHelpers().SetupScene(); | ||
134 | TestLLUDPServer udpServer = ClientStackHelpers.AddUdpServer(scene); | ||
135 | |||
136 | ScenePresence sp | ||
137 | = ClientStackHelpers.AddChildClient( | ||
138 | scene, udpServer, TestHelpers.ParseTail(0x1), TestHelpers.ParseTail(0x2), 123456); | ||
139 | |||
140 | LLUDPClient udpClient = ((LLClientView)sp.ControllingClient).UDPClient; | ||
141 | |||
142 | udpServer.Throttle.DebugLevel = 1; | ||
143 | udpClient.ThrottleDebugLevel = 1; | ||
144 | |||
145 | int resendBytes = 1000; | ||
146 | int landBytes = 2000; | ||
147 | int windBytes = 3000; | ||
148 | int cloudBytes = 4000; | ||
149 | int taskBytes = 5000; | ||
150 | int textureBytes = 6000; | ||
151 | int assetBytes = 7000; | ||
152 | |||
153 | SetThrottles( | ||
154 | udpClient, resendBytes, landBytes, windBytes, cloudBytes, taskBytes, textureBytes, assetBytes); | ||
155 | |||
156 | // We expect this to be lower because of the minimum bound set by MTU | ||
157 | int totalBytes = LLUDPServer.MTU + landBytes + windBytes + cloudBytes + taskBytes + textureBytes + assetBytes; | ||
158 | |||
159 | AssertThrottles( | ||
160 | udpClient, | ||
161 | LLUDPServer.MTU, landBytes, windBytes, cloudBytes, taskBytes, | ||
162 | textureBytes, assetBytes, totalBytes, 0, 0); | ||
163 | } | ||
164 | |||
165 | [Test] | ||
166 | public void TestClientThrottleAdaptiveNoLimit() | ||
167 | { | ||
168 | TestHelpers.InMethod(); | ||
169 | // TestHelpers.EnableLogging(); | ||
170 | |||
171 | Scene scene = new SceneHelpers().SetupScene(); | ||
172 | |||
173 | IniConfigSource ics = new IniConfigSource(); | ||
174 | IConfig config = ics.AddConfig("ClientStack.LindenUDP"); | ||
175 | config.Set("enable_adaptive_throttles", true); | ||
176 | config.Set("adaptive_throttle_min_bps", 32000); | ||
177 | |||
178 | TestLLUDPServer udpServer = ClientStackHelpers.AddUdpServer(scene, ics); | ||
179 | |||
180 | ScenePresence sp | ||
181 | = ClientStackHelpers.AddChildClient( | ||
182 | scene, udpServer, TestHelpers.ParseTail(0x1), TestHelpers.ParseTail(0x2), 123456); | ||
183 | |||
184 | LLUDPClient udpClient = ((LLClientView)sp.ControllingClient).UDPClient; | ||
185 | |||
186 | udpServer.Throttle.DebugLevel = 1; | ||
187 | udpClient.ThrottleDebugLevel = 1; | ||
188 | |||
189 | // Total is 275000 | ||
190 | int resendBytes = 5000; // this is set low to test the minimum throttle override | ||
191 | int landBytes = 20000; | ||
192 | int windBytes = 30000; | ||
193 | int cloudBytes = 40000; | ||
194 | int taskBytes = 50000; | ||
195 | int textureBytes = 60000; | ||
196 | int assetBytes = 70000; | ||
197 | int totalBytes = resendBytes + landBytes + windBytes + cloudBytes + taskBytes + textureBytes + assetBytes; | ||
198 | |||
199 | SetThrottles( | ||
200 | udpClient, resendBytes, landBytes, windBytes, cloudBytes, taskBytes, textureBytes, assetBytes); | ||
201 | |||
202 | // Ratio of current adaptive drip rate to requested bytes, minimum rate is 32000 | ||
203 | double commitRatio = 32000.0 / totalBytes; | ||
204 | |||
205 | AssertThrottles( | ||
206 | udpClient, | ||
207 | LLUDPServer.MTU, landBytes * commitRatio, windBytes * commitRatio, cloudBytes * commitRatio, taskBytes * commitRatio, | ||
208 | textureBytes * commitRatio, assetBytes * commitRatio, udpClient.FlowThrottle.AdjustedDripRate, totalBytes, 0); | ||
209 | |||
210 | // Test an increase in target throttle, ack of 20 packets adds 20 * LLUDPServer.MTU bytes | ||
211 | // to the throttle, recompute commitratio from those numbers | ||
212 | udpClient.FlowThrottle.AcknowledgePackets(20); | ||
213 | commitRatio = (32000.0 + 20.0 * LLUDPServer.MTU) / totalBytes; | ||
214 | |||
215 | AssertThrottles( | ||
216 | udpClient, | ||
217 | LLUDPServer.MTU, landBytes * commitRatio, windBytes * commitRatio, cloudBytes * commitRatio, taskBytes * commitRatio, | ||
218 | textureBytes * commitRatio, assetBytes * commitRatio, udpClient.FlowThrottle.AdjustedDripRate, totalBytes, 0); | ||
219 | |||
220 | // Test a decrease in target throttle, adaptive throttle should cut the rate by 50% with a floor | ||
221 | // set by the minimum adaptive rate | ||
222 | udpClient.FlowThrottle.ExpirePackets(1); | ||
223 | commitRatio = (32000.0 + (20.0 * LLUDPServer.MTU)/Math.Pow(2,1)) / totalBytes; | ||
224 | |||
225 | AssertThrottles( | ||
226 | udpClient, | ||
227 | LLUDPServer.MTU, landBytes * commitRatio, windBytes * commitRatio, cloudBytes * commitRatio, taskBytes * commitRatio, | ||
228 | textureBytes * commitRatio, assetBytes * commitRatio, udpClient.FlowThrottle.AdjustedDripRate, totalBytes, 0); | ||
229 | } | ||
230 | |||
231 | /// <summary> | ||
232 | /// Test throttle setttings where max client throttle has been limited server side. | ||
233 | /// </summary> | ||
234 | [Test] | ||
235 | public void TestSingleClientThrottleRegionLimited() | ||
236 | { | ||
237 | TestHelpers.InMethod(); | ||
238 | // TestHelpers.EnableLogging(); | ||
239 | |||
240 | int resendBytes = 6000; | ||
241 | int landBytes = 8000; | ||
242 | int windBytes = 10000; | ||
243 | int cloudBytes = 12000; | ||
244 | int taskBytes = 14000; | ||
245 | int textureBytes = 16000; | ||
246 | int assetBytes = 18000; | ||
247 | int totalBytes | ||
248 | = (int)((resendBytes + landBytes + windBytes + cloudBytes + taskBytes + textureBytes + assetBytes) / 2); | ||
249 | |||
250 | Scene scene = new SceneHelpers().SetupScene(); | ||
251 | TestLLUDPServer udpServer = ClientStackHelpers.AddUdpServer(scene); | ||
252 | udpServer.Throttle.RequestedDripRate = totalBytes; | ||
253 | |||
254 | ScenePresence sp1 | ||
255 | = ClientStackHelpers.AddChildClient( | ||
256 | scene, udpServer, TestHelpers.ParseTail(0x1), TestHelpers.ParseTail(0x2), 123456); | ||
257 | |||
258 | LLUDPClient udpClient1 = ((LLClientView)sp1.ControllingClient).UDPClient; | ||
259 | |||
260 | SetThrottles( | ||
261 | udpClient1, resendBytes, landBytes, windBytes, cloudBytes, taskBytes, textureBytes, assetBytes); | ||
262 | |||
263 | AssertThrottles( | ||
264 | udpClient1, | ||
265 | resendBytes / 2, landBytes / 2, windBytes / 2, cloudBytes / 2, taskBytes / 2, | ||
266 | textureBytes / 2, assetBytes / 2, totalBytes, 0, 0); | ||
267 | |||
268 | // Test: Now add another client | ||
269 | ScenePresence sp2 | ||
270 | = ClientStackHelpers.AddChildClient( | ||
271 | scene, udpServer, TestHelpers.ParseTail(0x10), TestHelpers.ParseTail(0x20), 123457); | ||
272 | |||
273 | LLUDPClient udpClient2 = ((LLClientView)sp2.ControllingClient).UDPClient; | ||
274 | // udpClient.ThrottleDebugLevel = 1; | ||
275 | |||
276 | SetThrottles( | ||
277 | udpClient2, resendBytes, landBytes, windBytes, cloudBytes, taskBytes, textureBytes, assetBytes); | ||
278 | |||
279 | AssertThrottles( | ||
280 | udpClient1, | ||
281 | resendBytes / 4, landBytes / 4, windBytes / 4, cloudBytes / 4, taskBytes / 4, | ||
282 | textureBytes / 4, assetBytes / 4, totalBytes / 2, 0, 0); | ||
283 | |||
284 | AssertThrottles( | ||
285 | udpClient2, | ||
286 | resendBytes / 4, landBytes / 4, windBytes / 4, cloudBytes / 4, taskBytes / 4, | ||
287 | textureBytes / 4, assetBytes / 4, totalBytes / 2, 0, 0); | ||
288 | } | ||
289 | |||
290 | /// <summary> | ||
291 | /// Test throttle setttings where max client throttle has been limited server side. | ||
292 | /// </summary> | ||
293 | [Test] | ||
294 | public void TestClientThrottlePerClientLimited() | ||
295 | { | ||
296 | TestHelpers.InMethod(); | ||
297 | // TestHelpers.EnableLogging(); | ||
298 | |||
299 | int resendBytes = 4000; | ||
300 | int landBytes = 6000; | ||
301 | int windBytes = 8000; | ||
302 | int cloudBytes = 10000; | ||
303 | int taskBytes = 12000; | ||
304 | int textureBytes = 14000; | ||
305 | int assetBytes = 16000; | ||
306 | int totalBytes | ||
307 | = (int)((resendBytes + landBytes + windBytes + cloudBytes + taskBytes + textureBytes + assetBytes) / 2); | ||
308 | |||
309 | Scene scene = new SceneHelpers().SetupScene(); | ||
310 | TestLLUDPServer udpServer = ClientStackHelpers.AddUdpServer(scene); | ||
311 | udpServer.ThrottleRates.Total = totalBytes; | ||
312 | |||
313 | ScenePresence sp | ||
314 | = ClientStackHelpers.AddChildClient( | ||
315 | scene, udpServer, TestHelpers.ParseTail(0x1), TestHelpers.ParseTail(0x2), 123456); | ||
316 | |||
317 | LLUDPClient udpClient = ((LLClientView)sp.ControllingClient).UDPClient; | ||
318 | // udpClient.ThrottleDebugLevel = 1; | ||
319 | |||
320 | SetThrottles( | ||
321 | udpClient, resendBytes, landBytes, windBytes, cloudBytes, taskBytes, textureBytes, assetBytes); | ||
322 | |||
323 | AssertThrottles( | ||
324 | udpClient, | ||
325 | resendBytes / 2, landBytes / 2, windBytes / 2, cloudBytes / 2, taskBytes / 2, | ||
326 | textureBytes / 2, assetBytes / 2, totalBytes, 0, totalBytes); | ||
327 | } | ||
328 | |||
329 | [Test] | ||
330 | public void TestClientThrottlePerClientAndRegionLimited() | ||
331 | { | ||
332 | TestHelpers.InMethod(); | ||
333 | //TestHelpers.EnableLogging(); | ||
334 | |||
335 | int resendBytes = 4000; | ||
336 | int landBytes = 6000; | ||
337 | int windBytes = 8000; | ||
338 | int cloudBytes = 10000; | ||
339 | int taskBytes = 12000; | ||
340 | int textureBytes = 14000; | ||
341 | int assetBytes = 16000; | ||
342 | |||
343 | // current total 70000 | ||
344 | int totalBytes = resendBytes + landBytes + windBytes + cloudBytes + taskBytes + textureBytes + assetBytes; | ||
345 | |||
346 | Scene scene = new SceneHelpers().SetupScene(); | ||
347 | TestLLUDPServer udpServer = ClientStackHelpers.AddUdpServer(scene); | ||
348 | udpServer.ThrottleRates.Total = (int)(totalBytes * 1.1); | ||
349 | udpServer.Throttle.RequestedDripRate = (int)(totalBytes * 1.5); | ||
350 | |||
351 | ScenePresence sp1 | ||
352 | = ClientStackHelpers.AddChildClient( | ||
353 | scene, udpServer, TestHelpers.ParseTail(0x1), TestHelpers.ParseTail(0x2), 123456); | ||
354 | |||
355 | LLUDPClient udpClient1 = ((LLClientView)sp1.ControllingClient).UDPClient; | ||
356 | udpClient1.ThrottleDebugLevel = 1; | ||
357 | |||
358 | SetThrottles( | ||
359 | udpClient1, resendBytes, landBytes, windBytes, cloudBytes, taskBytes, textureBytes, assetBytes); | ||
360 | |||
361 | AssertThrottles( | ||
362 | udpClient1, | ||
363 | resendBytes, landBytes, windBytes, cloudBytes, taskBytes, | ||
364 | textureBytes, assetBytes, totalBytes, 0, totalBytes * 1.1); | ||
365 | |||
366 | // Now add another client | ||
367 | ScenePresence sp2 | ||
368 | = ClientStackHelpers.AddChildClient( | ||
369 | scene, udpServer, TestHelpers.ParseTail(0x10), TestHelpers.ParseTail(0x20), 123457); | ||
370 | |||
371 | LLUDPClient udpClient2 = ((LLClientView)sp2.ControllingClient).UDPClient; | ||
372 | udpClient2.ThrottleDebugLevel = 1; | ||
373 | |||
374 | SetThrottles( | ||
375 | udpClient2, resendBytes, landBytes, windBytes, cloudBytes, taskBytes, textureBytes, assetBytes); | ||
376 | |||
377 | AssertThrottles( | ||
378 | udpClient1, | ||
379 | resendBytes * 0.75, landBytes * 0.75, windBytes * 0.75, cloudBytes * 0.75, taskBytes * 0.75, | ||
380 | textureBytes * 0.75, assetBytes * 0.75, totalBytes * 0.75, 0, totalBytes * 1.1); | ||
381 | |||
382 | AssertThrottles( | ||
383 | udpClient2, | ||
384 | resendBytes * 0.75, landBytes * 0.75, windBytes * 0.75, cloudBytes * 0.75, taskBytes * 0.75, | ||
385 | textureBytes * 0.75, assetBytes * 0.75, totalBytes * 0.75, 0, totalBytes * 1.1); | ||
386 | } | ||
387 | |||
388 | private void AssertThrottles( | ||
389 | LLUDPClient udpClient, | ||
390 | double resendBytes, double landBytes, double windBytes, double cloudBytes, double taskBytes, double textureBytes, double assetBytes, | ||
391 | double totalBytes, double targetBytes, double maxBytes) | ||
392 | { | ||
393 | ClientInfo ci = udpClient.GetClientInfo(); | ||
394 | |||
395 | // Console.WriteLine( | ||
396 | // "Resend={0}, Land={1}, Wind={2}, Cloud={3}, Task={4}, Texture={5}, Asset={6}, TOTAL = {7}", | ||
397 | // ci.resendThrottle, ci.landThrottle, ci.windThrottle, ci.cloudThrottle, ci.taskThrottle, ci.textureThrottle, ci.assetThrottle, ci.totalThrottle); | ||
398 | |||
399 | Assert.AreEqual((int)resendBytes, ci.resendThrottle, "Resend"); | ||
400 | Assert.AreEqual((int)landBytes, ci.landThrottle, "Land"); | ||
401 | Assert.AreEqual((int)windBytes, ci.windThrottle, "Wind"); | ||
402 | Assert.AreEqual((int)cloudBytes, ci.cloudThrottle, "Cloud"); | ||
403 | Assert.AreEqual((int)taskBytes, ci.taskThrottle, "Task"); | ||
404 | Assert.AreEqual((int)textureBytes, ci.textureThrottle, "Texture"); | ||
405 | Assert.AreEqual((int)assetBytes, ci.assetThrottle, "Asset"); | ||
406 | Assert.AreEqual((int)totalBytes, ci.totalThrottle, "Total"); | ||
407 | Assert.AreEqual((int)targetBytes, ci.targetThrottle, "Target"); | ||
408 | Assert.AreEqual((int)maxBytes, ci.maxThrottle, "Max"); | ||
409 | } | ||
410 | |||
411 | private void SetThrottles( | ||
412 | LLUDPClient udpClient, int resendBytes, int landBytes, int windBytes, int cloudBytes, int taskBytes, int textureBytes, int assetBytes) | ||
413 | { | ||
414 | byte[] throttles = new byte[28]; | ||
415 | |||
416 | Array.Copy(BitConverter.GetBytes((float)resendBytes * 8), 0, throttles, 0, 4); | ||
417 | Array.Copy(BitConverter.GetBytes((float)landBytes * 8), 0, throttles, 4, 4); | ||
418 | Array.Copy(BitConverter.GetBytes((float)windBytes * 8), 0, throttles, 8, 4); | ||
419 | Array.Copy(BitConverter.GetBytes((float)cloudBytes * 8), 0, throttles, 12, 4); | ||
420 | Array.Copy(BitConverter.GetBytes((float)taskBytes * 8), 0, throttles, 16, 4); | ||
421 | Array.Copy(BitConverter.GetBytes((float)textureBytes * 8), 0, throttles, 20, 4); | ||
422 | Array.Copy(BitConverter.GetBytes((float)assetBytes * 8), 0, throttles, 24, 4); | ||
423 | |||
424 | udpClient.SetThrottles(throttles); | ||
425 | } | ||
426 | } | ||
427 | } \ No newline at end of file | ||
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/ThrottleRates.cs b/OpenSim/Region/ClientStack/Linden/UDP/ThrottleRates.cs index 451dee5..076551f 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/ThrottleRates.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/ThrottleRates.cs | |||
@@ -58,7 +58,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
58 | 58 | ||
59 | /// <summary>Flag used to enable adaptive throttles</summary> | 59 | /// <summary>Flag used to enable adaptive throttles</summary> |
60 | public bool AdaptiveThrottlesEnabled; | 60 | public bool AdaptiveThrottlesEnabled; |
61 | 61 | ||
62 | /// <summary> | ||
63 | /// Set the minimum rate that the adaptive throttles can set. The viewer | ||
64 | /// can still throttle lower than this, but the adaptive throttles will | ||
65 | /// never decrease rates below this no matter how many packets are dropped | ||
66 | /// </summary> | ||
67 | public Int64 MinimumAdaptiveThrottleRate; | ||
68 | |||
62 | /// <summary>Amount of the texture throttle to steal for the task throttle</summary> | 69 | /// <summary>Amount of the texture throttle to steal for the task throttle</summary> |
63 | public double CannibalizeTextureRate; | 70 | public double CannibalizeTextureRate; |
64 | 71 | ||
@@ -75,6 +82,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
75 | { | 82 | { |
76 | IConfig throttleConfig = config.Configs["ClientStack.LindenUDP"]; | 83 | IConfig throttleConfig = config.Configs["ClientStack.LindenUDP"]; |
77 | 84 | ||
85 | // Current default total is 66750 | ||
78 | Resend = throttleConfig.GetInt("resend_default", 6625); | 86 | Resend = throttleConfig.GetInt("resend_default", 6625); |
79 | Land = throttleConfig.GetInt("land_default", 9125); | 87 | Land = throttleConfig.GetInt("land_default", 9125); |
80 | Wind = throttleConfig.GetInt("wind_default", 1750); | 88 | Wind = throttleConfig.GetInt("wind_default", 1750); |
@@ -93,7 +101,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
93 | BrustTime *= 1e-3f; | 101 | BrustTime *= 1e-3f; |
94 | 102 | ||
95 | AdaptiveThrottlesEnabled = throttleConfig.GetBoolean("enable_adaptive_throttles", false); | 103 | AdaptiveThrottlesEnabled = throttleConfig.GetBoolean("enable_adaptive_throttles", false); |
96 | 104 | MinimumAdaptiveThrottleRate = throttleConfig.GetInt("adaptive_throttle_min_bps", 32000); | |
105 | |||
97 | CannibalizeTextureRate = (double)throttleConfig.GetFloat("CannibalizeTextureRate", 0.0f); | 106 | CannibalizeTextureRate = (double)throttleConfig.GetFloat("CannibalizeTextureRate", 0.0f); |
98 | CannibalizeTextureRate = Util.Clamp<double>(CannibalizeTextureRate,0.0, 0.9); | 107 | CannibalizeTextureRate = Util.Clamp<double>(CannibalizeTextureRate,0.0, 0.9); |
99 | } | 108 | } |
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/TokenBucket.cs b/OpenSim/Region/ClientStack/Linden/UDP/TokenBucket.cs index 1877cf0..7a42d82 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/TokenBucket.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/TokenBucket.cs | |||
@@ -1,4 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) Contributors, http://opensimulator.org/ | 2 | * Copyright (c) Contributors, http://opensimulator.org/ |
3 | * See CONTRIBUTORS.TXT for a full list of copyright holders. | 3 | * See CONTRIBUTORS.TXT for a full list of copyright holders. |
4 | * | 4 | * |
@@ -42,11 +42,24 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
42 | public class TokenBucket | 42 | public class TokenBucket |
43 | { | 43 | { |
44 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 44 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
45 | <<<<<<< HEAD | ||
46 | |||
47 | public string Identifier { get; private set; } | ||
48 | |||
49 | public int DebugLevel { get; set; } | ||
50 | |||
51 | /// <summary> | ||
52 | /// Number of ticks (ms) per quantum, drip rate and max burst | ||
53 | /// are defined over this interval. | ||
54 | /// </summary> | ||
55 | protected const Int32 m_ticksPerQuantum = 1000; | ||
56 | ======= | ||
45 | private static Int32 m_counter = 0; | 57 | private static Int32 m_counter = 0; |
46 | 58 | ||
47 | // private Int32 m_identifier; | 59 | // private Int32 m_identifier; |
48 | 60 | ||
49 | protected const float m_timeScale = 1e-3f; | 61 | protected const float m_timeScale = 1e-3f; |
62 | >>>>>>> avn/ubitvar | ||
50 | 63 | ||
51 | /// <summary> | 64 | /// <summary> |
52 | /// This is the number of m_minimumDripRate bytes | 65 | /// This is the number of m_minimumDripRate bytes |
@@ -59,7 +72,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
59 | 72 | ||
60 | /// <summary> | 73 | /// <summary> |
61 | /// </summary> | 74 | /// </summary> |
75 | <<<<<<< HEAD | ||
76 | protected const Int32 m_minimumDripRate = LLUDPServer.MTU; | ||
77 | ======= | ||
62 | protected const float m_minimumDripRate = 1400; | 78 | protected const float m_minimumDripRate = 1400; |
79 | >>>>>>> avn/ubitvar | ||
63 | 80 | ||
64 | /// <summary>Time of the last drip, in system ticks</summary> | 81 | /// <summary>Time of the last drip, in system ticks</summary> |
65 | protected Int32 m_lastDrip; | 82 | protected Int32 m_lastDrip; |
@@ -73,21 +90,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
73 | /// <summary> | 90 | /// <summary> |
74 | /// Map of children buckets and their requested maximum burst rate | 91 | /// Map of children buckets and their requested maximum burst rate |
75 | /// </summary> | 92 | /// </summary> |
93 | <<<<<<< HEAD | ||
94 | protected Dictionary<TokenBucket,Int64> m_children = new Dictionary<TokenBucket,Int64>(); | ||
95 | ======= | ||
76 | protected Dictionary<TokenBucket, float> m_children = new Dictionary<TokenBucket, float>(); | 96 | protected Dictionary<TokenBucket, float> m_children = new Dictionary<TokenBucket, float>(); |
77 | 97 | ||
78 | #region Properties | 98 | #region Properties |
99 | >>>>>>> avn/ubitvar | ||
79 | 100 | ||
80 | /// <summary> | 101 | /// <summary> |
81 | /// The parent bucket of this bucket, or null if this bucket has no | 102 | /// The parent bucket of this bucket, or null if this bucket has no |
82 | /// parent. The parent bucket will limit the aggregate bandwidth of all | 103 | /// parent. The parent bucket will limit the aggregate bandwidth of all |
83 | /// of its children buckets | 104 | /// of its children buckets |
84 | /// </summary> | 105 | /// </summary> |
85 | protected TokenBucket m_parent; | 106 | public TokenBucket Parent { get; protected set; } |
86 | public TokenBucket Parent | ||
87 | { | ||
88 | get { return m_parent; } | ||
89 | set { m_parent = value; } | ||
90 | } | ||
91 | 107 | ||
92 | /// <summary> | 108 | /// <summary> |
93 | /// This is the maximum number | 109 | /// This is the maximum number |
@@ -120,11 +136,68 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
120 | } | 136 | } |
121 | 137 | ||
122 | /// <summary> | 138 | /// <summary> |
123 | /// The speed limit of this bucket in bytes per second. This is the | 139 | /// The requested drip rate for this particular bucket. |
124 | /// number of tokens that are added to the bucket per quantum | ||
125 | /// </summary> | 140 | /// </summary> |
126 | /// <remarks>Tokens are added to the bucket any time | 141 | /// <remarks> |
142 | /// 0 then TotalDripRequest is used instead. | ||
143 | /// Can never be above MaxDripRate. | ||
144 | /// Tokens are added to the bucket at any time | ||
127 | /// <seealso cref="RemoveTokens"/> is called, at the granularity of | 145 | /// <seealso cref="RemoveTokens"/> is called, at the granularity of |
146 | <<<<<<< HEAD | ||
147 | /// the system tick interval (typically around 15-22ms) | ||
148 | /// FIXME: It is extremely confusing to be able to set a RequestedDripRate of 0 and then receive a positive | ||
149 | /// number on get if TotalDripRequest is set. This also stops us being able to retrieve the fact that | ||
150 | /// RequestedDripRate is set to 0. Really, this should always return m_dripRate and then we can get | ||
151 | /// (m_dripRate == 0 ? TotalDripRequest : m_dripRate) on some other properties. | ||
152 | /// </remarks> | ||
153 | public virtual Int64 RequestedDripRate | ||
154 | { | ||
155 | get { return (m_dripRate == 0 ? TotalDripRequest : m_dripRate); } | ||
156 | set | ||
157 | { | ||
158 | if (value <= 0) | ||
159 | m_dripRate = 0; | ||
160 | else if (MaxDripRate > 0 && value > MaxDripRate) | ||
161 | m_dripRate = MaxDripRate; | ||
162 | else | ||
163 | m_dripRate = value; | ||
164 | |||
165 | m_burstRate = (Int64)((double)m_dripRate * m_quantumsPerBurst); | ||
166 | |||
167 | if (Parent != null) | ||
168 | Parent.RegisterRequest(this, m_dripRate); | ||
169 | } | ||
170 | } | ||
171 | |||
172 | /// <summary> | ||
173 | /// Gets the drip rate. | ||
174 | /// </summary> | ||
175 | /// <value> | ||
176 | /// DripRate can never be above max drip rate or below min drip rate. | ||
177 | /// If we are a child bucket then the drip rate return is modifed by the total load on the capacity of the | ||
178 | /// parent bucket. | ||
179 | /// </value> | ||
180 | public virtual Int64 DripRate | ||
181 | { | ||
182 | get | ||
183 | { | ||
184 | double rate; | ||
185 | |||
186 | // FIXME: This doesn't properly work if we have a parent and children and a requested drip rate set | ||
187 | // on ourselves which is not equal to the child drip rates. | ||
188 | if (Parent == null) | ||
189 | { | ||
190 | if (TotalDripRequest > 0) | ||
191 | rate = Math.Min(RequestedDripRate, TotalDripRequest); | ||
192 | else | ||
193 | rate = RequestedDripRate; | ||
194 | } | ||
195 | else | ||
196 | { | ||
197 | rate = (double)RequestedDripRate * Parent.DripRateModifier(); | ||
198 | } | ||
199 | |||
200 | ======= | ||
128 | /// the system tick interval (typically around 15-22ms)</remarks> | 201 | /// the system tick interval (typically around 15-22ms)</remarks> |
129 | protected float m_dripRate; | 202 | protected float m_dripRate; |
130 | public virtual float RequestedDripRate | 203 | public virtual float RequestedDripRate |
@@ -147,17 +220,28 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
147 | return rate; | 220 | return rate; |
148 | 221 | ||
149 | rate *= m_parent.DripRateModifier(); | 222 | rate *= m_parent.DripRateModifier(); |
223 | >>>>>>> avn/ubitvar | ||
150 | if (rate < m_minimumDripRate) | 224 | if (rate < m_minimumDripRate) |
151 | rate = m_minimumDripRate; | 225 | rate = m_minimumDripRate; |
226 | else if (MaxDripRate > 0 && rate > MaxDripRate) | ||
227 | rate = MaxDripRate; | ||
152 | 228 | ||
153 | return (float)rate; | 229 | return (float)rate; |
154 | } | 230 | } |
155 | } | 231 | } |
232 | protected Int64 m_dripRate; | ||
233 | |||
234 | // <summary> | ||
235 | // The maximum rate for flow control. Drip rate can never be greater than this. | ||
236 | // </summary> | ||
237 | public Int64 MaxDripRate { get; set; } | ||
156 | 238 | ||
157 | /// <summary> | 239 | /// <summary> |
158 | /// The current total of the requested maximum burst rates of | 240 | /// The current total of the requested maximum burst rates of children buckets. |
159 | /// this bucket's children buckets. | ||
160 | /// </summary> | 241 | /// </summary> |
242 | <<<<<<< HEAD | ||
243 | public Int64 TotalDripRequest { get; protected set; } | ||
244 | ======= | ||
161 | protected float m_totalDripRequest; | 245 | protected float m_totalDripRequest; |
162 | public float TotalDripRequest | 246 | public float TotalDripRequest |
163 | { | 247 | { |
@@ -168,31 +252,44 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
168 | #endregion Properties | 252 | #endregion Properties |
169 | 253 | ||
170 | #region Constructor | 254 | #region Constructor |
255 | >>>>>>> avn/ubitvar | ||
171 | 256 | ||
172 | /// <summary> | 257 | /// <summary> |
173 | /// Default constructor | 258 | /// Default constructor |
174 | /// </summary> | 259 | /// </summary> |
260 | /// <param name="identifier">Identifier for this token bucket</param> | ||
175 | /// <param name="parent">Parent bucket if this is a child bucket, or | 261 | /// <param name="parent">Parent bucket if this is a child bucket, or |
176 | /// null if this is a root bucket</param> | 262 | /// null if this is a root bucket</param> |
263 | <<<<<<< HEAD | ||
264 | /// <param name="requestedDripRate"> | ||
265 | /// Requested rate that the bucket fills, in bytes per | ||
266 | /// second. If zero, the bucket always remains full. | ||
267 | /// </param> | ||
268 | public TokenBucket(string identifier, TokenBucket parent, Int64 requestedDripRate, Int64 maxDripRate) | ||
269 | ======= | ||
177 | /// <param name="maxBurst">Maximum size of the bucket in bytes, or | 270 | /// <param name="maxBurst">Maximum size of the bucket in bytes, or |
178 | /// zero if this bucket has no maximum capacity</param> | 271 | /// zero if this bucket has no maximum capacity</param> |
179 | /// <param name="dripRate">Rate that the bucket fills, in bytes per | 272 | /// <param name="dripRate">Rate that the bucket fills, in bytes per |
180 | /// second. If zero, the bucket always remains full</param> | 273 | /// second. If zero, the bucket always remains full</param> |
181 | public TokenBucket(TokenBucket parent, float dripRate, float MaxBurst) | 274 | public TokenBucket(TokenBucket parent, float dripRate, float MaxBurst) |
275 | >>>>>>> avn/ubitvar | ||
182 | { | 276 | { |
183 | // m_identifier = m_counter++; | 277 | Identifier = identifier; |
184 | m_counter++; | ||
185 | 278 | ||
186 | Parent = parent; | 279 | Parent = parent; |
280 | <<<<<<< HEAD | ||
281 | RequestedDripRate = requestedDripRate; | ||
282 | MaxDripRate = maxDripRate; | ||
283 | m_lastDrip = Util.EnvironmentTickCount(); | ||
284 | ======= | ||
187 | RequestedDripRate = dripRate; | 285 | RequestedDripRate = dripRate; |
188 | RequestedBurst = MaxBurst; | 286 | RequestedBurst = MaxBurst; |
189 | // TotalDripRequest = dripRate; // this will be overwritten when a child node registers | 287 | // TotalDripRequest = dripRate; // this will be overwritten when a child node registers |
190 | // MaxBurst = (Int64)((double)dripRate * m_quantumsPerBurst); | 288 | // MaxBurst = (Int64)((double)dripRate * m_quantumsPerBurst); |
191 | m_lastDrip = Util.EnvironmentTickCount() + 100000; | 289 | m_lastDrip = Util.EnvironmentTickCount() + 100000; |
290 | >>>>>>> avn/ubitvar | ||
192 | } | 291 | } |
193 | 292 | ||
194 | #endregion Constructor | ||
195 | |||
196 | /// <summary> | 293 | /// <summary> |
197 | /// Compute a modifier for the MaxBurst rate. This is 1.0, meaning | 294 | /// Compute a modifier for the MaxBurst rate. This is 1.0, meaning |
198 | /// no modification if the requested bandwidth is less than the | 295 | /// no modification if the requested bandwidth is less than the |
@@ -202,8 +299,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
202 | /// </summary> | 299 | /// </summary> |
203 | protected float DripRateModifier() | 300 | protected float DripRateModifier() |
204 | { | 301 | { |
302 | <<<<<<< HEAD | ||
303 | Int64 driprate = DripRate; | ||
304 | double modifier = driprate >= TotalDripRequest ? 1.0 : (double)driprate / (double)TotalDripRequest; | ||
305 | |||
306 | // if (DebugLevel > 0) | ||
307 | // m_log.DebugFormat( | ||
308 | // "[TOKEN BUCKET]: Returning drip modifier {0}/{1} = {2} from {3}", | ||
309 | // driprate, TotalDripRequest, modifier, Identifier); | ||
310 | |||
311 | return modifier; | ||
312 | ======= | ||
205 | float driprate = DripRate; | 313 | float driprate = DripRate; |
206 | return driprate >= TotalDripRequest ? 1.0f : driprate / TotalDripRequest; | 314 | return driprate >= TotalDripRequest ? 1.0f : driprate / TotalDripRequest; |
315 | >>>>>>> avn/ubitvar | ||
207 | } | 316 | } |
208 | 317 | ||
209 | /// <summary> | 318 | /// <summary> |
@@ -225,16 +334,30 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
225 | lock (m_children) | 334 | lock (m_children) |
226 | { | 335 | { |
227 | m_children[child] = request; | 336 | m_children[child] = request; |
228 | // m_totalDripRequest = m_children.Values.Sum(); | ||
229 | 337 | ||
338 | <<<<<<< HEAD | ||
339 | TotalDripRequest = 0; | ||
340 | foreach (KeyValuePair<TokenBucket, Int64> cref in m_children) | ||
341 | TotalDripRequest += cref.Value; | ||
342 | ======= | ||
230 | m_totalDripRequest = 0; | 343 | m_totalDripRequest = 0; |
231 | foreach (KeyValuePair<TokenBucket, float> cref in m_children) | 344 | foreach (KeyValuePair<TokenBucket, float> cref in m_children) |
232 | m_totalDripRequest += cref.Value; | 345 | m_totalDripRequest += cref.Value; |
346 | >>>>>>> avn/ubitvar | ||
233 | } | 347 | } |
234 | 348 | ||
235 | // Pass the new values up to the parent | 349 | // Pass the new values up to the parent |
236 | if (m_parent != null) | 350 | if (Parent != null) |
237 | m_parent.RegisterRequest(this,Math.Min(RequestedDripRate, TotalDripRequest)); | 351 | { |
352 | Int64 effectiveDripRate; | ||
353 | |||
354 | if (RequestedDripRate > 0) | ||
355 | effectiveDripRate = Math.Min(RequestedDripRate, TotalDripRequest); | ||
356 | else | ||
357 | effectiveDripRate = TotalDripRequest; | ||
358 | |||
359 | Parent.RegisterRequest(this, effectiveDripRate); | ||
360 | } | ||
238 | } | 361 | } |
239 | 362 | ||
240 | /// <summary> | 363 | /// <summary> |
@@ -246,17 +369,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
246 | lock (m_children) | 369 | lock (m_children) |
247 | { | 370 | { |
248 | m_children.Remove(child); | 371 | m_children.Remove(child); |
249 | // m_totalDripRequest = m_children.Values.Sum(); | ||
250 | 372 | ||
373 | <<<<<<< HEAD | ||
374 | TotalDripRequest = 0; | ||
375 | foreach (KeyValuePair<TokenBucket, Int64> cref in m_children) | ||
376 | TotalDripRequest += cref.Value; | ||
377 | ======= | ||
251 | m_totalDripRequest = 0; | 378 | m_totalDripRequest = 0; |
252 | foreach (KeyValuePair<TokenBucket, float> cref in m_children) | 379 | foreach (KeyValuePair<TokenBucket, float> cref in m_children) |
253 | m_totalDripRequest += cref.Value; | 380 | m_totalDripRequest += cref.Value; |
381 | >>>>>>> avn/ubitvar | ||
254 | } | 382 | } |
255 | |||
256 | 383 | ||
257 | // Pass the new values up to the parent | 384 | // Pass the new values up to the parent |
258 | if (m_parent != null) | 385 | if (Parent != null) |
259 | m_parent.RegisterRequest(this,Math.Min(RequestedDripRate, TotalDripRequest)); | 386 | Parent.RegisterRequest(this,Math.Min(RequestedDripRate, TotalDripRequest)); |
260 | } | 387 | } |
261 | 388 | ||
262 | /// <summary> | 389 | /// <summary> |
@@ -300,7 +427,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
300 | // with no drip rate... | 427 | // with no drip rate... |
301 | if (DripRate == 0) | 428 | if (DripRate == 0) |
302 | { | 429 | { |
303 | m_log.WarnFormat("[TOKENBUCKET] something odd is happening and drip rate is 0"); | 430 | m_log.WarnFormat("[TOKENBUCKET] something odd is happening and drip rate is 0 for {0}", Identifier); |
304 | return; | 431 | return; |
305 | } | 432 | } |
306 | 433 | ||
@@ -321,9 +448,22 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
321 | 448 | ||
322 | public class AdaptiveTokenBucket : TokenBucket | 449 | public class AdaptiveTokenBucket : TokenBucket |
323 | { | 450 | { |
324 | // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 451 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
452 | |||
453 | public bool AdaptiveEnabled { get; set; } | ||
325 | 454 | ||
326 | /// <summary> | 455 | /// <summary> |
456 | <<<<<<< HEAD | ||
457 | /// Target drip rate for this bucket. | ||
458 | /// </summary> | ||
459 | /// <remarks>Usually set by the client. If adaptive is enabled then throttles will increase until we reach this.</remarks> | ||
460 | public Int64 TargetDripRate | ||
461 | { | ||
462 | get { return m_targetDripRate; } | ||
463 | set | ||
464 | { | ||
465 | m_targetDripRate = Math.Max(value, m_minimumFlow); | ||
466 | ======= | ||
327 | /// The minimum rate for flow control. Minimum drip rate is one | 467 | /// The minimum rate for flow control. Minimum drip rate is one |
328 | /// packet per second. | 468 | /// packet per second. |
329 | /// </summary> | 469 | /// </summary> |
@@ -342,25 +482,62 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
342 | set | 482 | set |
343 | { | 483 | { |
344 | m_maxDripRate = (value == 0 ? m_totalDripRequest : Math.Max(value, m_minimumFlow)); | 484 | m_maxDripRate = (value == 0 ? m_totalDripRequest : Math.Max(value, m_minimumFlow)); |
485 | >>>>>>> avn/ubitvar | ||
345 | } | 486 | } |
346 | } | 487 | } |
347 | 488 | protected Int64 m_targetDripRate; | |
348 | private bool m_enabled = false; | 489 | |
349 | |||
350 | // <summary> | 490 | // <summary> |
351 | // | 491 | // Adjust drip rate in response to network conditions. |
352 | // </summary> | 492 | // </summary> |
353 | public virtual float AdjustedDripRate | 493 | public virtual float AdjustedDripRate |
354 | { | 494 | { |
355 | get { return m_dripRate; } | 495 | get { return m_dripRate; } |
496 | <<<<<<< HEAD | ||
497 | set | ||
498 | { | ||
499 | m_dripRate = OpenSim.Framework.Util.Clamp<Int64>(value, m_minimumFlow, TargetDripRate); | ||
500 | m_burstRate = (Int64)((double)m_dripRate * m_quantumsPerBurst); | ||
501 | |||
502 | if (Parent != null) | ||
503 | Parent.RegisterRequest(this, m_dripRate); | ||
504 | ======= | ||
356 | set { | 505 | set { |
357 | m_dripRate = OpenSim.Framework.Util.Clamp<float>(value,m_minimumFlow,MaxDripRate); | 506 | m_dripRate = OpenSim.Framework.Util.Clamp<float>(value,m_minimumFlow,MaxDripRate); |
358 | 507 | ||
359 | if (m_parent != null) | 508 | if (m_parent != null) |
360 | m_parent.RegisterRequest(this,m_dripRate); | 509 | m_parent.RegisterRequest(this,m_dripRate); |
510 | >>>>>>> avn/ubitvar | ||
361 | } | 511 | } |
362 | } | 512 | } |
513 | |||
514 | /// <summary> | ||
515 | /// The minimum rate for adaptive flow control. | ||
516 | /// </summary> | ||
517 | protected Int64 m_minimumFlow = 32000; | ||
363 | 518 | ||
519 | <<<<<<< HEAD | ||
520 | /// <summary> | ||
521 | /// Constructor for the AdaptiveTokenBucket class | ||
522 | /// <param name="identifier">Unique identifier for the client</param> | ||
523 | /// <param name="parent">Parent bucket in the hierarchy</param> | ||
524 | /// <param name="requestedDripRate"></param> | ||
525 | /// <param name="maxDripRate">The ceiling rate for adaptation</param> | ||
526 | /// <param name="minDripRate">The floor rate for adaptation</param> | ||
527 | /// </summary> | ||
528 | public AdaptiveTokenBucket(string identifier, TokenBucket parent, Int64 requestedDripRate, Int64 maxDripRate, Int64 minDripRate, bool enabled) | ||
529 | : base(identifier, parent, requestedDripRate, maxDripRate) | ||
530 | { | ||
531 | AdaptiveEnabled = enabled; | ||
532 | |||
533 | if (AdaptiveEnabled) | ||
534 | { | ||
535 | // m_log.DebugFormat("[TOKENBUCKET]: Adaptive throttle enabled"); | ||
536 | m_minimumFlow = minDripRate; | ||
537 | TargetDripRate = m_minimumFlow; | ||
538 | AdjustedDripRate = m_minimumFlow; | ||
539 | } | ||
540 | ======= | ||
364 | // <summary> | 541 | // <summary> |
365 | // | 542 | // |
366 | // </summary> | 543 | // </summary> |
@@ -375,25 +552,50 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
375 | AdjustedDripRate = m_maxDripRate * .5f; | 552 | AdjustedDripRate = m_maxDripRate * .5f; |
376 | else | 553 | else |
377 | AdjustedDripRate = m_maxDripRate; | 554 | AdjustedDripRate = m_maxDripRate; |
555 | >>>>>>> avn/ubitvar | ||
378 | } | 556 | } |
379 | 557 | ||
380 | // <summary> | 558 | /// <summary> |
381 | // | 559 | /// Reliable packets sent to the client for which we never received an ack adjust the drip rate down. |
382 | // </summary> | 560 | /// <param name="packets">Number of packets that expired without successful delivery</param> |
383 | public void ExpirePackets(Int32 count) | 561 | /// </summary> |
562 | public void ExpirePackets(Int32 packets) | ||
384 | { | 563 | { |
385 | // m_log.WarnFormat("[ADAPTIVEBUCKET] drop {0} by {1} expired packets",AdjustedDripRate,count); | 564 | if (AdaptiveEnabled) |
386 | if (m_enabled) | 565 | { |
387 | AdjustedDripRate = (Int64) (AdjustedDripRate / Math.Pow(2,count)); | 566 | if (DebugLevel > 0) |
567 | m_log.WarnFormat( | ||
568 | "[ADAPTIVEBUCKET] drop {0} by {1} expired packets for {2}", | ||
569 | AdjustedDripRate, packets, Identifier); | ||
570 | |||
571 | // AdjustedDripRate = (Int64) (AdjustedDripRate / Math.Pow(2,packets)); | ||
572 | |||
573 | // Compute the fallback solely on the rate allocated beyond the minimum, this | ||
574 | // should smooth out the fallback to the minimum rate | ||
575 | AdjustedDripRate = m_minimumFlow + (Int64) ((AdjustedDripRate - m_minimumFlow) / Math.Pow(2, packets)); | ||
576 | } | ||
388 | } | 577 | } |
389 | 578 | ||
390 | // <summary> | 579 | /// <summary> |
391 | // | 580 | /// Reliable packets acked by the client adjust the drip rate up. |
392 | // </summary> | 581 | /// <param name="packets">Number of packets successfully acknowledged</param> |
393 | public void AcknowledgePackets(Int32 count) | 582 | /// </summary> |
583 | public void AcknowledgePackets(Int32 packets) | ||
584 | { | ||
585 | if (AdaptiveEnabled) | ||
586 | AdjustedDripRate = AdjustedDripRate + packets * LLUDPServer.MTU; | ||
587 | } | ||
588 | |||
589 | /// <summary> | ||
590 | /// Adjust the minimum flow level for the adaptive throttle, this will drop adjusted | ||
591 | /// throttles back to the minimum levels | ||
592 | /// <param>minDripRate--the new minimum flow</param> | ||
593 | /// </summary> | ||
594 | public void ResetMinimumAdaptiveFlow(Int64 minDripRate) | ||
394 | { | 595 | { |
395 | if (m_enabled) | 596 | m_minimumFlow = minDripRate; |
396 | AdjustedDripRate = AdjustedDripRate + count; | 597 | TargetDripRate = m_minimumFlow; |
598 | AdjustedDripRate = m_minimumFlow; | ||
397 | } | 599 | } |
398 | } | 600 | } |
399 | } | 601 | } |
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/UnackedPacketCollection.cs b/OpenSim/Region/ClientStack/Linden/UDP/UnackedPacketCollection.cs index 9d6c09e..b546a99 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/UnackedPacketCollection.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/UnackedPacketCollection.cs | |||
@@ -31,6 +31,9 @@ using System.Net; | |||
31 | using System.Threading; | 31 | using System.Threading; |
32 | using OpenMetaverse; | 32 | using OpenMetaverse; |
33 | 33 | ||
34 | //using System.Reflection; | ||
35 | //using log4net; | ||
36 | |||
34 | namespace OpenSim.Region.ClientStack.LindenUDP | 37 | namespace OpenSim.Region.ClientStack.LindenUDP |
35 | { | 38 | { |
36 | /// <summary> | 39 | /// <summary> |
@@ -60,6 +63,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
60 | } | 63 | } |
61 | } | 64 | } |
62 | 65 | ||
66 | //private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | ||
67 | |||
63 | /// <summary>Holds the actual unacked packet data, sorted by sequence number</summary> | 68 | /// <summary>Holds the actual unacked packet data, sorted by sequence number</summary> |
64 | private Dictionary<uint, OutgoingPacket> m_packets = new Dictionary<uint, OutgoingPacket>(); | 69 | private Dictionary<uint, OutgoingPacket> m_packets = new Dictionary<uint, OutgoingPacket>(); |
65 | /// <summary>Holds packets that need to be added to the unacknowledged list</summary> | 70 | /// <summary>Holds packets that need to be added to the unacknowledged list</summary> |
@@ -164,8 +169,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
164 | } | 169 | } |
165 | } | 170 | } |
166 | 171 | ||
167 | //if (expiredPackets != null) | 172 | // if (expiredPackets != null) |
168 | // m_log.DebugFormat("[UNACKED PACKET COLLECTION]: Found {0} expired packets on timeout of {1}", expiredPackets.Count, timeoutMS); | 173 | // m_log.DebugFormat("[UNACKED PACKET COLLECTION]: Found {0} expired packets on timeout of {1}", expiredPackets.Count, timeoutMS); |
169 | 174 | ||
170 | return expiredPackets; | 175 | return expiredPackets; |
171 | } | 176 | } |
@@ -192,7 +197,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
192 | 197 | ||
193 | // As with other network applications, assume that an acknowledged packet is an | 198 | // As with other network applications, assume that an acknowledged packet is an |
194 | // indication that the network can handle a little more load, speed up the transmission | 199 | // indication that the network can handle a little more load, speed up the transmission |
195 | ackedPacket.Client.FlowThrottle.AcknowledgePackets(ackedPacket.Buffer.DataLength); | 200 | ackedPacket.Client.FlowThrottle.AcknowledgePackets(1); |
196 | 201 | ||
197 | // Update stats | 202 | // Update stats |
198 | Interlocked.Add(ref ackedPacket.Client.UnackedBytes, -ackedPacket.Buffer.DataLength); | 203 | Interlocked.Add(ref ackedPacket.Client.UnackedBytes, -ackedPacket.Buffer.DataLength); |
@@ -207,9 +212,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
207 | } | 212 | } |
208 | else | 213 | else |
209 | { | 214 | { |
210 | //m_log.WarnFormat("[UNACKED PACKET COLLECTION]: Could not find packet with sequence number {0} to ack", pendingAcknowledgement.SequenceNumber); | 215 | // m_log.WarnFormat("[UNACKED PACKET COLLECTION]: found null packet for sequence number {0} to ack", |
216 | // pendingAcknowledgement.SequenceNumber); | ||
211 | } | 217 | } |
212 | } | 218 | } |
219 | else | ||
220 | { | ||
221 | // m_log.WarnFormat("[UNACKED PACKET COLLECTION]: Could not find packet with sequence number {0} to ack", | ||
222 | // pendingAcknowledgement.SequenceNumber); | ||
223 | } | ||
213 | } | 224 | } |
214 | 225 | ||
215 | uint pendingRemove; | 226 | uint pendingRemove; |
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/Tests/TestLLUDPServer.cs b/OpenSim/Tests/Common/Mock/TestLLUDPServer.cs index 27b9e5b..26887c9 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/Tests/TestLLUDPServer.cs +++ b/OpenSim/Tests/Common/Mock/TestLLUDPServer.cs | |||
@@ -32,8 +32,9 @@ using System.Net.Sockets; | |||
32 | using Nini.Config; | 32 | using Nini.Config; |
33 | using OpenMetaverse.Packets; | 33 | using OpenMetaverse.Packets; |
34 | using OpenSim.Framework; | 34 | using OpenSim.Framework; |
35 | using OpenSim.Region.ClientStack.LindenUDP; | ||
35 | 36 | ||
36 | namespace OpenSim.Region.ClientStack.LindenUDP.Tests | 37 | namespace OpenSim.Tests.Common |
37 | { | 38 | { |
38 | /// <summary> | 39 | /// <summary> |
39 | /// This class enables regression testing of the LLUDPServer by allowing us to intercept outgoing data. | 40 | /// This class enables regression testing of the LLUDPServer by allowing us to intercept outgoing data. |
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/Tests/MockScene.cs b/OpenSim/Tools/pCampBot/Behaviours/PhysicsBehaviour2.cs index e2178e5..1ec2046 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/Tests/MockScene.cs +++ b/OpenSim/Tools/pCampBot/Behaviours/PhysicsBehaviour2.cs | |||
@@ -25,55 +25,62 @@ | |||
25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
26 | */ | 26 | */ |
27 | 27 | ||
28 | using System.Net; | ||
29 | using OpenMetaverse; | 28 | using OpenMetaverse; |
30 | using OpenSim.Framework; | 29 | using System; |
31 | using OpenSim.Region.Framework.Scenes; | 30 | using System.Collections.Generic; |
32 | using GridRegion = OpenSim.Services.Interfaces.GridRegion; | 31 | using System.Linq; |
32 | using System.Reflection; | ||
33 | using System.Threading; | ||
34 | using log4net; | ||
35 | using pCampBot.Interfaces; | ||
33 | 36 | ||
34 | namespace OpenSim.Region.ClientStack.LindenUDP.Tests | 37 | namespace pCampBot |
35 | { | 38 | { |
36 | /// <summary> | 39 | /// <summary> |
37 | /// Mock scene for unit tests | 40 | /// This behavior is for the systematic study of some performance improvements made |
41 | /// for OSCC'13. | ||
42 | /// Walk around, sending AgentUpdate packets all the time. | ||
38 | /// </summary> | 43 | /// </summary> |
39 | public class MockScene : SceneBase | 44 | public class PhysicsBehaviour2 : AbstractBehaviour |
40 | { | 45 | { |
41 | public int ObjectNameCallsReceived | 46 | // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
42 | { | 47 | |
43 | get { return m_objectNameCallsReceived; } | 48 | public PhysicsBehaviour2() |
44 | } | 49 | { |
45 | protected int m_objectNameCallsReceived; | 50 | AbbreviatedName = "ph2"; |
46 | 51 | Name = "Physics2"; | |
47 | public MockScene() : base(new RegionInfo(1000, 1000, null, null)) | ||
48 | { | ||
49 | m_regStatus = RegionStatus.Up; | ||
50 | } | 52 | } |
51 | 53 | ||
52 | public override void Update(int frames) {} | 54 | private const int TIME_WALKING = 5 * 10; // 5 seconds |
53 | public override void LoadWorldMap() {} | 55 | private int counter = 0; |
54 | 56 | ||
55 | public override ISceneAgent AddNewAgent(IClientAPI client, PresenceType type) | 57 | public override void Action() |
56 | { | 58 | { |
57 | client.OnObjectName += RecordObjectNameCall; | ||
58 | 59 | ||
59 | // FIXME | 60 | if (counter >= TIME_WALKING) |
60 | return null; | 61 | { |
61 | } | 62 | counter = 0; |
62 | 63 | ||
63 | public override bool CloseAgent(UUID agentID, bool force) { return true; } | 64 | Vector3 target = new Vector3(Bot.Random.Next(1, 254), Bot.Random.Next(1, 254), Bot.Client.Self.SimPosition.Z); |
65 | MyTurnToward(target); | ||
64 | 66 | ||
65 | public override bool CheckClient(UUID clientId, IPEndPoint endPoint) { return true; } | 67 | Bot.Client.Self.Movement.AtPos = true; |
66 | 68 | ||
67 | public override void OtherRegionUp(GridRegion otherRegion) { } | 69 | } |
70 | else | ||
71 | counter++; | ||
72 | // In any case, send an update | ||
73 | Bot.Client.Self.Movement.SendUpdate(); | ||
74 | } | ||
68 | 75 | ||
69 | public override bool TryGetScenePresence(UUID uuid, out ScenePresence sp) { sp = null; return false; } | 76 | private void MyTurnToward(Vector3 target) |
70 | |||
71 | /// <summary> | ||
72 | /// Doesn't really matter what the call is - we're using this to test that a packet has actually been received | ||
73 | /// </summary> | ||
74 | protected void RecordObjectNameCall(IClientAPI remoteClient, uint localID, string message) | ||
75 | { | 77 | { |
76 | m_objectNameCallsReceived++; | 78 | Quaternion between = Vector3.RotationBetween(Vector3.UnitX, Vector3.Normalize(target - Bot.Client.Self.SimPosition)); |
79 | Quaternion rot = between ; | ||
80 | |||
81 | Bot.Client.Self.Movement.BodyRotation = rot; | ||
82 | Bot.Client.Self.Movement.HeadRotation = rot; | ||
83 | Bot.Client.Self.Movement.Camera.LookAt(Bot.Client.Self.SimPosition, target); | ||
77 | } | 84 | } |
78 | } | 85 | } |
79 | } | 86 | } \ No newline at end of file |