diff options
Diffstat (limited to 'OpenSim/Region/ClientStack')
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; | |||
37 | using log4net; | 37 | using log4net; |
38 | using OpenMetaverse; | 38 | using OpenMetaverse; |
39 | using OpenMetaverse.Packets; | 39 | using OpenMetaverse.Packets; |
40 | using OpenMetaverse.StructuredData; | ||
40 | using OpenSim.Framework; | 41 | using OpenSim.Framework; |
41 | using OpenSim.Framework.Client; | 42 | using OpenSim.Framework.Client; |
42 | using OpenSim.Framework.Communications.Cache; | 43 | using 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 | ||
28 | using System; | 28 | using System; |
29 | using System.Collections.Generic; | 29 | using System.Collections.Generic; |
30 | using System.IO; | ||
30 | using System.Net; | 31 | using System.Net; |
31 | using System.Net.Sockets; | 32 | using System.Net.Sockets; |
32 | using System.Reflection; | 33 | using 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 @@ | |||
28 | using System; | 28 | using System; |
29 | using OpenSim.Framework; | 29 | using OpenSim.Framework; |
30 | using OpenMetaverse; | 30 | using OpenMetaverse; |
31 | using OpenMetaverse.Packets; | ||
31 | 32 | ||
32 | namespace OpenSim.Region.ClientStack.LindenUDP | 33 | namespace 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 | } |