aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ClientStack/Linden/UDP
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs546
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs139
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs424
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLUDPServerCommands.cs901
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs95
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs108
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/Tests/LLImageManagerTests.cs1
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/Tests/PacketHandlerTests.cs1
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/Tests/ThrottleTests.cs427
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/ThrottleRates.cs13
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/TokenBucket.cs286
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/UnackedPacketCollection.cs19
-rw-r--r--OpenSim/Tests/Common/Mock/TestLLUDPServer.cs (renamed from OpenSim/Region/ClientStack/Linden/UDP/Tests/TestLLUDPServer.cs)3
-rw-r--r--OpenSim/Tools/pCampBot/Behaviours/PhysicsBehaviour2.cs (renamed from OpenSim/Region/ClientStack/Linden/UDP/Tests/MockScene.cs)79
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;
34using System.Threading; 34using System.Threading;
35using System.Timers; 35using System.Timers;
36using System.Xml; 36using System.Xml;
37
37using log4net; 38using log4net;
38using OpenMetaverse; 39using OpenMetaverse;
39using OpenMetaverse.Packets; 40using OpenMetaverse.Packets;
40using OpenMetaverse.Messages.Linden; 41using OpenMetaverse.Messages.Linden;
41using OpenMetaverse.StructuredData; 42using OpenMetaverse.StructuredData;
43
42using OpenSim.Framework; 44using OpenSim.Framework;
43using OpenSim.Framework.Client; 45using OpenSim.Framework.Client;
44using OpenSim.Framework.Monitoring; 46using OpenSim.Framework.Monitoring;
@@ -48,7 +50,6 @@ using OpenSim.Services.Interfaces;
48using Timer = System.Timers.Timer; 50using Timer = System.Timers.Timer;
49using AssetLandmark = OpenSim.Framework.AssetLandmark; 51using AssetLandmark = OpenSim.Framework.AssetLandmark;
50using RegionFlags = OpenMetaverse.RegionFlags; 52using RegionFlags = OpenMetaverse.RegionFlags;
51using Nini.Config;
52 53
53using System.IO; 54using System.IO;
54using PermissionMask = OpenSim.Framework.PermissionMask; 55using 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;
34using System.Reflection; 34using System.Reflection;
35using System.Threading; 35using System.Threading;
36using log4net; 36using log4net;
37using NDesk.Options;
38using Nini.Config; 37using Nini.Config;
39using OpenMetaverse.Packets; 38using OpenMetaverse.Packets;
40using OpenSim.Framework; 39using 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
28using System;
29using System.Collections.Generic;
30using System.Text;
31using NDesk.Options;
32using OpenSim.Framework;
33using OpenSim.Framework.Console;
34using OpenSim.Region.Framework.Scenes;
35
36namespace 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;
36using OpenSim.Framework.Monitoring; 36using OpenSim.Framework.Monitoring;
37using OpenSim.Region.Framework.Scenes; 37using OpenSim.Region.Framework.Scenes;
38using OpenSim.Tests.Common; 38using OpenSim.Tests.Common;
39using OpenSim.Tests.Common.Mock;
40 39
41namespace OpenSim.Region.ClientStack.LindenUDP.Tests 40namespace 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;
39using OpenSim.Region.CoreModules.Agent.TextureSender; 39using OpenSim.Region.CoreModules.Agent.TextureSender;
40using OpenSim.Region.Framework.Scenes; 40using OpenSim.Region.Framework.Scenes;
41using OpenSim.Tests.Common; 41using OpenSim.Tests.Common;
42using OpenSim.Tests.Common.Mock;
43 42
44namespace OpenSim.Region.ClientStack.LindenUDP.Tests 43namespace 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;
30using OpenMetaverse; 30using OpenMetaverse;
31using OpenMetaverse.Packets; 31using OpenMetaverse.Packets;
32using OpenSim.Framework; 32using OpenSim.Framework;
33using OpenSim.Tests.Common.Mock;
34using OpenSim.Tests.Common; 33using OpenSim.Tests.Common;
35 34
36namespace OpenSim.Region.ClientStack.LindenUDP.Tests 35namespace 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
28using System;
29using Nini.Config;
30using NUnit.Framework;
31using OpenMetaverse.Packets;
32using OpenSim.Framework;
33using OpenSim.Region.Framework.Scenes;
34using OpenSim.Tests.Common;
35
36namespace 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;
31using System.Threading; 31using System.Threading;
32using OpenMetaverse; 32using OpenMetaverse;
33 33
34//using System.Reflection;
35//using log4net;
36
34namespace OpenSim.Region.ClientStack.LindenUDP 37namespace 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;
32using Nini.Config; 32using Nini.Config;
33using OpenMetaverse.Packets; 33using OpenMetaverse.Packets;
34using OpenSim.Framework; 34using OpenSim.Framework;
35using OpenSim.Region.ClientStack.LindenUDP;
35 36
36namespace OpenSim.Region.ClientStack.LindenUDP.Tests 37namespace 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
28using System.Net;
29using OpenMetaverse; 28using OpenMetaverse;
30using OpenSim.Framework; 29using System;
31using OpenSim.Region.Framework.Scenes; 30using System.Collections.Generic;
32using GridRegion = OpenSim.Services.Interfaces.GridRegion; 31using System.Linq;
32using System.Reflection;
33using System.Threading;
34using log4net;
35using pCampBot.Interfaces;
33 36
34namespace OpenSim.Region.ClientStack.LindenUDP.Tests 37namespace 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