aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ClientStack/Linden/UDP
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/ClientStack/Linden/UDP')
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs291
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs14
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/ThrottleRates.cs6
3 files changed, 224 insertions, 87 deletions
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
index 0ebccbe..9d39daa 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
@@ -34,11 +34,13 @@ using System.Text;
34using System.Threading; 34using System.Threading;
35using System.Timers; 35using System.Timers;
36using System.Xml; 36using System.Xml;
37
37using log4net; 38using log4net;
38using OpenMetaverse; 39using OpenMetaverse;
39using OpenMetaverse.Packets; 40using OpenMetaverse.Packets;
40using OpenMetaverse.Messages.Linden; 41using OpenMetaverse.Messages.Linden;
41using OpenMetaverse.StructuredData; 42using OpenMetaverse.StructuredData;
43
42using OpenSim.Framework; 44using OpenSim.Framework;
43using OpenSim.Framework.Client; 45using OpenSim.Framework.Client;
44using OpenSim.Framework.Monitoring; 46using OpenSim.Framework.Monitoring;
@@ -48,7 +50,6 @@ using OpenSim.Services.Interfaces;
48using Timer = System.Timers.Timer; 50using Timer = System.Timers.Timer;
49using AssetLandmark = OpenSim.Framework.AssetLandmark; 51using AssetLandmark = OpenSim.Framework.AssetLandmark;
50using RegionFlags = OpenMetaverse.RegionFlags; 52using RegionFlags = OpenMetaverse.RegionFlags;
51using Nini.Config;
52 53
53using System.IO; 54using System.IO;
54using PermissionMask = OpenSim.Framework.PermissionMask; 55using PermissionMask = OpenSim.Framework.PermissionMask;
@@ -307,6 +308,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
307 private const float m_sunPainDaHalfOrbitalCutoff = 4.712388980384689858f; 308 private const float m_sunPainDaHalfOrbitalCutoff = 4.712388980384689858f;
308 309
309 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 310 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
311 private static string LogHeader = "[LLCLIENTVIEW]";
310 protected static Dictionary<PacketType, PacketMethod> PacketHandlers = new Dictionary<PacketType, PacketMethod>(); //Global/static handlers for all clients 312 protected static Dictionary<PacketType, PacketMethod> PacketHandlers = new Dictionary<PacketType, PacketMethod>(); //Global/static handlers for all clients
311 313
312 /// <summary> 314 /// <summary>
@@ -323,6 +325,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
323 private readonly byte[] m_channelVersion = Utils.EmptyBytes; 325 private readonly byte[] m_channelVersion = Utils.EmptyBytes;
324 private readonly IGroupsModule m_GroupsModule; 326 private readonly IGroupsModule m_GroupsModule;
325 327
328 private int m_cachedTextureSerial;
326 private PriorityQueue m_entityUpdates; 329 private PriorityQueue m_entityUpdates;
327 private PriorityQueue m_entityProps; 330 private PriorityQueue m_entityProps;
328 private Prioritizer m_prioritizer; 331 private Prioritizer m_prioritizer;
@@ -447,7 +450,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
447 450
448// ~LLClientView() 451// ~LLClientView()
449// { 452// {
450// m_log.DebugFormat("[LLCLIENTVIEW]: Destructor called for {0}, circuit code {1}", Name, CircuitCode); 453// m_log.DebugFormat("{0} Destructor called for {1}, circuit code {2}", LogHeader, Name, CircuitCode);
451// } 454// }
452 455
453 /// <summary> 456 /// <summary>
@@ -513,9 +516,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
513 // there is some unidentified connection problem, not where we have issues due to deadlock 516 // there is some unidentified connection problem, not where we have issues due to deadlock
514 if (!IsActive && !force) 517 if (!IsActive && !force)
515 { 518 {
516 m_log.DebugFormat( 519 m_log.DebugFormat( "{0} Not attempting to close inactive client {1} in {2} since force flag is not set",
517 "[CLIENT]: Not attempting to close inactive client {0} in {1} since force flag is not set", 520 LogHeader, Name, m_scene.Name);
518 Name, m_scene.Name);
519 521
520 return; 522 return;
521 } 523 }
@@ -1153,7 +1155,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1153 /// <param name="map">heightmap</param> 1155 /// <param name="map">heightmap</param>
1154 public virtual void SendLayerData(float[] map) 1156 public virtual void SendLayerData(float[] map)
1155 { 1157 {
1156 Util.FireAndForget(DoSendLayerData, map); 1158 Util.FireAndForget(DoSendLayerData, m_scene.Heightmap.GetTerrainData());
1157 } 1159 }
1158 1160
1159 /// <summary> 1161 /// <summary>
@@ -1162,10 +1164,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1162 /// <param name="o"></param> 1164 /// <param name="o"></param>
1163 private void DoSendLayerData(object o) 1165 private void DoSendLayerData(object o)
1164 { 1166 {
1165 float[] map = LLHeightFieldMoronize((float[])o); 1167 TerrainData map = (TerrainData)o;
1166 1168
1167 try 1169 try
1168 { 1170 {
1171 // Send LayerData in typerwriter pattern
1169 //for (int y = 0; y < 16; y++) 1172 //for (int y = 0; y < 16; y++)
1170 //{ 1173 //{
1171 // for (int x = 0; x < 16; x++) 1174 // for (int x = 0; x < 16; x++)
@@ -1175,7 +1178,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1175 //} 1178 //}
1176 1179
1177 // Send LayerData in a spiral pattern. Fun! 1180 // Send LayerData in a spiral pattern. Fun!
1178 SendLayerTopRight(map, 0, 0, 15, 15); 1181 SendLayerTopRight(map, 0, 0, map.SizeX/Constants.TerrainPatchSize-1, map.SizeY/Constants.TerrainPatchSize-1);
1179 } 1182 }
1180 catch (Exception e) 1183 catch (Exception e)
1181 { 1184 {
@@ -1183,7 +1186,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1183 } 1186 }
1184 } 1187 }
1185 1188
1186 private void SendLayerTopRight(float[] map, int x1, int y1, int x2, int y2) 1189 private void SendLayerTopRight(TerrainData map, int x1, int y1, int x2, int y2)
1187 { 1190 {
1188 // Row 1191 // Row
1189 for (int i = x1; i <= x2; i++) 1192 for (int i = x1; i <= x2; i++)
@@ -1193,11 +1196,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1193 for (int j = y1 + 1; j <= y2; j++) 1196 for (int j = y1 + 1; j <= y2; j++)
1194 SendLayerData(x2, j, map); 1197 SendLayerData(x2, j, map);
1195 1198
1196 if (x2 - x1 > 0) 1199 if (x2 - x1 > 0 && y2 - y1 > 0)
1197 SendLayerBottomLeft(map, x1, y1 + 1, x2 - 1, y2); 1200 SendLayerBottomLeft(map, x1, y1 + 1, x2 - 1, y2);
1198 } 1201 }
1199 1202
1200 void SendLayerBottomLeft(float[] map, int x1, int y1, int x2, int y2) 1203 void SendLayerBottomLeft(TerrainData map, int x1, int y1, int x2, int y2)
1201 { 1204 {
1202 // Row in reverse 1205 // Row in reverse
1203 for (int i = x2; i >= x1; i--) 1206 for (int i = x2; i >= x1; i--)
@@ -1207,7 +1210,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1207 for (int j = y2 - 1; j >= y1; j--) 1210 for (int j = y2 - 1; j >= y1; j--)
1208 SendLayerData(x1, j, map); 1211 SendLayerData(x1, j, map);
1209 1212
1210 if (x2 - x1 > 0) 1213 if (x2 - x1 > 0 && y2 - y1 > 0)
1211 SendLayerTopRight(map, x1 + 1, y1, x2, y2 - 1); 1214 SendLayerTopRight(map, x1 + 1, y1, x2, y2 - 1);
1212 } 1215 }
1213 1216
@@ -1229,22 +1232,26 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1229 // OutPacket(layerpack, ThrottleOutPacketType.Land); 1232 // OutPacket(layerpack, ThrottleOutPacketType.Land);
1230 // } 1233 // }
1231 1234
1235 // Legacy form of invocation that passes around a bare data array.
1236 // Just ignore what was passed and use the real terrain info that is part of the scene.
1237 public void SendLayerData(int px, int py, float[] map)
1238 {
1239 SendLayerData(px, py, m_scene.Heightmap.GetTerrainData());
1240 }
1241
1232 /// <summary> 1242 /// <summary>
1233 /// Sends a specified patch to a client 1243 /// Sends a terrain packet for the point specified.
1244 /// This is a legacy call that has refarbed the terrain into a flat map of floats.
1245 /// We just use the terrain from the region we know about.
1234 /// </summary> 1246 /// </summary>
1235 /// <param name="px">Patch coordinate (x) 0..15</param> 1247 /// <param name="px">Patch coordinate (x) 0..15</param>
1236 /// <param name="py">Patch coordinate (y) 0..15</param> 1248 /// <param name="py">Patch coordinate (y) 0..15</param>
1237 /// <param name="map">heightmap</param> 1249 /// <param name="map">heightmap</param>
1238 public void SendLayerData(int px, int py, float[] map) 1250 public void SendLayerData(int px, int py, TerrainData terrData)
1239 { 1251 {
1240 try 1252 try
1241 { 1253 {
1242 int[] patches = new int[] { py * 16 + px }; 1254 LayerDataPacket layerpack = OpenSimTerrainCompressor.CreateLandPacket(terrData, px, py);
1243 float[] heightmap = (map.Length == 65536) ?
1244 map :
1245 LLHeightFieldMoronize(map);
1246
1247 LayerDataPacket layerpack = TerrainCompressor.CreateLandPacket(heightmap, patches);
1248 1255
1249 // When a user edits the terrain, so much data is sent, the data queues up fast and presents a sub optimal editing experience. 1256 // When a user edits the terrain, so much data is sent, the data queues up fast and presents a sub optimal editing experience.
1250 // To alleviate this issue, when the user edits the terrain, we start skipping the queues until they're done editing the terrain. 1257 // To alleviate this issue, when the user edits the terrain, we start skipping the queues until they're done editing the terrain.
@@ -1262,14 +1269,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1262 if (m_justEditedTerrain) 1269 if (m_justEditedTerrain)
1263 { 1270 {
1264 layerpack.Header.Reliable = false; 1271 layerpack.Header.Reliable = false;
1265 OutPacket(layerpack, 1272 OutPacket(layerpack, ThrottleOutPacketType.Unknown );
1266 ThrottleOutPacketType.Unknown );
1267 } 1273 }
1268 else 1274 else
1269 { 1275 {
1270 layerpack.Header.Reliable = true; 1276 layerpack.Header.Reliable = true;
1271 OutPacket(layerpack, 1277 OutPacket(layerpack, ThrottleOutPacketType.Land);
1272 ThrottleOutPacketType.Land);
1273 } 1278 }
1274 } 1279 }
1275 catch (Exception e) 1280 catch (Exception e)
@@ -1279,38 +1284,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1279 } 1284 }
1280 1285
1281 /// <summary> 1286 /// <summary>
1282 /// Munges heightfield into the LLUDP backed in restricted heightfield.
1283 /// </summary>
1284 /// <param name="map">float array in the base; Constants.RegionSize</param>
1285 /// <returns>float array in the base 256</returns>
1286 internal float[] LLHeightFieldMoronize(float[] map)
1287 {
1288 if (map.Length == 65536)
1289 return map;
1290 else
1291 {
1292 float[] returnmap = new float[65536];
1293
1294 if (map.Length < 65535)
1295 {
1296 // rebase the vector stride to 256
1297 for (int i = 0; i < Constants.RegionSize; i++)
1298 Array.Copy(map, i * (int)Constants.RegionSize, returnmap, i * 256, (int)Constants.RegionSize);
1299 }
1300 else
1301 {
1302 for (int i = 0; i < 256; i++)
1303 Array.Copy(map, i * (int)Constants.RegionSize, returnmap, i * 256, 256);
1304 }
1305
1306 //Array.Copy(map,0,returnmap,0,(map.Length < 65536)? map.Length : 65536);
1307
1308 return returnmap;
1309 }
1310
1311 }
1312
1313 /// <summary>
1314 /// Send the wind matrix to the client 1287 /// Send the wind matrix to the client
1315 /// </summary> 1288 /// </summary>
1316 /// <param name="windSpeeds">16x16 array of wind speeds</param> 1289 /// <param name="windSpeeds">16x16 array of wind speeds</param>
@@ -1350,7 +1323,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1350 } 1323 }
1351 } 1324 }
1352 1325
1353 LayerDataPacket layerpack = TerrainCompressor.CreateLayerDataPacket(patches, TerrainPatch.LayerType.Wind); 1326 byte layerType = (byte)TerrainPatch.LayerType.Wind;
1327 if (m_scene.RegionInfo.RegionSizeX > Constants.RegionSize || m_scene.RegionInfo.RegionSizeY > Constants.RegionSize)
1328 layerType = (byte)TerrainPatch.LayerType.WindExtended;
1329
1330 LayerDataPacket layerpack = OpenSimTerrainCompressor.CreateLayerDataPacket(patches, layerType,
1331 (int)m_scene.RegionInfo.RegionSizeX, (int)m_scene.RegionInfo.RegionSizeY);
1354 layerpack.Header.Zerocoded = true; 1332 layerpack.Header.Zerocoded = true;
1355 OutPacket(layerpack, ThrottleOutPacketType.Wind); 1333 OutPacket(layerpack, ThrottleOutPacketType.Wind);
1356 } 1334 }
@@ -1374,7 +1352,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1374 } 1352 }
1375 } 1353 }
1376 1354
1377 LayerDataPacket layerpack = TerrainCompressor.CreateLayerDataPacket(patches, TerrainPatch.LayerType.Cloud); 1355 byte layerType = (byte)TerrainPatch.LayerType.Cloud;
1356 if (m_scene.RegionInfo.RegionSizeX > Constants.RegionSize || m_scene.RegionInfo.RegionSizeY > Constants.RegionSize)
1357 layerType = (byte)TerrainPatch.LayerType.CloudExtended;
1358
1359 LayerDataPacket layerpack = OpenSimTerrainCompressor.CreateLayerDataPacket(patches, layerType,
1360 (int)m_scene.RegionInfo.RegionSizeX, (int)m_scene.RegionInfo.RegionSizeY);
1378 layerpack.Header.Zerocoded = true; 1361 layerpack.Header.Zerocoded = true;
1379 OutPacket(layerpack, ThrottleOutPacketType.Cloud); 1362 OutPacket(layerpack, ThrottleOutPacketType.Cloud);
1380 } 1363 }
@@ -2785,8 +2768,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2785 { 2768 {
2786 if (req.AssetInf.Data == null) 2769 if (req.AssetInf.Data == null)
2787 { 2770 {
2788 m_log.ErrorFormat("Cannot send asset {0} ({1}), asset data is null", 2771 m_log.ErrorFormat("{0} Cannot send asset {1} ({2}), asset data is null",
2789 req.AssetInf.ID, req.AssetInf.Metadata.ContentType); 2772 LogHeader, req.AssetInf.ID, req.AssetInf.Metadata.ContentType);
2790 return; 2773 return;
2791 } 2774 }
2792 2775
@@ -6446,26 +6429,25 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6446 // Temporarily protect ourselves from the mantis #951 failure. 6429 // Temporarily protect ourselves from the mantis #951 failure.
6447 // However, we could do this for several other handlers where a failure isn't terminal 6430 // However, we could do this for several other handlers where a failure isn't terminal
6448 // for the client session anyway, in order to protect ourselves against bad code in plugins 6431 // for the client session anyway, in order to protect ourselves against bad code in plugins
6432 Vector3 avSize = appear.AgentData.Size;
6449 try 6433 try
6450 { 6434 {
6451 byte[] visualparams = new byte[appear.VisualParam.Length]; 6435 byte[] visualparams = new byte[appear.VisualParam.Length];
6452 for (int i = 0; i < appear.VisualParam.Length; i++) 6436 for (int i = 0; i < appear.VisualParam.Length; i++)
6453 visualparams[i] = appear.VisualParam[i].ParamValue; 6437 visualparams[i] = appear.VisualParam[i].ParamValue;
6438 //var b = appear.WearableData[0];
6454 6439
6455 Primitive.TextureEntry te = null; 6440 Primitive.TextureEntry te = null;
6456 if (appear.ObjectData.TextureEntry.Length > 1) 6441 if (appear.ObjectData.TextureEntry.Length > 1)
6457 te = new Primitive.TextureEntry(appear.ObjectData.TextureEntry, 0, appear.ObjectData.TextureEntry.Length); 6442 te = new Primitive.TextureEntry(appear.ObjectData.TextureEntry, 0, appear.ObjectData.TextureEntry.Length);
6458 6443
6459 List<CachedTextureRequestArg> hashes = new List<CachedTextureRequestArg>(); 6444 WearableCacheItem[] cacheitems = new WearableCacheItem[appear.WearableData.Length];
6460 for (int i = 0; i < appear.WearableData.Length; i++) 6445 for (int i=0; i<appear.WearableData.Length;i++)
6461 { 6446 cacheitems[i] = new WearableCacheItem(){CacheId = appear.WearableData[i].CacheID,TextureIndex=Convert.ToUInt32(appear.WearableData[i].TextureIndex)};
6462 CachedTextureRequestArg arg = new CachedTextureRequestArg();
6463 arg.BakedTextureIndex = appear.WearableData[i].TextureIndex;
6464 arg.WearableHashID = appear.WearableData[i].CacheID;
6465 hashes.Add(arg);
6466 }
6467 6447
6468 handlerSetAppearance(sender, te, visualparams, hashes); 6448
6449
6450 handlerSetAppearance(sender, te, visualparams,avSize, cacheitems);
6469 } 6451 }
6470 catch (Exception e) 6452 catch (Exception e)
6471 { 6453 {
@@ -8971,6 +8953,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP
8971 TeleportLocationRequest handlerTeleportLocationRequest = OnTeleportLocationRequest; 8953 TeleportLocationRequest handlerTeleportLocationRequest = OnTeleportLocationRequest;
8972 if (handlerTeleportLocationRequest != null) 8954 if (handlerTeleportLocationRequest != null)
8973 { 8955 {
8956 // Adjust teleport location to base of a larger region if requested to teleport to a sub-region
8957 uint locX, locY;
8958 Util.RegionHandleToWorldLoc(tpLocReq.Info.RegionHandle, out locX, out locY);
8959 if ((locX >= m_scene.RegionInfo.WorldLocX)
8960 && (locX < (m_scene.RegionInfo.WorldLocX + m_scene.RegionInfo.RegionSizeX))
8961 && (locY >= m_scene.RegionInfo.WorldLocY)
8962 && (locY < (m_scene.RegionInfo.WorldLocY + m_scene.RegionInfo.RegionSizeY)) )
8963 {
8964 tpLocReq.Info.RegionHandle = m_scene.RegionInfo.RegionHandle;
8965 tpLocReq.Info.Position.X += locX - m_scene.RegionInfo.WorldLocX;
8966 tpLocReq.Info.Position.Y += locY - m_scene.RegionInfo.WorldLocY;
8967 }
8968
8974 handlerTeleportLocationRequest(this, tpLocReq.Info.RegionHandle, tpLocReq.Info.Position, 8969 handlerTeleportLocationRequest(this, tpLocReq.Info.RegionHandle, tpLocReq.Info.Position,
8975 tpLocReq.Info.LookAt, 16); 8970 tpLocReq.Info.LookAt, 16);
8976 } 8971 }
@@ -11758,36 +11753,158 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11758 /// <returns></returns> 11753 /// <returns></returns>
11759 protected bool HandleAgentTextureCached(IClientAPI simclient, Packet packet) 11754 protected bool HandleAgentTextureCached(IClientAPI simclient, Packet packet)
11760 { 11755 {
11756 //m_log.Debug("texture cached: " + packet.ToString());
11761 AgentCachedTexturePacket cachedtex = (AgentCachedTexturePacket)packet; 11757 AgentCachedTexturePacket cachedtex = (AgentCachedTexturePacket)packet;
11758 AgentCachedTextureResponsePacket cachedresp = (AgentCachedTextureResponsePacket)PacketPool.Instance.GetPacket(PacketType.AgentCachedTextureResponse);
11762 11759
11763 if (cachedtex.AgentData.SessionID != SessionId) 11760 if (cachedtex.AgentData.SessionID != SessionId)
11764 return false; 11761 return false;
11765 11762
11766 List<CachedTextureRequestArg> requestArgs = new List<CachedTextureRequestArg>();
11767 11763
11768 for (int i = 0; i < cachedtex.WearableData.Length; i++) 11764 // TODO: don't create new blocks if recycling an old packet
11769 { 11765 cachedresp.AgentData.AgentID = AgentId;
11770 CachedTextureRequestArg arg = new CachedTextureRequestArg(); 11766 cachedresp.AgentData.SessionID = m_sessionId;
11771 arg.BakedTextureIndex = cachedtex.WearableData[i].TextureIndex; 11767 cachedresp.AgentData.SerialNum = m_cachedTextureSerial;
11772 arg.WearableHashID = cachedtex.WearableData[i].ID; 11768 m_cachedTextureSerial++;
11773 11769 cachedresp.WearableData =
11774 requestArgs.Add(arg); 11770 new AgentCachedTextureResponsePacket.WearableDataBlock[cachedtex.WearableData.Length];
11775 } 11771
11772 //IAvatarFactoryModule fac = m_scene.RequestModuleInterface<IAvatarFactoryModule>();
11773 // var item = fac.GetBakedTextureFaces(AgentId);
11774 //WearableCacheItem[] items = fac.GetCachedItems(AgentId);
11775
11776 IAssetService cache = m_scene.AssetService;
11777 IBakedTextureModule bakedTextureModule = m_scene.RequestModuleInterface<IBakedTextureModule>();
11778 //bakedTextureModule = null;
11779 int maxWearablesLoop = cachedtex.WearableData.Length;
11780 if (maxWearablesLoop > AvatarWearable.MAX_WEARABLES)
11781 maxWearablesLoop = AvatarWearable.MAX_WEARABLES;
11782
11783 if (bakedTextureModule != null && cache != null)
11784 {
11785 // We need to make sure the asset stored in the bake is available on this server also by it's assetid before we map it to a Cacheid
11786
11787 WearableCacheItem[] cacheItems = null;
11788 ScenePresence p = m_scene.GetScenePresence(AgentId);
11789 if (p.Appearance != null)
11790 if (p.Appearance.WearableCacheItems == null || p.Appearance.WearableCacheItemsDirty)
11791 {
11792 try
11793 {
11794 cacheItems = bakedTextureModule.Get(AgentId);
11795 p.Appearance.WearableCacheItems = cacheItems;
11796 p.Appearance.WearableCacheItemsDirty = false;
11797 }
11776 11798
11777 try 11799 /*
11778 { 11800 * The following Catch types DO NOT WORK, it jumps to the General Packet Exception Handler if you don't catch Exception!
11779 CachedTextureRequest handlerCachedTextureRequest = OnCachedTextureRequest; 11801 *
11780 if (handlerCachedTextureRequest != null) 11802 catch (System.Net.Sockets.SocketException)
11803 {
11804 cacheItems = null;
11805 }
11806 catch (WebException)
11807 {
11808 cacheItems = null;
11809 }
11810 catch (InvalidOperationException)
11811 {
11812 cacheItems = null;
11813 } */
11814 catch (Exception)
11815 {
11816 cacheItems = null;
11817 }
11818
11819 }
11820 else if (p.Appearance.WearableCacheItems != null)
11821 {
11822 cacheItems = p.Appearance.WearableCacheItems;
11823 }
11824
11825 if (cache != null && cacheItems != null)
11826 {
11827 foreach (WearableCacheItem item in cacheItems)
11828 {
11829
11830 if (cache.GetCached(item.TextureID.ToString()) == null)
11831 {
11832 item.TextureAsset.Temporary = true;
11833 cache.Store(item.TextureAsset);
11834 }
11835
11836
11837 }
11838 }
11839 if (cacheItems != null)
11781 { 11840 {
11782 handlerCachedTextureRequest(simclient,cachedtex.AgentData.SerialNum,requestArgs); 11841
11842 for (int i = 0; i < maxWearablesLoop; i++)
11843 {
11844 WearableCacheItem item =
11845 WearableCacheItem.SearchTextureIndex(cachedtex.WearableData[i].TextureIndex,cacheItems);
11846
11847 cachedresp.WearableData[i] = new AgentCachedTextureResponsePacket.WearableDataBlock();
11848 cachedresp.WearableData[i].TextureIndex= cachedtex.WearableData[i].TextureIndex;
11849 cachedresp.WearableData[i].HostName = new byte[0];
11850 if (item != null && cachedtex.WearableData[i].ID == item.CacheId)
11851 {
11852
11853 cachedresp.WearableData[i].TextureID = item.TextureID;
11854 }
11855 else
11856 {
11857 cachedresp.WearableData[i].TextureID = UUID.Zero;
11858 }
11859 }
11860 }
11861 else
11862 {
11863 for (int i = 0; i < maxWearablesLoop; i++)
11864 {
11865 cachedresp.WearableData[i] = new AgentCachedTextureResponsePacket.WearableDataBlock();
11866 cachedresp.WearableData[i].TextureIndex = cachedtex.WearableData[i].TextureIndex;
11867 cachedresp.WearableData[i].TextureID = UUID.Zero;
11868 //UUID.Parse("8334fb6e-c2f5-46ee-807d-a435f61a8d46");
11869 cachedresp.WearableData[i].HostName = new byte[0];
11870 }
11783 } 11871 }
11784 } 11872 }
11785 catch (Exception e) 11873 else
11786 { 11874 {
11787 m_log.ErrorFormat("[CLIENT VIEW]: AgentTextureCached packet handler threw an exception, {0}", e); 11875 if (cache == null)
11788 return false; 11876 {
11877 for (int i = 0; i < maxWearablesLoop; i++)
11878 {
11879 cachedresp.WearableData[i] = new AgentCachedTextureResponsePacket.WearableDataBlock();
11880 cachedresp.WearableData[i].TextureIndex = cachedtex.WearableData[i].TextureIndex;
11881 cachedresp.WearableData[i].TextureID = UUID.Zero;
11882 //UUID.Parse("8334fb6e-c2f5-46ee-807d-a435f61a8d46");
11883 cachedresp.WearableData[i].HostName = new byte[0];
11884 }
11885 }
11886 else
11887 {
11888 for (int i = 0; i < maxWearablesLoop; i++)
11889 {
11890 cachedresp.WearableData[i] = new AgentCachedTextureResponsePacket.WearableDataBlock();
11891 cachedresp.WearableData[i].TextureIndex = cachedtex.WearableData[i].TextureIndex;
11892
11893
11894
11895 if (cache.GetCached(cachedresp.WearableData[i].TextureID.ToString()) == null)
11896 cachedresp.WearableData[i].TextureID = UUID.Zero;
11897 //UUID.Parse("8334fb6e-c2f5-46ee-807d-a435f61a8d46");
11898 else
11899 cachedresp.WearableData[i].TextureID = UUID.Zero;
11900 // UUID.Parse("8334fb6e-c2f5-46ee-807d-a435f61a8d46");
11901 cachedresp.WearableData[i].HostName = new byte[0];
11902 }
11903 }
11789 } 11904 }
11790 11905 cachedresp.Header.Zerocoded = true;
11906 OutPacket(cachedresp, ThrottleOutPacketType.Task);
11907
11791 return true; 11908 return true;
11792 } 11909 }
11793 11910
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs
index 202cc62..51433cb 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs
@@ -162,6 +162,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
162 private int m_defaultRTO = 1000; // 1sec is the recommendation in the RFC 162 private int m_defaultRTO = 1000; // 1sec is the recommendation in the RFC
163 private int m_maxRTO = 60000; 163 private int m_maxRTO = 60000;
164 164
165 /// <summary>
166 /// This is the percentage of the udp texture queue to add to the task queue since
167 /// textures are now generally handled through http.
168 /// </summary>
169 private double m_cannibalrate = 0.0;
170
165 private ClientInfo m_info = new ClientInfo(); 171 private ClientInfo m_info = new ClientInfo();
166 172
167 /// <summary> 173 /// <summary>
@@ -201,6 +207,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
201 // Create an array of token buckets for this clients different throttle categories 207 // Create an array of token buckets for this clients different throttle categories
202 m_throttleCategories = new TokenBucket[THROTTLE_CATEGORY_COUNT]; 208 m_throttleCategories = new TokenBucket[THROTTLE_CATEGORY_COUNT];
203 209
210 m_cannibalrate = rates.CannibalizeTextureRate;
211
204 for (int i = 0; i < THROTTLE_CATEGORY_COUNT; i++) 212 for (int i = 0; i < THROTTLE_CATEGORY_COUNT; i++)
205 { 213 {
206 ThrottleOutPacketType type = (ThrottleOutPacketType)i; 214 ThrottleOutPacketType type = (ThrottleOutPacketType)i;
@@ -349,6 +357,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
349 texture = Math.Max(texture, LLUDPServer.MTU); 357 texture = Math.Max(texture, LLUDPServer.MTU);
350 asset = Math.Max(asset, LLUDPServer.MTU); 358 asset = Math.Max(asset, LLUDPServer.MTU);
351 359
360 // Since most textures are now delivered through http, make it possible
361 // to cannibalize some of the bw from the texture throttle to use for
362 // the task queue (e.g. object updates)
363 task = task + (int)(m_cannibalrate * texture);
364 texture = (int)((1 - m_cannibalrate) * texture);
365
352 //int total = resend + land + wind + cloud + task + texture + asset; 366 //int total = resend + land + wind + cloud + task + texture + asset;
353 //m_log.DebugFormat("[LLUDPCLIENT]: {0} is setting throttles. Resend={1}, Land={2}, Wind={3}, Cloud={4}, Task={5}, Texture={6}, Asset={7}, Total={8}", 367 //m_log.DebugFormat("[LLUDPCLIENT]: {0} is setting throttles. Resend={1}, Land={2}, Wind={3}, Cloud={4}, Task={5}, Texture={6}, Asset={7}, Total={8}",
354 // AgentID, resend, land, wind, cloud, task, texture, asset, total); 368 // AgentID, resend, land, wind, cloud, task, texture, asset, total);
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/ThrottleRates.cs b/OpenSim/Region/ClientStack/Linden/UDP/ThrottleRates.cs
index c9aac0b..e5bae6e 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/ThrottleRates.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/ThrottleRates.cs
@@ -59,6 +59,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
59 /// <summary>Flag used to enable adaptive throttles</summary> 59 /// <summary>Flag used to enable adaptive throttles</summary>
60 public bool AdaptiveThrottlesEnabled; 60 public bool AdaptiveThrottlesEnabled;
61 61
62 /// <summary>Amount of the texture throttle to steal for the task throttle</summary>
63 public double CannibalizeTextureRate;
64
62 /// <summary> 65 /// <summary>
63 /// Default constructor 66 /// Default constructor
64 /// </summary> 67 /// </summary>
@@ -80,6 +83,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
80 Total = throttleConfig.GetInt("client_throttle_max_bps", 0); 83 Total = throttleConfig.GetInt("client_throttle_max_bps", 0);
81 84
82 AdaptiveThrottlesEnabled = throttleConfig.GetBoolean("enable_adaptive_throttles", false); 85 AdaptiveThrottlesEnabled = throttleConfig.GetBoolean("enable_adaptive_throttles", false);
86
87 CannibalizeTextureRate = (double)throttleConfig.GetFloat("CannibalizeTextureRate", 0.0f);
88 CannibalizeTextureRate = Util.Clamp<double>(CannibalizeTextureRate,0.0, 0.9);
83 } 89 }
84 catch (Exception) { } 90 catch (Exception) { }
85 } 91 }