aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ClientStack
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/ClientStack')
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs594
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLFileTransfer.cs5
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs19
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs190
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/OpenSimUDPBase.cs22
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/OutgoingPacket.cs4
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/ThrottleRates.cs21
7 files changed, 453 insertions, 402 deletions
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
index f6a7a0c..49b9378 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
@@ -37,6 +37,7 @@ using System.Xml;
37using log4net; 37using log4net;
38using OpenMetaverse; 38using OpenMetaverse;
39using OpenMetaverse.Packets; 39using OpenMetaverse.Packets;
40using OpenMetaverse.StructuredData;
40using OpenSim.Framework; 41using OpenSim.Framework;
41using OpenSim.Framework.Client; 42using OpenSim.Framework.Client;
42using OpenSim.Framework.Communications.Cache; 43using OpenSim.Framework.Communications.Cache;
@@ -219,6 +220,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
219 public event FriendActionDelegate OnApproveFriendRequest; 220 public event FriendActionDelegate OnApproveFriendRequest;
220 public event FriendActionDelegate OnDenyFriendRequest; 221 public event FriendActionDelegate OnDenyFriendRequest;
221 public event FriendshipTermination OnTerminateFriendship; 222 public event FriendshipTermination OnTerminateFriendship;
223 public event GrantUserFriendRights OnGrantUserRights;
222 public event MoneyTransferRequest OnMoneyTransferRequest; 224 public event MoneyTransferRequest OnMoneyTransferRequest;
223 public event EconomyDataRequest OnEconomyDataRequest; 225 public event EconomyDataRequest OnEconomyDataRequest;
224 public event MoneyBalanceRequest OnMoneyBalanceRequest; 226 public event MoneyBalanceRequest OnMoneyBalanceRequest;
@@ -314,14 +316,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
314 private readonly LLUDPClient m_udpClient; 316 private readonly LLUDPClient m_udpClient;
315 private readonly UUID m_sessionId; 317 private readonly UUID m_sessionId;
316 private readonly UUID m_secureSessionId; 318 private readonly UUID m_secureSessionId;
317 private readonly UUID m_agentId; 319 protected readonly UUID m_agentId;
318 private readonly uint m_circuitCode; 320 private readonly uint m_circuitCode;
319 private readonly byte[] m_channelVersion = Utils.EmptyBytes; 321 private readonly byte[] m_channelVersion = Utils.EmptyBytes;
320 private readonly Dictionary<string, UUID> m_defaultAnimations = new Dictionary<string, UUID>(); 322 private readonly Dictionary<string, UUID> m_defaultAnimations = new Dictionary<string, UUID>();
321 private readonly IGroupsModule m_GroupsModule; 323 private readonly IGroupsModule m_GroupsModule;
322 324
323 private int m_cachedTextureSerial; 325 private int m_cachedTextureSerial;
324 private PriorityQueue<double, ImprovedTerseObjectUpdatePacket.ObjectDataBlock> m_avatarTerseUpdates; 326 protected PriorityQueue<double, ImprovedTerseObjectUpdatePacket.ObjectDataBlock> m_avatarTerseUpdates;
325 private PriorityQueue<double, ImprovedTerseObjectUpdatePacket.ObjectDataBlock> m_primTerseUpdates; 327 private PriorityQueue<double, ImprovedTerseObjectUpdatePacket.ObjectDataBlock> m_primTerseUpdates;
326 private PriorityQueue<double, ObjectUpdatePacket.ObjectDataBlock> m_primFullUpdates; 328 private PriorityQueue<double, ObjectUpdatePacket.ObjectDataBlock> m_primFullUpdates;
327 private int m_moneyBalance; 329 private int m_moneyBalance;
@@ -783,6 +785,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
783 public virtual void SendLayerData(float[] map) 785 public virtual void SendLayerData(float[] map)
784 { 786 {
785 Util.FireAndForget(DoSendLayerData, map); 787 Util.FireAndForget(DoSendLayerData, map);
788
789 // Send it sync, and async. It's not that much data
790 // and it improves user experience just so much!
791 DoSendLayerData(map);
786 } 792 }
787 793
788 /// <summary> 794 /// <summary>
@@ -795,16 +801,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
795 801
796 try 802 try
797 { 803 {
798 //for (int y = 0; y < 16; y++) 804 for (int y = 0; y < 16; y++)
799 //{ 805 {
800 // for (int x = 0; x < 16; x++) 806 for (int x = 0; x < 16; x+=4)
801 // { 807 {
802 // SendLayerData(x, y, map); 808 SendLayerPacket(x, y, map);
803 // } 809 }
804 //} 810 }
805
806 // Send LayerData in a spiral pattern. Fun!
807 SendLayerTopRight(map, 0, 0, 15, 15);
808 } 811 }
809 catch (Exception e) 812 catch (Exception e)
810 { 813 {
@@ -812,51 +815,35 @@ namespace OpenSim.Region.ClientStack.LindenUDP
812 } 815 }
813 } 816 }
814 817
815 private void SendLayerTopRight(float[] map, int x1, int y1, int x2, int y2)
816 {
817 // Row
818 for (int i = x1; i <= x2; i++)
819 SendLayerData(i, y1, map);
820
821 // Column
822 for (int j = y1 + 1; j <= y2; j++)
823 SendLayerData(x2, j, map);
824
825 if (x2 - x1 > 0)
826 SendLayerBottomLeft(map, x1, y1 + 1, x2 - 1, y2);
827 }
828
829 void SendLayerBottomLeft(float[] map, int x1, int y1, int x2, int y2)
830 {
831 // Row in reverse
832 for (int i = x2; i >= x1; i--)
833 SendLayerData(i, y2, map);
834
835 // Column in reverse
836 for (int j = y2 - 1; j >= y1; j--)
837 SendLayerData(x1, j, map);
838
839 if (x2 - x1 > 0)
840 SendLayerTopRight(map, x1 + 1, y1, x2, y2 - 1);
841 }
842
843 /// <summary> 818 /// <summary>
844 /// Sends a set of four patches (x, x+1, ..., x+3) to the client 819 /// Sends a set of four patches (x, x+1, ..., x+3) to the client
845 /// </summary> 820 /// </summary>
846 /// <param name="map">heightmap</param> 821 /// <param name="map">heightmap</param>
847 /// <param name="px">X coordinate for patches 0..12</param> 822 /// <param name="px">X coordinate for patches 0..12</param>
848 /// <param name="py">Y coordinate for patches 0..15</param> 823 /// <param name="py">Y coordinate for patches 0..15</param>
849 // private void SendLayerPacket(float[] map, int y, int x) 824 private void SendLayerPacket(int x, int y, float[] map)
850 // { 825 {
851 // int[] patches = new int[4]; 826 int[] patches = new int[4];
852 // patches[0] = x + 0 + y * 16; 827 patches[0] = x + 0 + y * 16;
853 // patches[1] = x + 1 + y * 16; 828 patches[1] = x + 1 + y * 16;
854 // patches[2] = x + 2 + y * 16; 829 patches[2] = x + 2 + y * 16;
855 // patches[3] = x + 3 + y * 16; 830 patches[3] = x + 3 + y * 16;
856 831
857 // Packet layerpack = LLClientView.TerrainManager.CreateLandPacket(map, patches); 832 float[] heightmap = (map.Length == 65536) ?
858 // OutPacket(layerpack, ThrottleOutPacketType.Land); 833 map :
859 // } 834 LLHeightFieldMoronize(map);
835
836 try
837 {
838 Packet layerpack = TerrainCompressor.CreateLandPacket(heightmap, patches);
839 OutPacket(layerpack, ThrottleOutPacketType.Land);
840 }
841 catch
842 {
843 for (int px = x ; px < x + 4 ; px++)
844 SendLayerData(px, y, map);
845 }
846 }
860 847
861 /// <summary> 848 /// <summary>
862 /// Sends a specified patch to a client 849 /// Sends a specified patch to a client
@@ -1250,7 +1237,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1250 /// <param name="fetchFolders">Do we need to send folder information?</param> 1237 /// <param name="fetchFolders">Do we need to send folder information?</param>
1251 /// <param name="fetchItems">Do we need to send item information?</param> 1238 /// <param name="fetchItems">Do we need to send item information?</param>
1252 public void SendInventoryFolderDetails(UUID ownerID, UUID folderID, List<InventoryItemBase> items, 1239 public void SendInventoryFolderDetails(UUID ownerID, UUID folderID, List<InventoryItemBase> items,
1253 List<InventoryFolderBase> folders, 1240 List<InventoryFolderBase> folders, int version,
1254 bool fetchFolders, bool fetchItems) 1241 bool fetchFolders, bool fetchItems)
1255 { 1242 {
1256 // An inventory descendents packet consists of a single agent section and an inventory details 1243 // An inventory descendents packet consists of a single agent section and an inventory details
@@ -1263,174 +1250,107 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1263 // 1250 //
1264 // for one example of this kind of thing. In fact, the Linden servers appear to only send about 1251 // for one example of this kind of thing. In fact, the Linden servers appear to only send about
1265 // 6 to 7 items at a time, so let's stick with 6 1252 // 6 to 7 items at a time, so let's stick with 6
1266 int MAX_ITEMS_PER_PACKET = 6; 1253 int MAX_ITEMS_PER_PACKET = 5;
1267 1254 int MAX_FOLDERS_PER_PACKET = 6;
1268 //Ckrinke This variable is not used, so comment out to remove the warning from the compiler (3-21-08)
1269 //Ckrinke uint FULL_MASK_PERMISSIONS = 2147483647;
1270 1255
1256 int totalItems = fetchItems ? items.Count : 0;
1257 int totalFolders = fetchFolders ? folders.Count : 0;
1271 int itemsSent = 0; 1258 int itemsSent = 0;
1272 if (fetchItems) 1259 int foldersSent = 0;
1273 { 1260 int foldersToSend = 0;
1274 InventoryDescendentsPacket descend = CreateInventoryDescendentsPacket(ownerID, folderID); 1261 int itemsToSend = 0;
1275
1276 if (items.Count < MAX_ITEMS_PER_PACKET)
1277 {
1278 descend.ItemData = new InventoryDescendentsPacket.ItemDataBlock[items.Count];
1279 }
1280 else
1281 {
1282 descend.ItemData = new InventoryDescendentsPacket.ItemDataBlock[MAX_ITEMS_PER_PACKET];
1283 }
1284 1262
1285 // Descendents must contain the *total* number of descendents (plus folders, whether we 1263 InventoryDescendentsPacket currentPacket = null;
1286 // fetch them or not), not the number of entries we send in this packet. For consistency,
1287 // I'll use it for folder-requests, too, although I wasn't able to get one with
1288 // FetchFolders = true.
1289 // TODO this should be checked with FetchFolders = true
1290 descend.AgentData.Descendents = items.Count + folders.Count;
1291 1264
1292 int count = 0; 1265 // Handle empty folders
1293 int i = 0; 1266 //
1294 foreach (InventoryItemBase item in items) 1267 if (totalItems == 0 && totalFolders == 0)
1268 currentPacket = CreateInventoryDescendentsPacket(ownerID, folderID, version, items.Count + folders.Count, 0, 0);
1269
1270 // To preserve SL compatibility, we will NOT combine folders and items in one packet
1271 //
1272 while(itemsSent < totalItems || foldersSent < totalFolders)
1273 {
1274 if (currentPacket == null) // Start a new packet
1295 { 1275 {
1296 descend.ItemData[i] = new InventoryDescendentsPacket.ItemDataBlock(); 1276 foldersToSend = totalFolders - foldersSent;
1297 descend.ItemData[i].ItemID = item.ID; 1277 if (foldersToSend > MAX_FOLDERS_PER_PACKET)
1298 descend.ItemData[i].AssetID = item.AssetID; 1278 foldersToSend = MAX_FOLDERS_PER_PACKET;
1299 descend.ItemData[i].CreatorID = item.CreatorIdAsUuid; 1279
1300 descend.ItemData[i].BaseMask = item.BasePermissions; 1280 if (foldersToSend == 0)
1301 descend.ItemData[i].Description = Util.StringToBytes256(item.Description); 1281 {
1302 descend.ItemData[i].EveryoneMask = item.EveryOnePermissions; 1282 itemsToSend = totalItems - itemsSent;
1303 descend.ItemData[i].OwnerMask = item.CurrentPermissions; 1283 if (itemsToSend > MAX_ITEMS_PER_PACKET)
1304 descend.ItemData[i].FolderID = item.Folder; 1284 itemsToSend = MAX_ITEMS_PER_PACKET;
1305 descend.ItemData[i].InvType = (sbyte)item.InvType;
1306 descend.ItemData[i].Name = Util.StringToBytes256(item.Name);
1307 descend.ItemData[i].NextOwnerMask = item.NextPermissions;
1308 descend.ItemData[i].OwnerID = item.Owner;
1309 descend.ItemData[i].Type = (sbyte)item.AssetType;
1310
1311 descend.ItemData[i].GroupID = item.GroupID;
1312 descend.ItemData[i].GroupOwned = item.GroupOwned;
1313 descend.ItemData[i].GroupMask = item.GroupPermissions;
1314 descend.ItemData[i].CreationDate = item.CreationDate;
1315 descend.ItemData[i].SalePrice = item.SalePrice;
1316 descend.ItemData[i].SaleType = item.SaleType;
1317 descend.ItemData[i].Flags = item.Flags;
1318
1319 descend.ItemData[i].CRC =
1320 Helpers.InventoryCRC(descend.ItemData[i].CreationDate, descend.ItemData[i].SaleType,
1321 descend.ItemData[i].InvType, descend.ItemData[i].Type,
1322 descend.ItemData[i].AssetID, descend.ItemData[i].GroupID,
1323 descend.ItemData[i].SalePrice,
1324 descend.ItemData[i].OwnerID, descend.ItemData[i].CreatorID,
1325 descend.ItemData[i].ItemID, descend.ItemData[i].FolderID,
1326 descend.ItemData[i].EveryoneMask,
1327 descend.ItemData[i].Flags, descend.ItemData[i].OwnerMask,
1328 descend.ItemData[i].GroupMask, item.CurrentPermissions);
1329
1330 i++;
1331 count++;
1332 itemsSent++;
1333 if (i == MAX_ITEMS_PER_PACKET)
1334 {
1335 descend.Header.Zerocoded = true;
1336 AddNullFolderBlockToDecendentsPacket(ref descend);
1337 OutPacket(descend, ThrottleOutPacketType.Asset);
1338
1339 if ((items.Count - count) > 0)
1340 {
1341 descend = CreateInventoryDescendentsPacket(ownerID, folderID);
1342 if ((items.Count - count) < MAX_ITEMS_PER_PACKET)
1343 {
1344 descend.ItemData = new InventoryDescendentsPacket.ItemDataBlock[items.Count - count];
1345 }
1346 else
1347 {
1348 descend.ItemData = new InventoryDescendentsPacket.ItemDataBlock[MAX_ITEMS_PER_PACKET];
1349 }
1350 descend.AgentData.Descendents = items.Count + folders.Count;
1351 i = 0;
1352 }
1353 } 1285 }
1354 }
1355 1286
1356 if (0 < i && i < MAX_ITEMS_PER_PACKET) 1287 currentPacket = CreateInventoryDescendentsPacket(ownerID, folderID, version, items.Count + folders.Count, foldersToSend, itemsToSend);
1357 {
1358 AddNullFolderBlockToDecendentsPacket(ref descend);
1359 OutPacket(descend, ThrottleOutPacketType.Asset);
1360 } 1288 }
1361 }
1362 1289
1363 //send subfolders 1290 if (foldersToSend-- > 0)
1364 if (fetchFolders) 1291 currentPacket.FolderData[foldersSent % MAX_FOLDERS_PER_PACKET] = CreateFolderDataBlock(folders[foldersSent++]);
1365 { 1292 else if(itemsToSend-- > 0)
1366 InventoryDescendentsPacket descend = CreateInventoryDescendentsPacket(ownerID, folderID); 1293 currentPacket.ItemData[itemsSent % MAX_ITEMS_PER_PACKET] = CreateItemDataBlock(items[itemsSent++]);
1367
1368 if (folders.Count < MAX_ITEMS_PER_PACKET)
1369 {
1370 descend.FolderData = new InventoryDescendentsPacket.FolderDataBlock[folders.Count];
1371 }
1372 else 1294 else
1373 { 1295 {
1374 descend.FolderData = new InventoryDescendentsPacket.FolderDataBlock[MAX_ITEMS_PER_PACKET]; 1296 OutPacket(currentPacket, ThrottleOutPacketType.Asset, false);
1297 currentPacket = null;
1375 } 1298 }
1376 1299
1377 // Not sure if this scenario ever actually occurs, but nonetheless we include the items 1300 }
1378 // count even if we're not sending item data for the same reasons as above.
1379 descend.AgentData.Descendents = items.Count + folders.Count;
1380 1301
1381 int i = 0; 1302 if (currentPacket != null)
1382 int count = 0; 1303 OutPacket(currentPacket, ThrottleOutPacketType.Asset, false);
1383 foreach (InventoryFolderBase folder in folders) 1304 }
1384 {
1385 descend.FolderData[i] = new InventoryDescendentsPacket.FolderDataBlock();
1386 descend.FolderData[i].FolderID = folder.ID;
1387 descend.FolderData[i].Name = Util.StringToBytes256(folder.Name);
1388 descend.FolderData[i].ParentID = folder.ParentID;
1389 descend.FolderData[i].Type = (sbyte)folder.Type;
1390 1305
1391 i++; 1306 private InventoryDescendentsPacket.FolderDataBlock CreateFolderDataBlock(InventoryFolderBase folder)
1392 count++; 1307 {
1393 itemsSent++; 1308 InventoryDescendentsPacket.FolderDataBlock newBlock = new InventoryDescendentsPacket.FolderDataBlock();
1394 if (i == MAX_ITEMS_PER_PACKET) 1309 newBlock.FolderID = folder.ID;
1395 { 1310 newBlock.Name = Util.StringToBytes256(folder.Name);
1396 AddNullItemBlockToDescendentsPacket(ref descend); 1311 newBlock.ParentID = folder.ParentID;
1397 OutPacket(descend, ThrottleOutPacketType.Asset); 1312 newBlock.Type = (sbyte)folder.Type;
1398 1313
1399 if ((folders.Count - count) > 0) 1314 return newBlock;
1400 { 1315 }
1401 descend = CreateInventoryDescendentsPacket(ownerID, folderID);
1402 if ((folders.Count - count) < MAX_ITEMS_PER_PACKET)
1403 {
1404 descend.FolderData =
1405 new InventoryDescendentsPacket.FolderDataBlock[folders.Count - count];
1406 }
1407 else
1408 {
1409 descend.FolderData =
1410 new InventoryDescendentsPacket.FolderDataBlock[MAX_ITEMS_PER_PACKET];
1411 }
1412 descend.AgentData.Descendents = items.Count + folders.Count;
1413 i = 0;
1414 }
1415 }
1416 }
1417 1316
1418 if (0 < i && i < MAX_ITEMS_PER_PACKET) 1317 private InventoryDescendentsPacket.ItemDataBlock CreateItemDataBlock(InventoryItemBase item)
1419 { 1318 {
1420 AddNullItemBlockToDescendentsPacket(ref descend); 1319 InventoryDescendentsPacket.ItemDataBlock newBlock = new InventoryDescendentsPacket.ItemDataBlock();
1421 OutPacket(descend, ThrottleOutPacketType.Asset); 1320 newBlock.ItemID = item.ID;
1422 } 1321 newBlock.AssetID = item.AssetID;
1423 } 1322 newBlock.CreatorID = item.CreatorIdAsUuid;
1323 newBlock.BaseMask = item.BasePermissions;
1324 newBlock.Description = Util.StringToBytes256(item.Description);
1325 newBlock.EveryoneMask = item.EveryOnePermissions;
1326 newBlock.OwnerMask = item.CurrentPermissions;
1327 newBlock.FolderID = item.Folder;
1328 newBlock.InvType = (sbyte)item.InvType;
1329 newBlock.Name = Util.StringToBytes256(item.Name);
1330 newBlock.NextOwnerMask = item.NextPermissions;
1331 newBlock.OwnerID = item.Owner;
1332 newBlock.Type = (sbyte)item.AssetType;
1424 1333
1425 if (itemsSent == 0) 1334 newBlock.GroupID = item.GroupID;
1426 { 1335 newBlock.GroupOwned = item.GroupOwned;
1427 // no items found. 1336 newBlock.GroupMask = item.GroupPermissions;
1428 InventoryDescendentsPacket descend = CreateInventoryDescendentsPacket(ownerID, folderID); 1337 newBlock.CreationDate = item.CreationDate;
1429 descend.AgentData.Descendents = 0; 1338 newBlock.SalePrice = item.SalePrice;
1430 AddNullItemBlockToDescendentsPacket(ref descend); 1339 newBlock.SaleType = item.SaleType;
1431 AddNullFolderBlockToDecendentsPacket(ref descend); 1340 newBlock.Flags = item.Flags;
1432 OutPacket(descend, ThrottleOutPacketType.Asset); 1341
1433 } 1342 newBlock.CRC =
1343 Helpers.InventoryCRC(newBlock.CreationDate, newBlock.SaleType,
1344 newBlock.InvType, newBlock.Type,
1345 newBlock.AssetID, newBlock.GroupID,
1346 newBlock.SalePrice,
1347 newBlock.OwnerID, newBlock.CreatorID,
1348 newBlock.ItemID, newBlock.FolderID,
1349 newBlock.EveryoneMask,
1350 newBlock.Flags, newBlock.OwnerMask,
1351 newBlock.GroupMask, newBlock.NextOwnerMask);
1352
1353 return newBlock;
1434 } 1354 }
1435 1355
1436 private void AddNullFolderBlockToDecendentsPacket(ref InventoryDescendentsPacket packet) 1356 private void AddNullFolderBlockToDecendentsPacket(ref InventoryDescendentsPacket packet)
@@ -1472,14 +1392,25 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1472 // No need to add CRC 1392 // No need to add CRC
1473 } 1393 }
1474 1394
1475 private InventoryDescendentsPacket CreateInventoryDescendentsPacket(UUID ownerID, UUID folderID) 1395 private InventoryDescendentsPacket CreateInventoryDescendentsPacket(UUID ownerID, UUID folderID, int version, int descendents, int folders, int items)
1476 { 1396 {
1477 InventoryDescendentsPacket descend = (InventoryDescendentsPacket)PacketPool.Instance.GetPacket(PacketType.InventoryDescendents); 1397 InventoryDescendentsPacket descend = (InventoryDescendentsPacket)PacketPool.Instance.GetPacket(PacketType.InventoryDescendents);
1478 descend.Header.Zerocoded = true; 1398 descend.Header.Zerocoded = true;
1479 descend.AgentData.AgentID = AgentId; 1399 descend.AgentData.AgentID = AgentId;
1480 descend.AgentData.OwnerID = ownerID; 1400 descend.AgentData.OwnerID = ownerID;
1481 descend.AgentData.FolderID = folderID; 1401 descend.AgentData.FolderID = folderID;
1482 descend.AgentData.Version = 1; 1402 descend.AgentData.Version = version;
1403 descend.AgentData.Descendents = descendents;
1404
1405 if (folders > 0)
1406 descend.FolderData = new InventoryDescendentsPacket.FolderDataBlock[folders];
1407 else
1408 AddNullFolderBlockToDecendentsPacket(ref descend);
1409
1410 if (items > 0)
1411 descend.ItemData = new InventoryDescendentsPacket.ItemDataBlock[items];
1412 else
1413 AddNullItemBlockToDescendentsPacket(ref descend);
1483 1414
1484 return descend; 1415 return descend;
1485 } 1416 }
@@ -1856,7 +1787,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1856 economyData.Info.TeleportMinPrice = TeleportMinPrice; 1787 economyData.Info.TeleportMinPrice = TeleportMinPrice;
1857 economyData.Info.TeleportPriceExponent = TeleportPriceExponent; 1788 economyData.Info.TeleportPriceExponent = TeleportPriceExponent;
1858 economyData.Header.Reliable = true; 1789 economyData.Header.Reliable = true;
1859 OutPacket(economyData, ThrottleOutPacketType.Unknown); 1790 OutPacket(economyData, ThrottleOutPacketType.Task);
1860 } 1791 }
1861 1792
1862 public void SendAvatarPickerReply(AvatarPickerReplyAgentDataArgs AgentData, List<AvatarPickerReplyDataArgs> Data) 1793 public void SendAvatarPickerReply(AvatarPickerReplyAgentDataArgs AgentData, List<AvatarPickerReplyDataArgs> Data)
@@ -2786,30 +2717,37 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2786 2717
2787 public void SendAvatarGroupsReply(UUID avatarID, GroupMembershipData[] data) 2718 public void SendAvatarGroupsReply(UUID avatarID, GroupMembershipData[] data)
2788 { 2719 {
2789 AvatarGroupsReplyPacket p = (AvatarGroupsReplyPacket)PacketPool.Instance.GetPacket(PacketType.AvatarGroupsReply); 2720 OSDMap llsd = new OSDMap(3);
2790 2721 OSDArray AgentData = new OSDArray(1);
2791 p.AgentData = new AvatarGroupsReplyPacket.AgentDataBlock(); 2722 OSDMap AgentDataMap = new OSDMap(1);
2792 p.AgentData.AgentID = AgentId; 2723 AgentDataMap.Add("AgentID", OSD.FromUUID(this.AgentId));
2793 p.AgentData.AvatarID = avatarID; 2724 AgentDataMap.Add("AvatarID", OSD.FromUUID(avatarID));
2794 2725 AgentData.Add(AgentDataMap);
2795 p.GroupData = new AvatarGroupsReplyPacket.GroupDataBlock[data.Length]; 2726 llsd.Add("AgentData", AgentData);
2796 int i = 0; 2727 OSDArray GroupData = new OSDArray(data.Length);
2797 foreach (GroupMembershipData m in data) 2728 OSDArray NewGroupData = new OSDArray(data.Length);
2798 { 2729 foreach (GroupMembershipData m in data)
2799 p.GroupData[i] = new AvatarGroupsReplyPacket.GroupDataBlock(); 2730 {
2800 p.GroupData[i].GroupPowers = m.GroupPowers; 2731 OSDMap GroupDataMap = new OSDMap(6);
2801 p.GroupData[i].AcceptNotices = m.AcceptNotices; 2732 OSDMap NewGroupDataMap = new OSDMap(1);
2802 p.GroupData[i].GroupTitle = Utils.StringToBytes(m.GroupTitle); 2733 GroupDataMap.Add("GroupPowers", OSD.FromBinary(m.GroupPowers));
2803 p.GroupData[i].GroupID = m.GroupID; 2734 GroupDataMap.Add("AcceptNotices", OSD.FromBoolean(m.AcceptNotices));
2804 p.GroupData[i].GroupName = Utils.StringToBytes(m.GroupName); 2735 GroupDataMap.Add("GroupTitle", OSD.FromString(m.GroupTitle));
2805 p.GroupData[i].GroupInsigniaID = m.GroupPicture; 2736 GroupDataMap.Add("GroupID", OSD.FromUUID(m.GroupID));
2806 i++; 2737 GroupDataMap.Add("GroupName", OSD.FromString(m.GroupName));
2807 } 2738 GroupDataMap.Add("GroupInsigniaID", OSD.FromUUID(m.GroupPicture));
2808 2739 NewGroupDataMap.Add("ListInProfile", OSD.FromBoolean(m.ListInProfile));
2809 p.NewGroupData = new AvatarGroupsReplyPacket.NewGroupDataBlock(); 2740 GroupData.Add(GroupDataMap);
2810 p.NewGroupData.ListInProfile = true; 2741 NewGroupData.Add(NewGroupDataMap);
2811 2742 }
2812 OutPacket(p, ThrottleOutPacketType.Task); 2743 llsd.Add("GroupData", GroupData);
2744 llsd.Add("NewGroupData", NewGroupData);
2745
2746 IEventQueue eq = this.Scene.RequestModuleInterface<IEventQueue>();
2747 if (eq != null)
2748 {
2749 eq.Enqueue(BuildEvent("AvatarGroupsReply", llsd), this.AgentId);
2750 }
2813 } 2751 }
2814 2752
2815 public void SendJoinGroupReply(UUID groupID, bool success) 2753 public void SendJoinGroupReply(UUID groupID, bool success)
@@ -3168,107 +3106,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3168 3106
3169 #endregion 3107 #endregion
3170 3108
3171 #region Prim/Avatar Updates
3172
3173 /*void SendObjectUpdate(SceneObjectPart obj, PrimFlags creatorFlags, PrimUpdateFlags updateFlags)
3174 {
3175 bool canUseCompressed, canUseImproved;
3176 UpdateFlagsToPacketType(creatorFlags, updateFlags, out canUseCompressed, out canUseImproved);
3177
3178 if (!canUseImproved && !canUseCompressed)
3179 SendFullObjectUpdate(obj, creatorFlags, updateFlags);
3180 else if (!canUseImproved)
3181 SendObjectUpdateCompressed(obj, creatorFlags, updateFlags);
3182 else
3183 SendImprovedTerseObjectUpdate(obj, creatorFlags, updateFlags);
3184 }
3185
3186 void SendFullObjectUpdate(SceneObjectPart obj, PrimFlags creatorFlags, PrimUpdateFlags updateFlags)
3187 {
3188 IClientAPI owner;
3189 if (m_scene.ClientManager.TryGetValue(obj.OwnerID, out owner) && owner is LLClientView)
3190 {
3191 LLClientView llOwner = (LLClientView)owner;
3192
3193 // Send an update out to the owner
3194 ObjectUpdatePacket updateToOwner = new ObjectUpdatePacket();
3195 updateToOwner.RegionData.RegionHandle = obj.RegionHandle;
3196 //updateToOwner.RegionData.TimeDilation = (ushort)(timeDilation * (float)UInt16.MaxValue);
3197 updateToOwner.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[1];
3198 updateToOwner.ObjectData[0] = BuildUpdateBlock(obj, obj.Flags | creatorFlags | PrimFlags.ObjectYouOwner, 0);
3199
3200 m_udpServer.SendPacket(llOwner.UDPClient, updateToOwner, ThrottleOutPacketType.State, true);
3201 }
3202
3203 // Send an update out to everyone else
3204 ObjectUpdatePacket updateToOthers = new ObjectUpdatePacket();
3205 updateToOthers.RegionData.RegionHandle = obj.RegionHandle;
3206 //updateToOthers.RegionData.TimeDilation = (ushort)(timeDilation * (float)UInt16.MaxValue);
3207 updateToOthers.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[1];
3208 updateToOthers.ObjectData[0] = BuildUpdateBlock(obj, obj.Flags, 0);
3209
3210 m_scene.ClientManager.ForEach(
3211 delegate(IClientAPI client)
3212 {
3213 if (client.AgentId != obj.OwnerID && client is LLClientView)
3214 {
3215 LLClientView llClient = (LLClientView)client;
3216 m_udpServer.SendPacket(llClient.UDPClient, updateToOthers, ThrottleOutPacketType.State, true);
3217 }
3218 }
3219 );
3220 }
3221
3222 void SendObjectUpdateCompressed(SceneObjectPart obj, PrimFlags creatorFlags, PrimUpdateFlags updateFlags)
3223 {
3224 }
3225
3226 void SendImprovedTerseObjectUpdate(SceneObjectPart obj, PrimFlags creatorFlags, PrimUpdateFlags updateFlags)
3227 {
3228 }
3229
3230 void UpdateFlagsToPacketType(PrimFlags creatorFlags, PrimUpdateFlags updateFlags, out bool canUseCompressed, out bool canUseImproved)
3231 {
3232 canUseCompressed = true;
3233 canUseImproved = true;
3234
3235 if ((updateFlags & PrimUpdateFlags.FullUpdate) == PrimUpdateFlags.FullUpdate || creatorFlags != PrimFlags.None)
3236 {
3237 canUseCompressed = false;
3238 canUseImproved = false;
3239 }
3240 else
3241 {
3242 if ((updateFlags & PrimUpdateFlags.Velocity) != 0 ||
3243 (updateFlags & PrimUpdateFlags.Acceleration) != 0 ||
3244 (updateFlags & PrimUpdateFlags.CollisionPlane) != 0 ||
3245 (updateFlags & PrimUpdateFlags.Joint) != 0)
3246 {
3247 canUseCompressed = false;
3248 }
3249
3250 if ((updateFlags & PrimUpdateFlags.PrimFlags) != 0 ||
3251 (updateFlags & PrimUpdateFlags.ParentID) != 0 ||
3252 (updateFlags & PrimUpdateFlags.Scale) != 0 ||
3253 (updateFlags & PrimUpdateFlags.PrimData) != 0 ||
3254 (updateFlags & PrimUpdateFlags.Text) != 0 ||
3255 (updateFlags & PrimUpdateFlags.NameValue) != 0 ||
3256 (updateFlags & PrimUpdateFlags.ExtraData) != 0 ||
3257 (updateFlags & PrimUpdateFlags.TextureAnim) != 0 ||
3258 (updateFlags & PrimUpdateFlags.Sound) != 0 ||
3259 (updateFlags & PrimUpdateFlags.Particles) != 0 ||
3260 (updateFlags & PrimUpdateFlags.Material) != 0 ||
3261 (updateFlags & PrimUpdateFlags.ClickAction) != 0 ||
3262 (updateFlags & PrimUpdateFlags.MediaURL) != 0 ||
3263 (updateFlags & PrimUpdateFlags.Joint) != 0)
3264 {
3265 canUseImproved = false;
3266 }
3267 }
3268 }*/
3269
3270 #endregion Prim/Avatar Updates
3271
3272 #region Avatar Packet/Data Sending Methods 3109 #region Avatar Packet/Data Sending Methods
3273 3110
3274 /// <summary> 3111 /// <summary>
@@ -3314,7 +3151,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3314 ProcessAvatarTerseUpdates(); 3151 ProcessAvatarTerseUpdates();
3315 } 3152 }
3316 3153
3317 private void ProcessAvatarTerseUpdates() 3154 protected void ProcessAvatarTerseUpdates()
3318 { 3155 {
3319 ImprovedTerseObjectUpdatePacket terse = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ImprovedTerseObjectUpdate); 3156 ImprovedTerseObjectUpdatePacket terse = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ImprovedTerseObjectUpdate);
3320 terse.Header.Reliable = false; 3157 terse.Header.Reliable = false;
@@ -3335,6 +3172,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3335 terse.ObjectData[i] = m_avatarTerseUpdates.Dequeue(); 3172 terse.ObjectData[i] = m_avatarTerseUpdates.Dequeue();
3336 } 3173 }
3337 3174
3175 // HACK: Using the task category until the tiered reprioritization code is in
3338 OutPacket(terse, ThrottleOutPacketType.Task); 3176 OutPacket(terse, ThrottleOutPacketType.Task);
3339 } 3177 }
3340 3178
@@ -3343,12 +3181,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3343 if (!IsActive) return; // We don't need to update inactive clients. 3181 if (!IsActive) return; // We don't need to update inactive clients.
3344 3182
3345 CoarseLocationUpdatePacket loc = (CoarseLocationUpdatePacket)PacketPool.Instance.GetPacket(PacketType.CoarseLocationUpdate); 3183 CoarseLocationUpdatePacket loc = (CoarseLocationUpdatePacket)PacketPool.Instance.GetPacket(PacketType.CoarseLocationUpdate);
3346 // TODO: don't create new blocks if recycling an old packet 3184 loc.Header.Reliable = false;
3347 int total = CoarseLocations.Count; 3185
3348 CoarseLocationUpdatePacket.IndexBlock ib = 3186 // Each packet can only hold around 62 avatar positions and the client clears the mini-map each time
3349 new CoarseLocationUpdatePacket.IndexBlock(); 3187 // a CoarseLocationUpdate packet is received. Oh well.
3188 int total = Math.Min(CoarseLocations.Count, 60);
3189
3190 CoarseLocationUpdatePacket.IndexBlock ib = new CoarseLocationUpdatePacket.IndexBlock();
3191
3350 loc.Location = new CoarseLocationUpdatePacket.LocationBlock[total]; 3192 loc.Location = new CoarseLocationUpdatePacket.LocationBlock[total];
3351 loc.AgentData = new CoarseLocationUpdatePacket.AgentDataBlock[total]; 3193 loc.AgentData = new CoarseLocationUpdatePacket.AgentDataBlock[total];
3194
3352 int selfindex = -1; 3195 int selfindex = -1;
3353 for (int i = 0; i < total; i++) 3196 for (int i = 0; i < total; i++)
3354 { 3197 {
@@ -3358,18 +3201,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3358 lb.X = (byte)CoarseLocations[i].X; 3201 lb.X = (byte)CoarseLocations[i].X;
3359 lb.Y = (byte)CoarseLocations[i].Y; 3202 lb.Y = (byte)CoarseLocations[i].Y;
3360 3203
3361 lb.Z = CoarseLocations[i].Z > 1024 ? (byte)0 : (byte)(CoarseLocations[i].Z * 0.25); 3204 lb.Z = CoarseLocations[i].Z > 1024 ? (byte)0 : (byte)(CoarseLocations[i].Z * 0.25f);
3362 loc.Location[i] = lb; 3205 loc.Location[i] = lb;
3363 loc.AgentData[i] = new CoarseLocationUpdatePacket.AgentDataBlock(); 3206 loc.AgentData[i] = new CoarseLocationUpdatePacket.AgentDataBlock();
3364 loc.AgentData[i].AgentID = users[i]; 3207 loc.AgentData[i].AgentID = users[i];
3365 if (users[i] == AgentId) 3208 if (users[i] == AgentId)
3366 selfindex = i; 3209 selfindex = i;
3367 } 3210 }
3211
3368 ib.You = (short)selfindex; 3212 ib.You = (short)selfindex;
3369 ib.Prey = -1; 3213 ib.Prey = -1;
3370 loc.Index = ib; 3214 loc.Index = ib;
3371 loc.Header.Reliable = false;
3372 loc.Header.Zerocoded = true;
3373 3215
3374 OutPacket(loc, ThrottleOutPacketType.Task); 3216 OutPacket(loc, ThrottleOutPacketType.Task);
3375 } 3217 }
@@ -4180,11 +4022,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4180 4022
4181 protected ImprovedTerseObjectUpdatePacket.ObjectDataBlock CreateImprovedTerseBlock(SendPrimitiveTerseData data) 4023 protected ImprovedTerseObjectUpdatePacket.ObjectDataBlock CreateImprovedTerseBlock(SendPrimitiveTerseData data)
4182 { 4024 {
4183 return CreateImprovedTerseBlock(false, data.LocalID, data.State, Vector4.Zero, data.Position, data.Velocity, 4025 return CreateImprovedTerseBlock(false, data.LocalID, data.AttachPoint, Vector4.Zero, data.Position, data.Velocity,
4184 data.Acceleration, data.Rotation, data.AngularVelocity, data.TextureEntry); 4026 data.Acceleration, data.Rotation, data.AngularVelocity, data.TextureEntry);
4185 } 4027 }
4186 4028
4187 protected ImprovedTerseObjectUpdatePacket.ObjectDataBlock CreateImprovedTerseBlock(bool avatar, uint localID, byte state, 4029 protected ImprovedTerseObjectUpdatePacket.ObjectDataBlock CreateImprovedTerseBlock(bool avatar, uint localID, int attachPoint,
4188 Vector4 collisionPlane, Vector3 position, Vector3 velocity, Vector3 acceleration, Quaternion rotation, 4030 Vector4 collisionPlane, Vector3 position, Vector3 velocity, Vector3 acceleration, Quaternion rotation,
4189 Vector3 angularVelocity, byte[] textureEntry) 4031 Vector3 angularVelocity, byte[] textureEntry)
4190 { 4032 {
@@ -4196,7 +4038,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4196 pos += 4; 4038 pos += 4;
4197 4039
4198 // Avatar/CollisionPlane 4040 // Avatar/CollisionPlane
4199 data[pos++] = state; 4041 data[pos++] = (byte)((attachPoint % 16) * 16 + (attachPoint / 16)); ;
4200 if (avatar) 4042 if (avatar)
4201 { 4043 {
4202 data[pos++] = 1; 4044 data[pos++] = 1;
@@ -4430,11 +4272,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4430 /// </summary> 4272 /// </summary>
4431 protected virtual void RegisterLocalPacketHandlers() 4273 protected virtual void RegisterLocalPacketHandlers()
4432 { 4274 {
4433 AddLocalPacketHandler(PacketType.LogoutRequest, Logout); 4275 AddLocalPacketHandler(PacketType.LogoutRequest, HandleLogout);
4434 AddLocalPacketHandler(PacketType.AgentUpdate, HandleAgentUpdate); 4276 AddLocalPacketHandler(PacketType.AgentUpdate, HandleAgentUpdate);
4435 AddLocalPacketHandler(PacketType.ViewerEffect, HandleViewerEffect); 4277 AddLocalPacketHandler(PacketType.ViewerEffect, HandleViewerEffect);
4436 AddLocalPacketHandler(PacketType.AgentCachedTexture, AgentTextureCached); 4278 AddLocalPacketHandler(PacketType.AgentCachedTexture, HandleAgentTextureCached);
4437 AddLocalPacketHandler(PacketType.MultipleObjectUpdate, MultipleObjUpdate); 4279 AddLocalPacketHandler(PacketType.MultipleObjectUpdate, HandleMultipleObjUpdate);
4438 AddLocalPacketHandler(PacketType.MoneyTransferRequest, HandleMoneyTransferRequest); 4280 AddLocalPacketHandler(PacketType.MoneyTransferRequest, HandleMoneyTransferRequest);
4439 AddLocalPacketHandler(PacketType.ParcelBuy, HandleParcelBuyRequest); 4281 AddLocalPacketHandler(PacketType.ParcelBuy, HandleParcelBuyRequest);
4440 AddLocalPacketHandler(PacketType.UUIDGroupNameRequest, HandleUUIDGroupNameRequest); 4282 AddLocalPacketHandler(PacketType.UUIDGroupNameRequest, HandleUUIDGroupNameRequest);
@@ -4703,7 +4545,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4703 /// <param name="client"></param> 4545 /// <param name="client"></param>
4704 /// <param name="packet"></param> 4546 /// <param name="packet"></param>
4705 /// <returns></returns> 4547 /// <returns></returns>
4706 protected virtual bool Logout(IClientAPI client, Packet packet) 4548 protected virtual bool HandleLogout(IClientAPI client, Packet packet)
4707 { 4549 {
4708 if (packet.Type == PacketType.LogoutRequest) 4550 if (packet.Type == PacketType.LogoutRequest)
4709 { 4551 {
@@ -4741,7 +4583,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4741 /// <param name="simclient"></param> 4583 /// <param name="simclient"></param>
4742 /// <param name="packet"></param> 4584 /// <param name="packet"></param>
4743 /// <returns></returns> 4585 /// <returns></returns>
4744 protected bool AgentTextureCached(IClientAPI simclient, Packet packet) 4586 protected bool HandleAgentTextureCached(IClientAPI simclient, Packet packet)
4745 { 4587 {
4746 //m_log.Debug("texture cached: " + packet.ToString()); 4588 //m_log.Debug("texture cached: " + packet.ToString());
4747 AgentCachedTexturePacket cachedtex = (AgentCachedTexturePacket)packet; 4589 AgentCachedTexturePacket cachedtex = (AgentCachedTexturePacket)packet;
@@ -4771,7 +4613,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4771 return true; 4613 return true;
4772 } 4614 }
4773 4615
4774 protected bool MultipleObjUpdate(IClientAPI simClient, Packet packet) 4616 protected bool HandleMultipleObjUpdate(IClientAPI simClient, Packet packet)
4775 { 4617 {
4776 MultipleObjectUpdatePacket multipleupdate = (MultipleObjectUpdatePacket)packet; 4618 MultipleObjectUpdatePacket multipleupdate = (MultipleObjectUpdatePacket)packet;
4777 if (multipleupdate.AgentData.SessionID != SessionId) return false; 4619 if (multipleupdate.AgentData.SessionID != SessionId) return false;
@@ -5050,11 +4892,28 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5050 /// </summary> 4892 /// </summary>
5051 /// <param name="packet">Packet to send</param> 4893 /// <param name="packet">Packet to send</param>
5052 /// <param name="throttlePacketType">Throttling category for the packet</param> 4894 /// <param name="throttlePacketType">Throttling category for the packet</param>
5053 private void OutPacket(Packet packet, ThrottleOutPacketType throttlePacketType) 4895 protected void OutPacket(Packet packet, ThrottleOutPacketType throttlePacketType)
5054 { 4896 {
4897 #region BinaryStats
4898 LLUDPServer.LogPacketHeader(false, m_circuitCode, 0, packet.Type, (ushort)packet.Length);
4899 #endregion BinaryStats
4900
5055 m_udpServer.SendPacket(m_udpClient, packet, throttlePacketType, true); 4901 m_udpServer.SendPacket(m_udpClient, packet, throttlePacketType, true);
5056 } 4902 }
5057 4903
4904 /// <summary>
4905 /// This is the starting point for sending a simulator packet out to the client
4906 /// </summary>
4907 /// <param name="packet">Packet to send</param>
4908 /// <param name="throttlePacketType">Throttling category for the packet</param>
4909 /// <param name="doAutomaticSplitting">True to automatically split oversized
4910 /// packets (the default), or false to disable splitting if the calling code
4911 /// handles splitting manually</param>
4912 protected void OutPacket(Packet packet, ThrottleOutPacketType throttlePacketType, bool doAutomaticSplitting)
4913 {
4914 m_udpServer.SendPacket(m_udpClient, packet, throttlePacketType, doAutomaticSplitting);
4915 }
4916
5058 public bool AddMoney(int debit) 4917 public bool AddMoney(int debit)
5059 { 4918 {
5060 if (m_moneyBalance + debit >= 0) 4919 if (m_moneyBalance + debit >= 0)
@@ -9854,7 +9713,26 @@ namespace OpenSim.Region.ClientStack.LindenUDP
9854 Utils.BytesToString(avatarInterestUpdate.PropertiesData.SkillsText), 9713 Utils.BytesToString(avatarInterestUpdate.PropertiesData.SkillsText),
9855 Utils.BytesToString(avatarInterestUpdate.PropertiesData.LanguagesText)); 9714 Utils.BytesToString(avatarInterestUpdate.PropertiesData.LanguagesText));
9856 break; 9715 break;
9857 9716
9717 case PacketType.GrantUserRights:
9718 GrantUserRightsPacket GrantUserRights =
9719 (GrantUserRightsPacket)Pack;
9720 #region Packet Session and User Check
9721 if (m_checkPackets)
9722 {
9723 if (GrantUserRights.AgentData.SessionID != SessionId ||
9724 GrantUserRights.AgentData.AgentID != AgentId)
9725 break;
9726 }
9727 #endregion
9728 GrantUserFriendRights GrantUserRightsHandler = OnGrantUserRights;
9729 if (GrantUserRightsHandler != null)
9730 GrantUserRightsHandler(this,
9731 GrantUserRights.AgentData.AgentID,
9732 GrantUserRights.Rights[0].AgentRelated,
9733 GrantUserRights.Rights[0].RelatedRights);
9734 break;
9735
9858 case PacketType.PlacesQuery: 9736 case PacketType.PlacesQuery:
9859 PlacesQueryPacket placesQueryPacket = 9737 PlacesQueryPacket placesQueryPacket =
9860 (PlacesQueryPacket)Pack; 9738 (PlacesQueryPacket)Pack;
@@ -9944,7 +9822,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
9944 commandMessagePacket.CommandBlock.Command = (uint)command; 9822 commandMessagePacket.CommandBlock.Command = (uint)command;
9945 commandMessagePacket.CommandBlock.Time = time; 9823 commandMessagePacket.CommandBlock.Time = time;
9946 9824
9947 OutPacket(commandMessagePacket, ThrottleOutPacketType.Unknown); 9825 OutPacket(commandMessagePacket, ThrottleOutPacketType.Task);
9948 } 9826 }
9949 9827
9950 public void SendParcelMediaUpdate(string mediaUrl, UUID mediaTextureID, 9828 public void SendParcelMediaUpdate(string mediaUrl, UUID mediaTextureID,
@@ -9962,7 +9840,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
9962 updatePacket.DataBlockExtended.MediaHeight = mediaHeight; 9840 updatePacket.DataBlockExtended.MediaHeight = mediaHeight;
9963 updatePacket.DataBlockExtended.MediaLoop = mediaLoop; 9841 updatePacket.DataBlockExtended.MediaLoop = mediaLoop;
9964 9842
9965 OutPacket(updatePacket, ThrottleOutPacketType.Unknown); 9843 OutPacket(updatePacket, ThrottleOutPacketType.Task);
9966 } 9844 }
9967 9845
9968 #endregion 9846 #endregion
@@ -10236,7 +10114,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
10236 } 10114 }
10237 10115
10238 #region PriorityQueue 10116 #region PriorityQueue
10239 private class PriorityQueue<TPriority, TValue> 10117 public class PriorityQueue<TPriority, TValue>
10240 { 10118 {
10241 internal delegate bool UpdatePriorityHandler(ref TPriority priority, uint local_id); 10119 internal delegate bool UpdatePriorityHandler(ref TPriority priority, uint local_id);
10242 10120
@@ -10264,7 +10142,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
10264 this.m_comparison = comparison; 10142 this.m_comparison = comparison;
10265 } 10143 }
10266 10144
10267 internal object SyncRoot { get { return this.m_syncRoot; } } 10145 public object SyncRoot { get { return this.m_syncRoot; } }
10268 internal int Count 10146 internal int Count
10269 { 10147 {
10270 get 10148 get
@@ -10276,7 +10154,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
10276 } 10154 }
10277 } 10155 }
10278 10156
10279 internal bool Enqueue(TPriority priority, TValue value, uint local_id) 10157 public bool Enqueue(TPriority priority, TValue value, uint local_id)
10280 { 10158 {
10281 LookupItem item; 10159 LookupItem item;
10282 10160
@@ -10396,5 +10274,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
10396 } 10274 }
10397 #endregion 10275 #endregion
10398 10276
10277 public static OSD BuildEvent(string eventName, OSD eventBody)
10278 {
10279 OSDMap osdEvent = new OSDMap(2);
10280 osdEvent.Add("message", new OSDString(eventName));
10281 osdEvent.Add("body", eventBody);
10282
10283 return osdEvent;
10284 }
10399 } 10285 }
10400} 10286}
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLFileTransfer.cs b/OpenSim/Region/ClientStack/LindenUDP/LLFileTransfer.cs
index 697bbe6..adf171e 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLFileTransfer.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLFileTransfer.cs
@@ -197,11 +197,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
197 197
198 private void Initialise(UUID fileID, string fileName) 198 private void Initialise(UUID fileID, string fileName)
199 { 199 {
200 m_asset = new AssetBase(); 200 m_asset = new AssetBase(fileID, fileName, type);
201 m_asset.FullID = fileID;
202 m_asset.Type = type;
203 m_asset.Data = new byte[0]; 201 m_asset.Data = new byte[0];
204 m_asset.Name = fileName;
205 m_asset.Description = "empty"; 202 m_asset.Description = "empty";
206 m_asset.Local = true; 203 m_asset.Local = true;
207 m_asset.Temporary = true; 204 m_asset.Temporary = true;
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs
index 84a4959..9856a1c 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs
@@ -135,8 +135,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
135 private readonly TokenBucket m_throttle; 135 private readonly TokenBucket m_throttle;
136 /// <summary>Throttle buckets for each packet category</summary> 136 /// <summary>Throttle buckets for each packet category</summary>
137 private readonly TokenBucket[] m_throttleCategories; 137 private readonly TokenBucket[] m_throttleCategories;
138 /// <summary>Throttle rate defaults and limits</summary>
139 private readonly ThrottleRates m_defaultThrottleRates;
140 /// <summary>Outgoing queues for throttled packets</summary> 138 /// <summary>Outgoing queues for throttled packets</summary>
141 private readonly OpenSim.Framework.LocklessQueue<OutgoingPacket>[] m_packetOutboxes = new OpenSim.Framework.LocklessQueue<OutgoingPacket>[THROTTLE_CATEGORY_COUNT]; 139 private readonly OpenSim.Framework.LocklessQueue<OutgoingPacket>[] m_packetOutboxes = new OpenSim.Framework.LocklessQueue<OutgoingPacket>[THROTTLE_CATEGORY_COUNT];
142 /// <summary>A container that can hold one packet for each outbox, used to store 140 /// <summary>A container that can hold one packet for each outbox, used to store
@@ -145,6 +143,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
145 /// <summary>A reference to the LLUDPServer that is managing this client</summary> 143 /// <summary>A reference to the LLUDPServer that is managing this client</summary>
146 private readonly LLUDPServer m_udpServer; 144 private readonly LLUDPServer m_udpServer;
147 145
146 private int m_defaultRTO = 3000;
147 private int m_maxRTO = 60000;
148
148 /// <summary> 149 /// <summary>
149 /// Default constructor 150 /// Default constructor
150 /// </summary> 151 /// </summary>
@@ -155,13 +156,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP
155 /// <param name="circuitCode">Circuit code for this connection</param> 156 /// <param name="circuitCode">Circuit code for this connection</param>
156 /// <param name="agentID">AgentID for the connected agent</param> 157 /// <param name="agentID">AgentID for the connected agent</param>
157 /// <param name="remoteEndPoint">Remote endpoint for this connection</param> 158 /// <param name="remoteEndPoint">Remote endpoint for this connection</param>
158 public LLUDPClient(LLUDPServer server, ThrottleRates rates, TokenBucket parentThrottle, uint circuitCode, UUID agentID, IPEndPoint remoteEndPoint) 159 public LLUDPClient(LLUDPServer server, ThrottleRates rates, TokenBucket parentThrottle, uint circuitCode, UUID agentID, IPEndPoint remoteEndPoint, int defaultRTO, int maxRTO)
159 { 160 {
160 AgentID = agentID; 161 AgentID = agentID;
161 RemoteEndPoint = remoteEndPoint; 162 RemoteEndPoint = remoteEndPoint;
162 CircuitCode = circuitCode; 163 CircuitCode = circuitCode;
163 m_udpServer = server; 164 m_udpServer = server;
164 m_defaultThrottleRates = rates; 165 if (defaultRTO != 0)
166 m_defaultRTO = defaultRTO;
167 if (maxRTO != 0)
168 m_maxRTO = maxRTO;
169
165 // Create a token bucket throttle for this client that has the scene token bucket as a parent 170 // Create a token bucket throttle for this client that has the scene token bucket as a parent
166 m_throttle = new TokenBucket(parentThrottle, rates.TotalLimit, rates.Total); 171 m_throttle = new TokenBucket(parentThrottle, rates.TotalLimit, rates.Total);
167 // Create an array of token buckets for this clients different throttle categories 172 // Create an array of token buckets for this clients different throttle categories
@@ -178,7 +183,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
178 } 183 }
179 184
180 // Default the retransmission timeout to three seconds 185 // Default the retransmission timeout to three seconds
181 RTO = 3000; 186 RTO = m_defaultRTO;
182 187
183 // Initialize this to a sane value to prevent early disconnects 188 // Initialize this to a sane value to prevent early disconnects
184 TickLastPacketReceived = Environment.TickCount & Int32.MaxValue; 189 TickLastPacketReceived = Environment.TickCount & Int32.MaxValue;
@@ -500,7 +505,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
500 int rto = (int)(SRTT + Math.Max(m_udpServer.TickCountResolution, K * RTTVAR)); 505 int rto = (int)(SRTT + Math.Max(m_udpServer.TickCountResolution, K * RTTVAR));
501 506
502 // Clamp the retransmission timeout to manageable values 507 // Clamp the retransmission timeout to manageable values
503 rto = Utils.Clamp(RTO, 3000, 60000); 508 rto = Utils.Clamp(RTO, m_defaultRTO, m_maxRTO);
504 509
505 RTO = rto; 510 RTO = rto;
506 511
@@ -520,7 +525,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
520 RTTVAR = 0.0f; 525 RTTVAR = 0.0f;
521 526
522 // Double the retransmission timeout 527 // Double the retransmission timeout
523 RTO = Math.Min(RTO * 2, 60000); 528 RTO = Math.Min(RTO * 2, m_maxRTO);
524 } 529 }
525 530
526 /// <summary> 531 /// <summary>
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
index 74d3262..0b05ed9 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
@@ -27,6 +27,7 @@
27 27
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.IO;
30using System.Net; 31using System.Net;
31using System.Net.Sockets; 32using System.Net.Sockets;
32using System.Reflection; 33using System.Reflection;
@@ -118,13 +119,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
118 /// <summary></summary> 119 /// <summary></summary>
119 //private UDPClientCollection m_clients = new UDPClientCollection(); 120 //private UDPClientCollection m_clients = new UDPClientCollection();
120 /// <summary>Bandwidth throttle for this UDP server</summary> 121 /// <summary>Bandwidth throttle for this UDP server</summary>
121 private TokenBucket m_throttle; 122 protected TokenBucket m_throttle;
122 /// <summary>Bandwidth throttle rates for this UDP server</summary> 123 /// <summary>Bandwidth throttle rates for this UDP server</summary>
123 private ThrottleRates m_throttleRates; 124 protected ThrottleRates m_throttleRates;
124 /// <summary>Manages authentication for agent circuits</summary> 125 /// <summary>Manages authentication for agent circuits</summary>
125 private AgentCircuitManager m_circuitManager; 126 private AgentCircuitManager m_circuitManager;
126 /// <summary>Reference to the scene this UDP server is attached to</summary> 127 /// <summary>Reference to the scene this UDP server is attached to</summary>
127 private Scene m_scene; 128 protected Scene m_scene;
128 /// <summary>The X/Y coordinates of the scene this UDP server is attached to</summary> 129 /// <summary>The X/Y coordinates of the scene this UDP server is attached to</summary>
129 private Location m_location; 130 private Location m_location;
130 /// <summary>The size of the receive buffer for the UDP socket. This value 131 /// <summary>The size of the receive buffer for the UDP socket. This value
@@ -153,6 +154,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
153 /// <summary>Flag to signal when clients should send pings</summary> 154 /// <summary>Flag to signal when clients should send pings</summary>
154 private bool m_sendPing; 155 private bool m_sendPing;
155 156
157 private int m_defaultRTO = 0;
158 private int m_maxRTO = 0;
159
156 public Socket Server { get { return null; } } 160 public Socket Server { get { return null; } }
157 161
158 public LLUDPServer(IPAddress listenIP, ref uint port, int proxyPortOffsetParm, bool allow_alternate_port, IConfigSource configSource, AgentCircuitManager circuitManager) 162 public LLUDPServer(IPAddress listenIP, ref uint port, int proxyPortOffsetParm, bool allow_alternate_port, IConfigSource configSource, AgentCircuitManager circuitManager)
@@ -189,6 +193,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
189 AvatarTerseUpdatesPerPacket = config.GetInt("AvatarTerseUpdatesPerPacket", 10); 193 AvatarTerseUpdatesPerPacket = config.GetInt("AvatarTerseUpdatesPerPacket", 10);
190 PrimFullUpdatesPerPacket = config.GetInt("PrimFullUpdatesPerPacket", 100); 194 PrimFullUpdatesPerPacket = config.GetInt("PrimFullUpdatesPerPacket", 100);
191 TextureSendLimit = config.GetInt("TextureSendLimit", 20); 195 TextureSendLimit = config.GetInt("TextureSendLimit", 20);
196
197 m_defaultRTO = config.GetInt("DefaultRTO", 0);
198 m_maxRTO = config.GetInt("MaxRTO", 0);
192 } 199 }
193 else 200 else
194 { 201 {
@@ -198,6 +205,31 @@ namespace OpenSim.Region.ClientStack.LindenUDP
198 TextureSendLimit = 20; 205 TextureSendLimit = 20;
199 } 206 }
200 207
208 #region BinaryStats
209 config = configSource.Configs["Statistics.Binary"];
210 m_shouldCollectStats = false;
211 if (config != null)
212 {
213 if (config.Contains("enabled") && config.GetBoolean("enabled"))
214 {
215 if (config.Contains("collect_packet_headers"))
216 m_shouldCollectStats = config.GetBoolean("collect_packet_headers");
217 if (config.Contains("packet_headers_period_seconds"))
218 {
219 binStatsMaxFilesize = TimeSpan.FromSeconds(config.GetInt("region_stats_period_seconds"));
220 }
221 if (config.Contains("stats_dir"))
222 {
223 binStatsDir = config.GetString("stats_dir");
224 }
225 }
226 else
227 {
228 m_shouldCollectStats = false;
229 }
230 }
231 #endregion BinaryStats
232
201 m_throttle = new TokenBucket(null, sceneThrottleBps, sceneThrottleBps); 233 m_throttle = new TokenBucket(null, sceneThrottleBps, sceneThrottleBps);
202 m_throttleRates = new ThrottleRates(configSource); 234 m_throttleRates = new ThrottleRates(configSource);
203 } 235 }
@@ -247,8 +279,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
247 279
248 public void BroadcastPacket(Packet packet, ThrottleOutPacketType category, bool sendToPausedAgents, bool allowSplitting) 280 public void BroadcastPacket(Packet packet, ThrottleOutPacketType category, bool sendToPausedAgents, bool allowSplitting)
249 { 281 {
250 // CoarseLocationUpdate packets cannot be split in an automated way 282 // CoarseLocationUpdate and AvatarGroupsReply packets cannot be split in an automated way
251 if (packet.Type == PacketType.CoarseLocationUpdate && allowSplitting) 283 if ((packet.Type == PacketType.CoarseLocationUpdate || packet.Type == PacketType.AvatarGroupsReply) && allowSplitting)
252 allowSplitting = false; 284 allowSplitting = false;
253 285
254 if (allowSplitting && packet.HasVariableBlocks) 286 if (allowSplitting && packet.HasVariableBlocks)
@@ -256,8 +288,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
256 byte[][] datas = packet.ToBytesMultiple(); 288 byte[][] datas = packet.ToBytesMultiple();
257 int packetCount = datas.Length; 289 int packetCount = datas.Length;
258 290
259 //if (packetCount > 1) 291 if (packetCount < 1)
260 // m_log.Debug("[LLUDPSERVER]: Split " + packet.Type + " packet into " + packetCount + " packets"); 292 m_log.Error("[LLUDPSERVER]: Failed to split " + packet.Type + " with estimated length " + packet.Length);
261 293
262 for (int i = 0; i < packetCount; i++) 294 for (int i = 0; i < packetCount; i++)
263 { 295 {
@@ -295,8 +327,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
295 byte[][] datas = packet.ToBytesMultiple(); 327 byte[][] datas = packet.ToBytesMultiple();
296 int packetCount = datas.Length; 328 int packetCount = datas.Length;
297 329
298 //if (packetCount > 1) 330 if (packetCount < 1)
299 // m_log.Debug("[LLUDPSERVER]: Split " + packet.Type + " packet into " + packetCount + " packets"); 331 m_log.Error("[LLUDPSERVER]: Failed to split " + packet.Type + " with estimated length " + packet.Length);
300 332
301 for (int i = 0; i < packetCount; i++) 333 for (int i = 0; i < packetCount; i++)
302 { 334 {
@@ -353,9 +385,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
353 } 385 }
354 else 386 else
355 { 387 {
356 m_log.Error("[LLUDPSERVER]: Packet exceeded buffer size! This could be an indication of packet assembly not obeying the MTU. Type=" + 388 bufferSize = dataLength;
357 type + ", DataLength=" + dataLength + ", BufferLength=" + buffer.Data.Length + ". Dropping packet"); 389 buffer = new UDPPacketBuffer(udpClient.RemoteEndPoint, bufferSize);
358 return; 390
391 // m_log.Error("[LLUDPSERVER]: Packet exceeded buffer size! This could be an indication of packet assembly not obeying the MTU. Type=" +
392 // type + ", DataLength=" + dataLength + ", BufferLength=" + buffer.Data.Length + ". Dropping packet");
393 Buffer.BlockCopy(data, 0, buffer.Data, 0, dataLength);
359 } 394 }
360 } 395 }
361 396
@@ -364,6 +399,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
364 #region Queue or Send 399 #region Queue or Send
365 400
366 OutgoingPacket outgoingPacket = new OutgoingPacket(udpClient, buffer, category); 401 OutgoingPacket outgoingPacket = new OutgoingPacket(udpClient, buffer, category);
402 outgoingPacket.Type = type;
367 403
368 if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket)) 404 if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket))
369 SendPacketFinal(outgoingPacket); 405 SendPacketFinal(outgoingPacket);
@@ -409,6 +445,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
409 SendPacket(udpClient, pc, ThrottleOutPacketType.Unknown, false); 445 SendPacket(udpClient, pc, ThrottleOutPacketType.Unknown, false);
410 } 446 }
411 447
448 public void CompletePing(LLUDPClient udpClient, byte pingID)
449 {
450 CompletePingCheckPacket completePing = new CompletePingCheckPacket();
451 completePing.PingID.PingID = pingID;
452 SendPacket(udpClient, completePing, ThrottleOutPacketType.Unknown, false);
453 }
454
412 public void ResendUnacked(LLUDPClient udpClient) 455 public void ResendUnacked(LLUDPClient udpClient)
413 { 456 {
414 if (!udpClient.IsConnected) 457 if (!udpClient.IsConnected)
@@ -429,7 +472,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
429 472
430 if (expiredPackets != null) 473 if (expiredPackets != null)
431 { 474 {
432 m_log.Debug("[LLUDPSERVER]: Resending " + expiredPackets.Count + " packets to " + udpClient.AgentID + ", RTO=" + udpClient.RTO); 475 //m_log.Debug("[LLUDPSERVER]: Resending " + expiredPackets.Count + " packets to " + udpClient.AgentID + ", RTO=" + udpClient.RTO);
433 476
434 // Exponential backoff of the retransmission timeout 477 // Exponential backoff of the retransmission timeout
435 udpClient.BackoffRTO(); 478 udpClient.BackoffRTO();
@@ -468,6 +511,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
468 byte flags = buffer.Data[0]; 511 byte flags = buffer.Data[0];
469 bool isResend = (flags & Helpers.MSG_RESENT) != 0; 512 bool isResend = (flags & Helpers.MSG_RESENT) != 0;
470 bool isReliable = (flags & Helpers.MSG_RELIABLE) != 0; 513 bool isReliable = (flags & Helpers.MSG_RELIABLE) != 0;
514 bool sendSynchronous = false;
471 LLUDPClient udpClient = outgoingPacket.Client; 515 LLUDPClient udpClient = outgoingPacket.Client;
472 516
473 if (!udpClient.IsConnected) 517 if (!udpClient.IsConnected)
@@ -523,9 +567,27 @@ namespace OpenSim.Region.ClientStack.LindenUDP
523 if (isReliable) 567 if (isReliable)
524 Interlocked.Add(ref udpClient.UnackedBytes, outgoingPacket.Buffer.DataLength); 568 Interlocked.Add(ref udpClient.UnackedBytes, outgoingPacket.Buffer.DataLength);
525 569
526 // Put the UDP payload on the wire 570 //Some packet types need to be sent synchonously.
527 AsyncBeginSend(buffer); 571 //Sorry, i know it's not optimal, but until the LL client
572 //manages packets correctly and re-orders them as required, this is necessary.
528 573
574 if (outgoingPacket.Type == PacketType.ImprovedTerseObjectUpdate
575 || outgoingPacket.Type == PacketType.ChatFromSimulator
576 || outgoingPacket.Type == PacketType.ObjectUpdate
577 || outgoingPacket.Type == PacketType.LayerData)
578 {
579 sendSynchronous = true;
580 }
581
582 // Put the UDP payload on the wire
583 if (sendSynchronous == true)
584 {
585 SyncBeginSend(buffer);
586 }
587 else
588 {
589 AsyncBeginSend(buffer);
590 }
529 // Keep track of when this packet was sent out (right now) 591 // Keep track of when this packet was sent out (right now)
530 outgoingPacket.TickCount = Environment.TickCount & Int32.MaxValue; 592 outgoingPacket.TickCount = Environment.TickCount & Int32.MaxValue;
531 } 593 }
@@ -585,7 +647,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
585 IClientAPI client; 647 IClientAPI client;
586 if (!m_scene.TryGetClient(address, out client) || !(client is LLClientView)) 648 if (!m_scene.TryGetClient(address, out client) || !(client is LLClientView))
587 { 649 {
588 m_log.Debug("[LLUDPSERVER]: Received a " + packet.Type + " packet from an unrecognized source: " + address + " in " + m_scene.RegionInfo.RegionName); 650 //m_log.Debug("[LLUDPSERVER]: Received a " + packet.Type + " packet from an unrecognized source: " + address + " in " + m_scene.RegionInfo.RegionName);
589 return; 651 return;
590 } 652 }
591 653
@@ -663,16 +725,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP
663 725
664 #endregion Incoming Packet Accounting 726 #endregion Incoming Packet Accounting
665 727
728 #region BinaryStats
729 LogPacketHeader(true, udpClient.CircuitCode, 0, packet.Type, (ushort)packet.Length);
730 #endregion BinaryStats
731
666 #region Ping Check Handling 732 #region Ping Check Handling
667 733
668 if (packet.Type == PacketType.StartPingCheck) 734 if (packet.Type == PacketType.StartPingCheck)
669 { 735 {
670 // We don't need to do anything else with ping checks 736 // We don't need to do anything else with ping checks
671 StartPingCheckPacket startPing = (StartPingCheckPacket)packet; 737 StartPingCheckPacket startPing = (StartPingCheckPacket)packet;
672 738 CompletePing(udpClient, startPing.PingID.PingID);
673 CompletePingCheckPacket completePing = new CompletePingCheckPacket();
674 completePing.PingID.PingID = startPing.PingID.PingID;
675 SendPacket(udpClient, completePing, ThrottleOutPacketType.Unknown, false);
676 return; 739 return;
677 } 740 }
678 else if (packet.Type == PacketType.CompletePingCheck) 741 else if (packet.Type == PacketType.CompletePingCheck)
@@ -687,6 +750,87 @@ namespace OpenSim.Region.ClientStack.LindenUDP
687 packetInbox.Enqueue(new IncomingPacket(udpClient, packet)); 750 packetInbox.Enqueue(new IncomingPacket(udpClient, packet));
688 } 751 }
689 752
753 #region BinaryStats
754
755 public class PacketLogger
756 {
757 public DateTime StartTime;
758 public string Path = null;
759 public System.IO.BinaryWriter Log = null;
760 }
761
762 public static PacketLogger PacketLog;
763
764 protected static bool m_shouldCollectStats = false;
765 // Number of seconds to log for
766 static TimeSpan binStatsMaxFilesize = TimeSpan.FromSeconds(300);
767 static object binStatsLogLock = new object();
768 static string binStatsDir = "";
769
770 public static void LogPacketHeader(bool incoming, uint circuit, byte flags, PacketType packetType, ushort size)
771 {
772 if (!m_shouldCollectStats) return;
773
774 // Binary logging format is TTTTTTTTCCCCFPPPSS, T=Time, C=Circuit, F=Flags, P=PacketType, S=size
775
776 // Put the incoming bit into the least significant bit of the flags byte
777 if (incoming)
778 flags |= 0x01;
779 else
780 flags &= 0xFE;
781
782 // Put the flags byte into the most significant bits of the type integer
783 uint type = (uint)packetType;
784 type |= (uint)flags << 24;
785
786 // m_log.Debug("1 LogPacketHeader(): Outside lock");
787 lock (binStatsLogLock)
788 {
789 DateTime now = DateTime.Now;
790
791 // m_log.Debug("2 LogPacketHeader(): Inside lock. now is " + now.Ticks);
792 try
793 {
794 if (PacketLog == null || (now > PacketLog.StartTime + binStatsMaxFilesize))
795 {
796 if (PacketLog != null && PacketLog.Log != null)
797 {
798 PacketLog.Log.Close();
799 }
800
801 // First log file or time has expired, start writing to a new log file
802 PacketLog = new PacketLogger();
803 PacketLog.StartTime = now;
804 PacketLog.Path = (binStatsDir.Length > 0 ? binStatsDir + System.IO.Path.DirectorySeparatorChar.ToString() : "")
805 + String.Format("packets-{0}.log", now.ToString("yyyyMMddHHmmss"));
806 PacketLog.Log = new BinaryWriter(File.Open(PacketLog.Path, FileMode.Append, FileAccess.Write));
807 }
808
809 // Serialize the data
810 byte[] output = new byte[18];
811 Buffer.BlockCopy(BitConverter.GetBytes(now.Ticks), 0, output, 0, 8);
812 Buffer.BlockCopy(BitConverter.GetBytes(circuit), 0, output, 8, 4);
813 Buffer.BlockCopy(BitConverter.GetBytes(type), 0, output, 12, 4);
814 Buffer.BlockCopy(BitConverter.GetBytes(size), 0, output, 16, 2);
815
816 // Write the serialized data to disk
817 if (PacketLog != null && PacketLog.Log != null)
818 PacketLog.Log.Write(output);
819 }
820 catch (Exception ex)
821 {
822 m_log.Error("Packet statistics gathering failed: " + ex.Message, ex);
823 if (PacketLog.Log != null)
824 {
825 PacketLog.Log.Close();
826 }
827 PacketLog = null;
828 }
829 }
830 }
831
832 #endregion BinaryStats
833
690 private void HandleUseCircuitCode(object o) 834 private void HandleUseCircuitCode(object o)
691 { 835 {
692 object[] array = (object[])o; 836 object[] array = (object[])o;
@@ -759,10 +903,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
759 } 903 }
760 } 904 }
761 905
762 private void AddClient(uint circuitCode, UUID agentID, UUID sessionID, IPEndPoint remoteEndPoint, AuthenticateResponse sessionInfo) 906 protected virtual void AddClient(uint circuitCode, UUID agentID, UUID sessionID, IPEndPoint remoteEndPoint, AuthenticateResponse sessionInfo)
763 { 907 {
764 // Create the LLUDPClient 908 // Create the LLUDPClient
765 LLUDPClient udpClient = new LLUDPClient(this, m_throttleRates, m_throttle, circuitCode, agentID, remoteEndPoint); 909 LLUDPClient udpClient = new LLUDPClient(this, m_throttleRates, m_throttle, circuitCode, agentID, remoteEndPoint, m_defaultRTO, m_maxRTO);
766 IClientAPI existingClient; 910 IClientAPI existingClient;
767 911
768 if (!m_scene.TryGetClient(agentID, out existingClient)) 912 if (!m_scene.TryGetClient(agentID, out existingClient))
@@ -976,7 +1120,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
976 } 1120 }
977 } 1121 }
978 1122
979 private void LogoutHandler(IClientAPI client) 1123 protected void LogoutHandler(IClientAPI client)
980 { 1124 {
981 client.SendLogoutPacket(); 1125 client.SendLogoutPacket();
982 if (client.IsActive) 1126 if (client.IsActive)
diff --git a/OpenSim/Region/ClientStack/LindenUDP/OpenSimUDPBase.cs b/OpenSim/Region/ClientStack/LindenUDP/OpenSimUDPBase.cs
index 552cc4a..63579ac 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/OpenSimUDPBase.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/OpenSimUDPBase.cs
@@ -246,6 +246,24 @@ namespace OpenMetaverse
246 } 246 }
247 } 247 }
248 248
249 public void SyncBeginSend(UDPPacketBuffer buf)
250 {
251 if (!m_shutdownFlag)
252 {
253 try
254 {
255 m_udpSocket.SendTo(
256 buf.Data,
257 0,
258 buf.DataLength,
259 SocketFlags.None,
260 buf.RemoteEndPoint);
261 }
262 catch (SocketException) { }
263 catch (ObjectDisposedException) { }
264 }
265 }
266
249 public void AsyncBeginSend(UDPPacketBuffer buf) 267 public void AsyncBeginSend(UDPPacketBuffer buf)
250 { 268 {
251 if (!m_shutdownFlag) 269 if (!m_shutdownFlag)
@@ -270,8 +288,8 @@ namespace OpenMetaverse
270 { 288 {
271 try 289 try
272 { 290 {
273 UDPPacketBuffer buf = (UDPPacketBuffer)result.AsyncState; 291// UDPPacketBuffer buf = (UDPPacketBuffer)result.AsyncState;
274 int bytesSent = m_udpSocket.EndSendTo(result); 292 m_udpSocket.EndSendTo(result);
275 } 293 }
276 catch (SocketException) { } 294 catch (SocketException) { }
277 catch (ObjectDisposedException) { } 295 catch (ObjectDisposedException) { }
diff --git a/OpenSim/Region/ClientStack/LindenUDP/OutgoingPacket.cs b/OpenSim/Region/ClientStack/LindenUDP/OutgoingPacket.cs
index 1a1a1cb..7dc42d3 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/OutgoingPacket.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/OutgoingPacket.cs
@@ -28,6 +28,7 @@
28using System; 28using System;
29using OpenSim.Framework; 29using OpenSim.Framework;
30using OpenMetaverse; 30using OpenMetaverse;
31using OpenMetaverse.Packets;
31 32
32namespace OpenSim.Region.ClientStack.LindenUDP 33namespace OpenSim.Region.ClientStack.LindenUDP
33{ 34{
@@ -52,7 +53,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
52 public int TickCount; 53 public int TickCount;
53 /// <summary>Category this packet belongs to</summary> 54 /// <summary>Category this packet belongs to</summary>
54 public ThrottleOutPacketType Category; 55 public ThrottleOutPacketType Category;
55 56 /// <summary>The type of packet so its delivery method can be determined</summary>
57 public PacketType Type;
56 /// <summary> 58 /// <summary>
57 /// Default constructor 59 /// Default constructor
58 /// </summary> 60 /// </summary>
diff --git a/OpenSim/Region/ClientStack/LindenUDP/ThrottleRates.cs b/OpenSim/Region/ClientStack/LindenUDP/ThrottleRates.cs
index 008d827..aaf6e26 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/ThrottleRates.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/ThrottleRates.cs
@@ -87,15 +87,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
87 IConfig throttleConfig = config.Configs["ClientStack.LindenUDP"]; 87 IConfig throttleConfig = config.Configs["ClientStack.LindenUDP"];
88 88
89 Resend = throttleConfig.GetInt("resend_default", 12500); 89 Resend = throttleConfig.GetInt("resend_default", 12500);
90 Land = throttleConfig.GetInt("land_default", 500); 90 Land = throttleConfig.GetInt("land_default", 1000);
91 Wind = throttleConfig.GetInt("wind_default", 500); 91 Wind = throttleConfig.GetInt("wind_default", 1000);
92 Cloud = throttleConfig.GetInt("cloud_default", 500); 92 Cloud = throttleConfig.GetInt("cloud_default", 1000);
93 Task = throttleConfig.GetInt("task_default", 500); 93 Task = throttleConfig.GetInt("task_default", 1000);
94 Texture = throttleConfig.GetInt("texture_default", 500); 94 Texture = throttleConfig.GetInt("texture_default", 1000);
95 Asset = throttleConfig.GetInt("asset_default", 500); 95 Asset = throttleConfig.GetInt("asset_default", 1000);
96 State = throttleConfig.GetInt("state_default", 500); 96 State = throttleConfig.GetInt("state_default", 1000);
97
98 Total = throttleConfig.GetInt("client_throttle_max_bps", 0);
99 97
100 ResendLimit = throttleConfig.GetInt("resend_limit", 18750); 98 ResendLimit = throttleConfig.GetInt("resend_limit", 18750);
101 LandLimit = throttleConfig.GetInt("land_limit", 29750); 99 LandLimit = throttleConfig.GetInt("land_limit", 29750);
@@ -104,9 +102,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
104 TaskLimit = throttleConfig.GetInt("task_limit", 18750); 102 TaskLimit = throttleConfig.GetInt("task_limit", 18750);
105 TextureLimit = throttleConfig.GetInt("texture_limit", 55750); 103 TextureLimit = throttleConfig.GetInt("texture_limit", 55750);
106 AssetLimit = throttleConfig.GetInt("asset_limit", 27500); 104 AssetLimit = throttleConfig.GetInt("asset_limit", 27500);
107 State = throttleConfig.GetInt("state_limit", 37000); 105 StateLimit = throttleConfig.GetInt("state_limit", 37000);
108 106
109 TotalLimit = throttleConfig.GetInt("client_throttle_max_bps", 0); 107 Total = throttleConfig.GetInt("client_throttle_max_bps", 0);
108 TotalLimit = Total;
110 } 109 }
111 catch (Exception) { } 110 catch (Exception) { }
112 } 111 }