diff options
Diffstat (limited to 'OpenSim/Region/ClientStack/LindenUDP')
4 files changed, 269 insertions, 173 deletions
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs index db0c3b8..7eb829e 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs | |||
@@ -220,6 +220,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
220 | public event FriendActionDelegate OnApproveFriendRequest; | 220 | public event FriendActionDelegate OnApproveFriendRequest; |
221 | public event FriendActionDelegate OnDenyFriendRequest; | 221 | public event FriendActionDelegate OnDenyFriendRequest; |
222 | public event FriendshipTermination OnTerminateFriendship; | 222 | public event FriendshipTermination OnTerminateFriendship; |
223 | public event GrantUserFriendRights OnGrantUserRights; | ||
223 | public event MoneyTransferRequest OnMoneyTransferRequest; | 224 | public event MoneyTransferRequest OnMoneyTransferRequest; |
224 | public event EconomyDataRequest OnEconomyDataRequest; | 225 | public event EconomyDataRequest OnEconomyDataRequest; |
225 | public event MoneyBalanceRequest OnMoneyBalanceRequest; | 226 | public event MoneyBalanceRequest OnMoneyBalanceRequest; |
@@ -1251,7 +1252,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1251 | /// <param name="fetchFolders">Do we need to send folder information?</param> | 1252 | /// <param name="fetchFolders">Do we need to send folder information?</param> |
1252 | /// <param name="fetchItems">Do we need to send item information?</param> | 1253 | /// <param name="fetchItems">Do we need to send item information?</param> |
1253 | public void SendInventoryFolderDetails(UUID ownerID, UUID folderID, List<InventoryItemBase> items, | 1254 | public void SendInventoryFolderDetails(UUID ownerID, UUID folderID, List<InventoryItemBase> items, |
1254 | List<InventoryFolderBase> folders, | 1255 | List<InventoryFolderBase> folders, int version, |
1255 | bool fetchFolders, bool fetchItems) | 1256 | bool fetchFolders, bool fetchItems) |
1256 | { | 1257 | { |
1257 | // An inventory descendents packet consists of a single agent section and an inventory details | 1258 | // An inventory descendents packet consists of a single agent section and an inventory details |
@@ -1264,174 +1265,107 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1264 | // | 1265 | // |
1265 | // for one example of this kind of thing. In fact, the Linden servers appear to only send about | 1266 | // for one example of this kind of thing. In fact, the Linden servers appear to only send about |
1266 | // 6 to 7 items at a time, so let's stick with 6 | 1267 | // 6 to 7 items at a time, so let's stick with 6 |
1267 | int MAX_ITEMS_PER_PACKET = 6; | 1268 | int MAX_ITEMS_PER_PACKET = 5; |
1268 | 1269 | int MAX_FOLDERS_PER_PACKET = 6; | |
1269 | //Ckrinke This variable is not used, so comment out to remove the warning from the compiler (3-21-08) | ||
1270 | //Ckrinke uint FULL_MASK_PERMISSIONS = 2147483647; | ||
1271 | 1270 | ||
1271 | int totalItems = fetchItems ? items.Count : 0; | ||
1272 | int totalFolders = fetchFolders ? folders.Count : 0; | ||
1272 | int itemsSent = 0; | 1273 | int itemsSent = 0; |
1273 | if (fetchItems) | 1274 | int foldersSent = 0; |
1274 | { | 1275 | int foldersToSend = 0; |
1275 | InventoryDescendentsPacket descend = CreateInventoryDescendentsPacket(ownerID, folderID); | 1276 | int itemsToSend = 0; |
1276 | 1277 | ||
1277 | if (items.Count < MAX_ITEMS_PER_PACKET) | 1278 | InventoryDescendentsPacket currentPacket = null; |
1278 | { | ||
1279 | descend.ItemData = new InventoryDescendentsPacket.ItemDataBlock[items.Count]; | ||
1280 | } | ||
1281 | else | ||
1282 | { | ||
1283 | descend.ItemData = new InventoryDescendentsPacket.ItemDataBlock[MAX_ITEMS_PER_PACKET]; | ||
1284 | } | ||
1285 | |||
1286 | // Descendents must contain the *total* number of descendents (plus folders, whether we | ||
1287 | // fetch them or not), not the number of entries we send in this packet. For consistency, | ||
1288 | // I'll use it for folder-requests, too, although I wasn't able to get one with | ||
1289 | // FetchFolders = true. | ||
1290 | // TODO this should be checked with FetchFolders = true | ||
1291 | descend.AgentData.Descendents = items.Count + folders.Count; | ||
1292 | 1279 | ||
1293 | int count = 0; | 1280 | // Handle empty folders |
1294 | int i = 0; | 1281 | // |
1295 | foreach (InventoryItemBase item in items) | 1282 | if (totalItems == 0 && totalFolders == 0) |
1283 | currentPacket = CreateInventoryDescendentsPacket(ownerID, folderID, version, items.Count + folders.Count, 0, 0); | ||
1284 | |||
1285 | // To preserve SL compatibility, we will NOT combine folders and items in one packet | ||
1286 | // | ||
1287 | while(itemsSent < totalItems || foldersSent < totalFolders) | ||
1288 | { | ||
1289 | if (currentPacket == null) // Start a new packet | ||
1296 | { | 1290 | { |
1297 | descend.ItemData[i] = new InventoryDescendentsPacket.ItemDataBlock(); | 1291 | foldersToSend = totalFolders - foldersSent; |
1298 | descend.ItemData[i].ItemID = item.ID; | 1292 | if (foldersToSend > MAX_FOLDERS_PER_PACKET) |
1299 | descend.ItemData[i].AssetID = item.AssetID; | 1293 | foldersToSend = MAX_FOLDERS_PER_PACKET; |
1300 | descend.ItemData[i].CreatorID = item.CreatorIdAsUuid; | 1294 | |
1301 | descend.ItemData[i].BaseMask = item.BasePermissions; | 1295 | if (foldersToSend == 0) |
1302 | descend.ItemData[i].Description = Util.StringToBytes256(item.Description); | 1296 | { |
1303 | descend.ItemData[i].EveryoneMask = item.EveryOnePermissions; | 1297 | itemsToSend = totalItems - itemsSent; |
1304 | descend.ItemData[i].OwnerMask = item.CurrentPermissions; | 1298 | if (itemsToSend > MAX_ITEMS_PER_PACKET) |
1305 | descend.ItemData[i].FolderID = item.Folder; | 1299 | itemsToSend = MAX_ITEMS_PER_PACKET; |
1306 | descend.ItemData[i].InvType = (sbyte)item.InvType; | ||
1307 | descend.ItemData[i].Name = Util.StringToBytes256(item.Name); | ||
1308 | descend.ItemData[i].NextOwnerMask = item.NextPermissions; | ||
1309 | descend.ItemData[i].OwnerID = item.Owner; | ||
1310 | descend.ItemData[i].Type = (sbyte)item.AssetType; | ||
1311 | |||
1312 | descend.ItemData[i].GroupID = item.GroupID; | ||
1313 | descend.ItemData[i].GroupOwned = item.GroupOwned; | ||
1314 | descend.ItemData[i].GroupMask = item.GroupPermissions; | ||
1315 | descend.ItemData[i].CreationDate = item.CreationDate; | ||
1316 | descend.ItemData[i].SalePrice = item.SalePrice; | ||
1317 | descend.ItemData[i].SaleType = item.SaleType; | ||
1318 | descend.ItemData[i].Flags = item.Flags; | ||
1319 | |||
1320 | descend.ItemData[i].CRC = | ||
1321 | Helpers.InventoryCRC(descend.ItemData[i].CreationDate, descend.ItemData[i].SaleType, | ||
1322 | descend.ItemData[i].InvType, descend.ItemData[i].Type, | ||
1323 | descend.ItemData[i].AssetID, descend.ItemData[i].GroupID, | ||
1324 | descend.ItemData[i].SalePrice, | ||
1325 | descend.ItemData[i].OwnerID, descend.ItemData[i].CreatorID, | ||
1326 | descend.ItemData[i].ItemID, descend.ItemData[i].FolderID, | ||
1327 | descend.ItemData[i].EveryoneMask, | ||
1328 | descend.ItemData[i].Flags, descend.ItemData[i].OwnerMask, | ||
1329 | descend.ItemData[i].GroupMask, item.CurrentPermissions); | ||
1330 | |||
1331 | i++; | ||
1332 | count++; | ||
1333 | itemsSent++; | ||
1334 | if (i == MAX_ITEMS_PER_PACKET) | ||
1335 | { | ||
1336 | descend.Header.Zerocoded = true; | ||
1337 | AddNullFolderBlockToDecendentsPacket(ref descend); | ||
1338 | OutPacket(descend, ThrottleOutPacketType.Asset); | ||
1339 | |||
1340 | if ((items.Count - count) > 0) | ||
1341 | { | ||
1342 | descend = CreateInventoryDescendentsPacket(ownerID, folderID); | ||
1343 | if ((items.Count - count) < MAX_ITEMS_PER_PACKET) | ||
1344 | { | ||
1345 | descend.ItemData = new InventoryDescendentsPacket.ItemDataBlock[items.Count - count]; | ||
1346 | } | ||
1347 | else | ||
1348 | { | ||
1349 | descend.ItemData = new InventoryDescendentsPacket.ItemDataBlock[MAX_ITEMS_PER_PACKET]; | ||
1350 | } | ||
1351 | descend.AgentData.Descendents = items.Count + folders.Count; | ||
1352 | i = 0; | ||
1353 | } | ||
1354 | } | 1300 | } |
1355 | } | ||
1356 | 1301 | ||
1357 | if (0 < i && i < MAX_ITEMS_PER_PACKET) | 1302 | currentPacket = CreateInventoryDescendentsPacket(ownerID, folderID, version, items.Count + folders.Count, foldersToSend, itemsToSend); |
1358 | { | ||
1359 | AddNullFolderBlockToDecendentsPacket(ref descend); | ||
1360 | OutPacket(descend, ThrottleOutPacketType.Asset); | ||
1361 | } | 1303 | } |
1362 | } | ||
1363 | 1304 | ||
1364 | //send subfolders | 1305 | if (foldersToSend-- > 0) |
1365 | if (fetchFolders) | 1306 | currentPacket.FolderData[foldersSent % MAX_FOLDERS_PER_PACKET] = CreateFolderDataBlock(folders[foldersSent++]); |
1366 | { | 1307 | else if(itemsToSend-- > 0) |
1367 | InventoryDescendentsPacket descend = CreateInventoryDescendentsPacket(ownerID, folderID); | 1308 | currentPacket.ItemData[itemsSent % MAX_ITEMS_PER_PACKET] = CreateItemDataBlock(items[itemsSent++]); |
1368 | |||
1369 | if (folders.Count < MAX_ITEMS_PER_PACKET) | ||
1370 | { | ||
1371 | descend.FolderData = new InventoryDescendentsPacket.FolderDataBlock[folders.Count]; | ||
1372 | } | ||
1373 | else | 1309 | else |
1374 | { | 1310 | { |
1375 | descend.FolderData = new InventoryDescendentsPacket.FolderDataBlock[MAX_ITEMS_PER_PACKET]; | 1311 | OutPacket(currentPacket, ThrottleOutPacketType.Asset, false); |
1312 | currentPacket = null; | ||
1376 | } | 1313 | } |
1377 | 1314 | ||
1378 | // Not sure if this scenario ever actually occurs, but nonetheless we include the items | 1315 | } |
1379 | // count even if we're not sending item data for the same reasons as above. | ||
1380 | descend.AgentData.Descendents = items.Count + folders.Count; | ||
1381 | 1316 | ||
1382 | int i = 0; | 1317 | if (currentPacket != null) |
1383 | int count = 0; | 1318 | OutPacket(currentPacket, ThrottleOutPacketType.Asset, false); |
1384 | foreach (InventoryFolderBase folder in folders) | 1319 | } |
1385 | { | ||
1386 | descend.FolderData[i] = new InventoryDescendentsPacket.FolderDataBlock(); | ||
1387 | descend.FolderData[i].FolderID = folder.ID; | ||
1388 | descend.FolderData[i].Name = Util.StringToBytes256(folder.Name); | ||
1389 | descend.FolderData[i].ParentID = folder.ParentID; | ||
1390 | descend.FolderData[i].Type = (sbyte)folder.Type; | ||
1391 | 1320 | ||
1392 | i++; | 1321 | private InventoryDescendentsPacket.FolderDataBlock CreateFolderDataBlock(InventoryFolderBase folder) |
1393 | count++; | 1322 | { |
1394 | itemsSent++; | 1323 | InventoryDescendentsPacket.FolderDataBlock newBlock = new InventoryDescendentsPacket.FolderDataBlock(); |
1395 | if (i == MAX_ITEMS_PER_PACKET) | 1324 | newBlock.FolderID = folder.ID; |
1396 | { | 1325 | newBlock.Name = Util.StringToBytes256(folder.Name); |
1397 | AddNullItemBlockToDescendentsPacket(ref descend); | 1326 | newBlock.ParentID = folder.ParentID; |
1398 | OutPacket(descend, ThrottleOutPacketType.Asset); | 1327 | newBlock.Type = (sbyte)folder.Type; |
1399 | 1328 | ||
1400 | if ((folders.Count - count) > 0) | 1329 | return newBlock; |
1401 | { | 1330 | } |
1402 | descend = CreateInventoryDescendentsPacket(ownerID, folderID); | ||
1403 | if ((folders.Count - count) < MAX_ITEMS_PER_PACKET) | ||
1404 | { | ||
1405 | descend.FolderData = | ||
1406 | new InventoryDescendentsPacket.FolderDataBlock[folders.Count - count]; | ||
1407 | } | ||
1408 | else | ||
1409 | { | ||
1410 | descend.FolderData = | ||
1411 | new InventoryDescendentsPacket.FolderDataBlock[MAX_ITEMS_PER_PACKET]; | ||
1412 | } | ||
1413 | descend.AgentData.Descendents = items.Count + folders.Count; | ||
1414 | i = 0; | ||
1415 | } | ||
1416 | } | ||
1417 | } | ||
1418 | 1331 | ||
1419 | if (0 < i && i < MAX_ITEMS_PER_PACKET) | 1332 | private InventoryDescendentsPacket.ItemDataBlock CreateItemDataBlock(InventoryItemBase item) |
1420 | { | 1333 | { |
1421 | AddNullItemBlockToDescendentsPacket(ref descend); | 1334 | InventoryDescendentsPacket.ItemDataBlock newBlock = new InventoryDescendentsPacket.ItemDataBlock(); |
1422 | OutPacket(descend, ThrottleOutPacketType.Asset); | 1335 | newBlock.ItemID = item.ID; |
1423 | } | 1336 | newBlock.AssetID = item.AssetID; |
1424 | } | 1337 | newBlock.CreatorID = item.CreatorIdAsUuid; |
1338 | newBlock.BaseMask = item.BasePermissions; | ||
1339 | newBlock.Description = Util.StringToBytes256(item.Description); | ||
1340 | newBlock.EveryoneMask = item.EveryOnePermissions; | ||
1341 | newBlock.OwnerMask = item.CurrentPermissions; | ||
1342 | newBlock.FolderID = item.Folder; | ||
1343 | newBlock.InvType = (sbyte)item.InvType; | ||
1344 | newBlock.Name = Util.StringToBytes256(item.Name); | ||
1345 | newBlock.NextOwnerMask = item.NextPermissions; | ||
1346 | newBlock.OwnerID = item.Owner; | ||
1347 | newBlock.Type = (sbyte)item.AssetType; | ||
1425 | 1348 | ||
1426 | if (itemsSent == 0) | 1349 | newBlock.GroupID = item.GroupID; |
1427 | { | 1350 | newBlock.GroupOwned = item.GroupOwned; |
1428 | // no items found. | 1351 | newBlock.GroupMask = item.GroupPermissions; |
1429 | InventoryDescendentsPacket descend = CreateInventoryDescendentsPacket(ownerID, folderID); | 1352 | newBlock.CreationDate = item.CreationDate; |
1430 | descend.AgentData.Descendents = 0; | 1353 | newBlock.SalePrice = item.SalePrice; |
1431 | AddNullItemBlockToDescendentsPacket(ref descend); | 1354 | newBlock.SaleType = item.SaleType; |
1432 | AddNullFolderBlockToDecendentsPacket(ref descend); | 1355 | newBlock.Flags = item.Flags; |
1433 | OutPacket(descend, ThrottleOutPacketType.Asset); | 1356 | |
1434 | } | 1357 | newBlock.CRC = |
1358 | Helpers.InventoryCRC(newBlock.CreationDate, newBlock.SaleType, | ||
1359 | newBlock.InvType, newBlock.Type, | ||
1360 | newBlock.AssetID, newBlock.GroupID, | ||
1361 | newBlock.SalePrice, | ||
1362 | newBlock.OwnerID, newBlock.CreatorID, | ||
1363 | newBlock.ItemID, newBlock.FolderID, | ||
1364 | newBlock.EveryoneMask, | ||
1365 | newBlock.Flags, newBlock.OwnerMask, | ||
1366 | newBlock.GroupMask, newBlock.NextOwnerMask); | ||
1367 | |||
1368 | return newBlock; | ||
1435 | } | 1369 | } |
1436 | 1370 | ||
1437 | private void AddNullFolderBlockToDecendentsPacket(ref InventoryDescendentsPacket packet) | 1371 | private void AddNullFolderBlockToDecendentsPacket(ref InventoryDescendentsPacket packet) |
@@ -1473,14 +1407,25 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1473 | // No need to add CRC | 1407 | // No need to add CRC |
1474 | } | 1408 | } |
1475 | 1409 | ||
1476 | private InventoryDescendentsPacket CreateInventoryDescendentsPacket(UUID ownerID, UUID folderID) | 1410 | private InventoryDescendentsPacket CreateInventoryDescendentsPacket(UUID ownerID, UUID folderID, int version, int descendents, int folders, int items) |
1477 | { | 1411 | { |
1478 | InventoryDescendentsPacket descend = (InventoryDescendentsPacket)PacketPool.Instance.GetPacket(PacketType.InventoryDescendents); | 1412 | InventoryDescendentsPacket descend = (InventoryDescendentsPacket)PacketPool.Instance.GetPacket(PacketType.InventoryDescendents); |
1479 | descend.Header.Zerocoded = true; | 1413 | descend.Header.Zerocoded = true; |
1480 | descend.AgentData.AgentID = AgentId; | 1414 | descend.AgentData.AgentID = AgentId; |
1481 | descend.AgentData.OwnerID = ownerID; | 1415 | descend.AgentData.OwnerID = ownerID; |
1482 | descend.AgentData.FolderID = folderID; | 1416 | descend.AgentData.FolderID = folderID; |
1483 | descend.AgentData.Version = 1; | 1417 | descend.AgentData.Version = version; |
1418 | descend.AgentData.Descendents = descendents; | ||
1419 | |||
1420 | if (folders > 0) | ||
1421 | descend.FolderData = new InventoryDescendentsPacket.FolderDataBlock[folders]; | ||
1422 | else | ||
1423 | AddNullFolderBlockToDecendentsPacket(ref descend); | ||
1424 | |||
1425 | if (items > 0) | ||
1426 | descend.ItemData = new InventoryDescendentsPacket.ItemDataBlock[items]; | ||
1427 | else | ||
1428 | AddNullItemBlockToDescendentsPacket(ref descend); | ||
1484 | 1429 | ||
1485 | return descend; | 1430 | return descend; |
1486 | } | 1431 | } |
@@ -3251,12 +3196,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
3251 | if (!IsActive) return; // We don't need to update inactive clients. | 3196 | if (!IsActive) return; // We don't need to update inactive clients. |
3252 | 3197 | ||
3253 | CoarseLocationUpdatePacket loc = (CoarseLocationUpdatePacket)PacketPool.Instance.GetPacket(PacketType.CoarseLocationUpdate); | 3198 | CoarseLocationUpdatePacket loc = (CoarseLocationUpdatePacket)PacketPool.Instance.GetPacket(PacketType.CoarseLocationUpdate); |
3254 | // TODO: don't create new blocks if recycling an old packet | 3199 | loc.Header.Reliable = false; |
3255 | int total = CoarseLocations.Count; | 3200 | |
3256 | CoarseLocationUpdatePacket.IndexBlock ib = | 3201 | // Each packet can only hold around 62 avatar positions and the client clears the mini-map each time |
3257 | new CoarseLocationUpdatePacket.IndexBlock(); | 3202 | // a CoarseLocationUpdate packet is received. Oh well. |
3203 | int total = Math.Min(CoarseLocations.Count, 60); | ||
3204 | |||
3205 | CoarseLocationUpdatePacket.IndexBlock ib = new CoarseLocationUpdatePacket.IndexBlock(); | ||
3206 | |||
3258 | loc.Location = new CoarseLocationUpdatePacket.LocationBlock[total]; | 3207 | loc.Location = new CoarseLocationUpdatePacket.LocationBlock[total]; |
3259 | loc.AgentData = new CoarseLocationUpdatePacket.AgentDataBlock[total]; | 3208 | loc.AgentData = new CoarseLocationUpdatePacket.AgentDataBlock[total]; |
3209 | |||
3260 | int selfindex = -1; | 3210 | int selfindex = -1; |
3261 | for (int i = 0; i < total; i++) | 3211 | for (int i = 0; i < total; i++) |
3262 | { | 3212 | { |
@@ -3266,18 +3216,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
3266 | lb.X = (byte)CoarseLocations[i].X; | 3216 | lb.X = (byte)CoarseLocations[i].X; |
3267 | lb.Y = (byte)CoarseLocations[i].Y; | 3217 | lb.Y = (byte)CoarseLocations[i].Y; |
3268 | 3218 | ||
3269 | lb.Z = CoarseLocations[i].Z > 1024 ? (byte)0 : (byte)(CoarseLocations[i].Z * 0.25); | 3219 | lb.Z = CoarseLocations[i].Z > 1024 ? (byte)0 : (byte)(CoarseLocations[i].Z * 0.25f); |
3270 | loc.Location[i] = lb; | 3220 | loc.Location[i] = lb; |
3271 | loc.AgentData[i] = new CoarseLocationUpdatePacket.AgentDataBlock(); | 3221 | loc.AgentData[i] = new CoarseLocationUpdatePacket.AgentDataBlock(); |
3272 | loc.AgentData[i].AgentID = users[i]; | 3222 | loc.AgentData[i].AgentID = users[i]; |
3273 | if (users[i] == AgentId) | 3223 | if (users[i] == AgentId) |
3274 | selfindex = i; | 3224 | selfindex = i; |
3275 | } | 3225 | } |
3226 | |||
3276 | ib.You = (short)selfindex; | 3227 | ib.You = (short)selfindex; |
3277 | ib.Prey = -1; | 3228 | ib.Prey = -1; |
3278 | loc.Index = ib; | 3229 | loc.Index = ib; |
3279 | loc.Header.Reliable = false; | ||
3280 | loc.Header.Zerocoded = true; | ||
3281 | 3230 | ||
3282 | OutPacket(loc, ThrottleOutPacketType.Task); | 3231 | OutPacket(loc, ThrottleOutPacketType.Task); |
3283 | } | 3232 | } |
@@ -4088,11 +4037,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
4088 | 4037 | ||
4089 | protected ImprovedTerseObjectUpdatePacket.ObjectDataBlock CreateImprovedTerseBlock(SendPrimitiveTerseData data) | 4038 | protected ImprovedTerseObjectUpdatePacket.ObjectDataBlock CreateImprovedTerseBlock(SendPrimitiveTerseData data) |
4090 | { | 4039 | { |
4091 | return CreateImprovedTerseBlock(false, data.LocalID, data.State, Vector4.Zero, data.Position, data.Velocity, | 4040 | return CreateImprovedTerseBlock(false, data.LocalID, data.AttachPoint, Vector4.Zero, data.Position, data.Velocity, |
4092 | data.Acceleration, data.Rotation, data.AngularVelocity, data.TextureEntry); | 4041 | data.Acceleration, data.Rotation, data.AngularVelocity, data.TextureEntry); |
4093 | } | 4042 | } |
4094 | 4043 | ||
4095 | protected ImprovedTerseObjectUpdatePacket.ObjectDataBlock CreateImprovedTerseBlock(bool avatar, uint localID, byte state, | 4044 | protected ImprovedTerseObjectUpdatePacket.ObjectDataBlock CreateImprovedTerseBlock(bool avatar, uint localID, int attachPoint, |
4096 | Vector4 collisionPlane, Vector3 position, Vector3 velocity, Vector3 acceleration, Quaternion rotation, | 4045 | Vector4 collisionPlane, Vector3 position, Vector3 velocity, Vector3 acceleration, Quaternion rotation, |
4097 | Vector3 angularVelocity, byte[] textureEntry) | 4046 | Vector3 angularVelocity, byte[] textureEntry) |
4098 | { | 4047 | { |
@@ -4104,7 +4053,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
4104 | pos += 4; | 4053 | pos += 4; |
4105 | 4054 | ||
4106 | // Avatar/CollisionPlane | 4055 | // Avatar/CollisionPlane |
4107 | data[pos++] = state; | 4056 | data[pos++] = (byte)((attachPoint % 16) * 16 + (attachPoint / 16)); ; |
4108 | if (avatar) | 4057 | if (avatar) |
4109 | { | 4058 | { |
4110 | data[pos++] = 1; | 4059 | data[pos++] = 1; |
@@ -4960,9 +4909,26 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
4960 | /// <param name="throttlePacketType">Throttling category for the packet</param> | 4909 | /// <param name="throttlePacketType">Throttling category for the packet</param> |
4961 | protected void OutPacket(Packet packet, ThrottleOutPacketType throttlePacketType) | 4910 | protected void OutPacket(Packet packet, ThrottleOutPacketType throttlePacketType) |
4962 | { | 4911 | { |
4912 | #region BinaryStats | ||
4913 | LLUDPServer.LogPacketHeader(false, m_circuitCode, 0, packet.Type, (ushort)packet.Length); | ||
4914 | #endregion BinaryStats | ||
4915 | |||
4963 | m_udpServer.SendPacket(m_udpClient, packet, throttlePacketType, true); | 4916 | m_udpServer.SendPacket(m_udpClient, packet, throttlePacketType, true); |
4964 | } | 4917 | } |
4965 | 4918 | ||
4919 | /// <summary> | ||
4920 | /// This is the starting point for sending a simulator packet out to the client | ||
4921 | /// </summary> | ||
4922 | /// <param name="packet">Packet to send</param> | ||
4923 | /// <param name="throttlePacketType">Throttling category for the packet</param> | ||
4924 | /// <param name="doAutomaticSplitting">True to automatically split oversized | ||
4925 | /// packets (the default), or false to disable splitting if the calling code | ||
4926 | /// handles splitting manually</param> | ||
4927 | protected void OutPacket(Packet packet, ThrottleOutPacketType throttlePacketType, bool doAutomaticSplitting) | ||
4928 | { | ||
4929 | m_udpServer.SendPacket(m_udpClient, packet, throttlePacketType, doAutomaticSplitting); | ||
4930 | } | ||
4931 | |||
4966 | public bool AddMoney(int debit) | 4932 | public bool AddMoney(int debit) |
4967 | { | 4933 | { |
4968 | if (m_moneyBalance + debit >= 0) | 4934 | if (m_moneyBalance + debit >= 0) |
@@ -9762,7 +9728,26 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
9762 | Utils.BytesToString(avatarInterestUpdate.PropertiesData.SkillsText), | 9728 | Utils.BytesToString(avatarInterestUpdate.PropertiesData.SkillsText), |
9763 | Utils.BytesToString(avatarInterestUpdate.PropertiesData.LanguagesText)); | 9729 | Utils.BytesToString(avatarInterestUpdate.PropertiesData.LanguagesText)); |
9764 | break; | 9730 | break; |
9765 | 9731 | ||
9732 | case PacketType.GrantUserRights: | ||
9733 | GrantUserRightsPacket GrantUserRights = | ||
9734 | (GrantUserRightsPacket)Pack; | ||
9735 | #region Packet Session and User Check | ||
9736 | if (m_checkPackets) | ||
9737 | { | ||
9738 | if (GrantUserRights.AgentData.SessionID != SessionId || | ||
9739 | GrantUserRights.AgentData.AgentID != AgentId) | ||
9740 | break; | ||
9741 | } | ||
9742 | #endregion | ||
9743 | GrantUserFriendRights GrantUserRightsHandler = OnGrantUserRights; | ||
9744 | if (GrantUserRightsHandler != null) | ||
9745 | GrantUserRightsHandler(this, | ||
9746 | GrantUserRights.AgentData.AgentID, | ||
9747 | GrantUserRights.Rights[0].AgentRelated, | ||
9748 | GrantUserRights.Rights[0].RelatedRights); | ||
9749 | break; | ||
9750 | |||
9766 | case PacketType.PlacesQuery: | 9751 | case PacketType.PlacesQuery: |
9767 | PlacesQueryPacket placesQueryPacket = | 9752 | PlacesQueryPacket placesQueryPacket = |
9768 | (PlacesQueryPacket)Pack; | 9753 | (PlacesQueryPacket)Pack; |
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/LLUDPServer.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs index 93946ae..c773c05 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; |
@@ -204,6 +205,31 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
204 | TextureSendLimit = 20; | 205 | TextureSendLimit = 20; |
205 | } | 206 | } |
206 | 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 | |||
207 | m_throttle = new TokenBucket(null, sceneThrottleBps, sceneThrottleBps); | 233 | m_throttle = new TokenBucket(null, sceneThrottleBps, sceneThrottleBps); |
208 | m_throttleRates = new ThrottleRates(configSource); | 234 | m_throttleRates = new ThrottleRates(configSource); |
209 | } | 235 | } |
@@ -359,9 +385,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
359 | } | 385 | } |
360 | else | 386 | else |
361 | { | 387 | { |
362 | m_log.Error("[LLUDPSERVER]: Packet exceeded buffer size! This could be an indication of packet assembly not obeying the MTU. Type=" + | 388 | bufferSize = dataLength; |
363 | type + ", DataLength=" + dataLength + ", BufferLength=" + buffer.Data.Length + ". Dropping packet"); | 389 | buffer = new UDPPacketBuffer(udpClient.RemoteEndPoint, bufferSize); |
364 | 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); | ||
365 | } | 394 | } |
366 | } | 395 | } |
367 | 396 | ||
@@ -676,6 +705,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
676 | 705 | ||
677 | #endregion Incoming Packet Accounting | 706 | #endregion Incoming Packet Accounting |
678 | 707 | ||
708 | #region BinaryStats | ||
709 | LogPacketHeader(true, udpClient.CircuitCode, 0, packet.Type, (ushort)packet.Length); | ||
710 | #endregion BinaryStats | ||
711 | |||
679 | #region Ping Check Handling | 712 | #region Ping Check Handling |
680 | 713 | ||
681 | if (packet.Type == PacketType.StartPingCheck) | 714 | if (packet.Type == PacketType.StartPingCheck) |
@@ -697,6 +730,87 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
697 | packetInbox.Enqueue(new IncomingPacket(udpClient, packet)); | 730 | packetInbox.Enqueue(new IncomingPacket(udpClient, packet)); |
698 | } | 731 | } |
699 | 732 | ||
733 | #region BinaryStats | ||
734 | |||
735 | public class PacketLogger | ||
736 | { | ||
737 | public DateTime StartTime; | ||
738 | public string Path = null; | ||
739 | public System.IO.BinaryWriter Log = null; | ||
740 | } | ||
741 | |||
742 | public static PacketLogger PacketLog; | ||
743 | |||
744 | protected static bool m_shouldCollectStats = false; | ||
745 | // Number of seconds to log for | ||
746 | static TimeSpan binStatsMaxFilesize = TimeSpan.FromSeconds(300); | ||
747 | static object binStatsLogLock = new object(); | ||
748 | static string binStatsDir = ""; | ||
749 | |||
750 | public static void LogPacketHeader(bool incoming, uint circuit, byte flags, PacketType packetType, ushort size) | ||
751 | { | ||
752 | if (!m_shouldCollectStats) return; | ||
753 | |||
754 | // Binary logging format is TTTTTTTTCCCCFPPPSS, T=Time, C=Circuit, F=Flags, P=PacketType, S=size | ||
755 | |||
756 | // Put the incoming bit into the least significant bit of the flags byte | ||
757 | if (incoming) | ||
758 | flags |= 0x01; | ||
759 | else | ||
760 | flags &= 0xFE; | ||
761 | |||
762 | // Put the flags byte into the most significant bits of the type integer | ||
763 | uint type = (uint)packetType; | ||
764 | type |= (uint)flags << 24; | ||
765 | |||
766 | // m_log.Debug("1 LogPacketHeader(): Outside lock"); | ||
767 | lock (binStatsLogLock) | ||
768 | { | ||
769 | DateTime now = DateTime.Now; | ||
770 | |||
771 | // m_log.Debug("2 LogPacketHeader(): Inside lock. now is " + now.Ticks); | ||
772 | try | ||
773 | { | ||
774 | if (PacketLog == null || (now > PacketLog.StartTime + binStatsMaxFilesize)) | ||
775 | { | ||
776 | if (PacketLog != null && PacketLog.Log != null) | ||
777 | { | ||
778 | PacketLog.Log.Close(); | ||
779 | } | ||
780 | |||
781 | // First log file or time has expired, start writing to a new log file | ||
782 | PacketLog = new PacketLogger(); | ||
783 | PacketLog.StartTime = now; | ||
784 | PacketLog.Path = (binStatsDir.Length > 0 ? binStatsDir + System.IO.Path.DirectorySeparatorChar.ToString() : "") | ||
785 | + String.Format("packets-{0}.log", now.ToString("yyyyMMddHHmmss")); | ||
786 | PacketLog.Log = new BinaryWriter(File.Open(PacketLog.Path, FileMode.Append, FileAccess.Write)); | ||
787 | } | ||
788 | |||
789 | // Serialize the data | ||
790 | byte[] output = new byte[18]; | ||
791 | Buffer.BlockCopy(BitConverter.GetBytes(now.Ticks), 0, output, 0, 8); | ||
792 | Buffer.BlockCopy(BitConverter.GetBytes(circuit), 0, output, 8, 4); | ||
793 | Buffer.BlockCopy(BitConverter.GetBytes(type), 0, output, 12, 4); | ||
794 | Buffer.BlockCopy(BitConverter.GetBytes(size), 0, output, 16, 2); | ||
795 | |||
796 | // Write the serialized data to disk | ||
797 | if (PacketLog != null && PacketLog.Log != null) | ||
798 | PacketLog.Log.Write(output); | ||
799 | } | ||
800 | catch (Exception ex) | ||
801 | { | ||
802 | m_log.Error("Packet statistics gathering failed: " + ex.Message, ex); | ||
803 | if (PacketLog.Log != null) | ||
804 | { | ||
805 | PacketLog.Log.Close(); | ||
806 | } | ||
807 | PacketLog = null; | ||
808 | } | ||
809 | } | ||
810 | } | ||
811 | |||
812 | #endregion BinaryStats | ||
813 | |||
700 | private void HandleUseCircuitCode(object o) | 814 | private void HandleUseCircuitCode(object o) |
701 | { | 815 | { |
702 | object[] array = (object[])o; | 816 | object[] array = (object[])o; |
diff --git a/OpenSim/Region/ClientStack/LindenUDP/OpenSimUDPBase.cs b/OpenSim/Region/ClientStack/LindenUDP/OpenSimUDPBase.cs index 552cc4a..d2779ba 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/OpenSimUDPBase.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/OpenSimUDPBase.cs | |||
@@ -270,8 +270,8 @@ namespace OpenMetaverse | |||
270 | { | 270 | { |
271 | try | 271 | try |
272 | { | 272 | { |
273 | UDPPacketBuffer buf = (UDPPacketBuffer)result.AsyncState; | 273 | // UDPPacketBuffer buf = (UDPPacketBuffer)result.AsyncState; |
274 | int bytesSent = m_udpSocket.EndSendTo(result); | 274 | m_udpSocket.EndSendTo(result); |
275 | } | 275 | } |
276 | catch (SocketException) { } | 276 | catch (SocketException) { } |
277 | catch (ObjectDisposedException) { } | 277 | catch (ObjectDisposedException) { } |