From 6797ac14741851efa5ba60a00891e18cf7755c80 Mon Sep 17 00:00:00 2001 From: teravus Date: Sat, 29 Dec 2012 08:53:58 -0500 Subject: * This finishes the implementation of AgentCachedTexture. Requires the XBakes Module and service for full functionality. Previous no-cache functionality works without the service and module. In some ways, I would have been happier not putting an AssetBase in WearableCacheItem.. but turns out it was probably unavoidable. No additional locks, yay. --- .../Linden/Caps/UploadBakedTextureModule.cs | 140 ++++++++++++++++++++- .../Region/ClientStack/Linden/UDP/LLClientView.cs | 110 +++++++++++++--- 2 files changed, 230 insertions(+), 20 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden') diff --git a/OpenSim/Region/ClientStack/Linden/Caps/UploadBakedTextureModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/UploadBakedTextureModule.cs index 3b0ccd7..6778ba5 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/UploadBakedTextureModule.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/UploadBakedTextureModule.cs @@ -27,6 +27,7 @@ using System; using System.Collections; +using System.Collections.Generic; using System.Collections.Specialized; using System.Drawing; using System.Drawing.Imaging; @@ -53,8 +54,8 @@ namespace OpenSim.Region.ClientStack.Linden [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "UploadBakedTextureModule")] public class UploadBakedTextureModule : INonSharedRegionModule { -// private static readonly ILog m_log = -// LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + private static readonly ILog m_log = + LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); /// /// For historical reasons this is fixed, but there @@ -64,31 +65,154 @@ namespace OpenSim.Region.ClientStack.Linden private Scene m_scene; private bool m_persistBakedTextures; + private IBakedTextureModule m_BakedTextureModule; + public void Initialise(IConfigSource source) { IConfig appearanceConfig = source.Configs["Appearance"]; if (appearanceConfig != null) m_persistBakedTextures = appearanceConfig.GetBoolean("PersistBakedTextures", m_persistBakedTextures); + + } public void AddRegion(Scene s) { m_scene = s; + } public void RemoveRegion(Scene s) { + s.EventManager.OnRegisterCaps -= RegisterCaps; + s.EventManager.OnNewPresence -= RegisterNewPresence; + s.EventManager.OnRemovePresence -= DeRegisterPresence; + m_BakedTextureModule = null; + m_scene = null; } + + public void RegionLoaded(Scene s) { m_scene.EventManager.OnRegisterCaps += RegisterCaps; + m_scene.EventManager.OnNewPresence += RegisterNewPresence; + m_scene.EventManager.OnRemovePresence += DeRegisterPresence; + + } + + private void DeRegisterPresence(UUID agentId) + { + ScenePresence presence = null; + if (m_scene.TryGetScenePresence(agentId, out presence)) + { + presence.ControllingClient.OnSetAppearance -= CaptureAppearanceSettings; + } + + } + + private void RegisterNewPresence(ScenePresence presence) + { + presence.ControllingClient.OnSetAppearance += CaptureAppearanceSettings; + + } + + private void CaptureAppearanceSettings(IClientAPI remoteClient, Primitive.TextureEntry textureEntry, byte[] visualParams, Vector3 avSize, WearableCacheItem[] cacheItems) + { + m_BakedTextureModule = m_scene.RequestModuleInterface(); + if (cacheItems.Length > 0) + { + m_log.Info("[Cacheitems]: " + cacheItems.Length); + for (int iter = 0; iter < cacheItems.Length; iter++) + { + m_log.Info("[Cacheitems] {" + iter + "/" + cacheItems[iter].TextureIndex + "}: c-" + cacheItems[iter].CacheId + ", t-" + + cacheItems[iter].TextureID); + } + + ScenePresence p = null; + if (m_scene.TryGetScenePresence(remoteClient.AgentId, out p)) + { + + WearableCacheItem[] existingitems = p.Appearance.WearableCacheItems; + if (existingitems == null) + { + if (m_BakedTextureModule != null) + { + WearableCacheItem[] savedcache = null; + try + { + if (p.Appearance.WearableCacheItemsDirty) + { + savedcache = m_BakedTextureModule.Get(p.UUID); + p.Appearance.WearableCacheItems = savedcache; + p.Appearance.WearableCacheItemsDirty = false; + } + + } + catch (InvalidOperationException) + { + } + + if (savedcache != null) + existingitems = savedcache; + } + } + // Existing items null means it's a fully new appearance + if (existingitems == null) + { + + for (int iter = 0; iter < cacheItems.Length; iter++) + { + + cacheItems[iter].TextureID = textureEntry.FaceTextures[cacheItems[iter].TextureIndex].TextureID; + if (m_scene.AssetService != null) + cacheItems[iter].TextureAsset = m_scene.AssetService.GetCached(cacheItems[iter].TextureID.ToString()); + + + } + } + else + + + { + // for each uploaded baked texture + for (int i = 0; i < cacheItems.Length; i++) + { + cacheItems[i].TextureID = + textureEntry.FaceTextures[cacheItems[i].TextureIndex].TextureID; + } + + for (int i = 0; i < cacheItems.Length; i++) + { + if (cacheItems[i].TextureAsset == null) + { + cacheItems[i].TextureAsset = m_scene.AssetService.GetCached(cacheItems[i].TextureID.ToString()); + } + } + } + + + + p.Appearance.WearableCacheItems = cacheItems; + + + + if (m_BakedTextureModule != null) + { + m_BakedTextureModule.Store(remoteClient.AgentId, cacheItems); + p.Appearance.WearableCacheItemsDirty = true; + + } + } + } } public void PostInitialise() { } + + public void Close() { } public string Name { get { return "UploadBakedTextureModule"; } } @@ -100,15 +224,23 @@ namespace OpenSim.Region.ClientStack.Linden public void RegisterCaps(UUID agentID, Caps caps) { + UploadBakedTextureHandler avatarhandler = new UploadBakedTextureHandler( + caps, m_scene.AssetService, m_persistBakedTextures); + + + caps.RegisterHandler( "UploadBakedTexture", new RestStreamHandler( "POST", "/CAPS/" + caps.CapsObjectPath + m_uploadBakedTexturePath, - new UploadBakedTextureHandler( - caps, m_scene.AssetService, m_persistBakedTextures).UploadBakedTexture, + avatarhandler.UploadBakedTexture, "UploadBakedTexture", agentID.ToString())); + + + + } } } \ No newline at end of file diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index d18b026..9e39699 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -3629,7 +3629,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP avp.Sender.IsTrial = false; avp.Sender.ID = agentID; - //m_log.DebugFormat("[CLIENT]: Sending appearance for {0} to {1}", agentID.ToString(), AgentId.ToString()); + m_log.DebugFormat("[CLIENT]: Sending appearance for {0} to {1}", agentID.ToString(), AgentId.ToString()); OutPacket(avp, ThrottleOutPacketType.State); } @@ -11725,32 +11725,110 @@ namespace OpenSim.Region.ClientStack.LindenUDP // var item = fac.GetBakedTextureFaces(AgentId); //WearableCacheItem[] items = fac.GetCachedItems(AgentId); - IImprovedAssetCache cache = m_scene.RequestModuleInterface(); - if (cache == null) + IAssetService cache = m_scene.AssetService; + IBakedTextureModule bakedTextureModule = m_scene.RequestModuleInterface(); + if (bakedTextureModule != null && cache != null) { - for (int i = 0; i < cachedtex.WearableData.Length; i++) + // 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 + + WearableCacheItem[] cacheItems = null; + ScenePresence p = m_scene.GetScenePresence(AgentId); + if (p.Appearance != null) + if (p.Appearance.WearableCacheItems == null || p.Appearance.WearableCacheItemsDirty) + { + try + { + cacheItems = bakedTextureModule.Get(AgentId); + p.Appearance.WearableCacheItems = cacheItems; + p.Appearance.WearableCacheItemsDirty = false; + } + catch (InvalidOperationException) + { + cacheItems = null; + } + } + else if (p.Appearance.WearableCacheItems != null) + { + cacheItems = p.Appearance.WearableCacheItems; + } + + if (cache != null && cacheItems != null) + { + foreach (WearableCacheItem item in cacheItems) + { + + if (cache.GetCached(item.TextureID.ToString()) == null) + { + item.TextureAsset.Temporary = true; + cache.Store(item.TextureAsset); + } + + + } + } + if (cacheItems != null) + { + + for (int i = 0; i < cachedtex.WearableData.Length; i++) + { + WearableCacheItem item = + WearableCacheItem.SearchTextureIndex(cachedtex.WearableData[i].TextureIndex,cacheItems); + + cachedresp.WearableData[i] = new AgentCachedTextureResponsePacket.WearableDataBlock(); + cachedresp.WearableData[i].TextureIndex= cachedtex.WearableData[i].TextureIndex; + cachedresp.WearableData[i].HostName = new byte[0]; + if (item != null) + { + cachedresp.WearableData[i].TextureID = item.TextureID; + } + else + { + cachedresp.WearableData[i].TextureID = UUID.Zero; + } + } + } + else { - cachedresp.WearableData[i] = new AgentCachedTextureResponsePacket.WearableDataBlock(); - cachedresp.WearableData[i].TextureIndex = cachedtex.WearableData[i].TextureIndex; - cachedresp.WearableData[i].TextureID = UUID.Zero; //UUID.Parse("8334fb6e-c2f5-46ee-807d-a435f61a8d46"); - cachedresp.WearableData[i].HostName = new byte[0]; + for (int i = 0; i < cachedtex.WearableData.Length; i++) + { + cachedresp.WearableData[i] = new AgentCachedTextureResponsePacket.WearableDataBlock(); + cachedresp.WearableData[i].TextureIndex = cachedtex.WearableData[i].TextureIndex; + cachedresp.WearableData[i].TextureID = UUID.Zero; + //UUID.Parse("8334fb6e-c2f5-46ee-807d-a435f61a8d46"); + cachedresp.WearableData[i].HostName = new byte[0]; + } } } else { - for (int i = 0; i < cachedtex.WearableData.Length; i++) + if (cache == null) + { + for (int i = 0; i < cachedtex.WearableData.Length; i++) + { + cachedresp.WearableData[i] = new AgentCachedTextureResponsePacket.WearableDataBlock(); + cachedresp.WearableData[i].TextureIndex = cachedtex.WearableData[i].TextureIndex; + cachedresp.WearableData[i].TextureID = UUID.Zero; + //UUID.Parse("8334fb6e-c2f5-46ee-807d-a435f61a8d46"); + cachedresp.WearableData[i].HostName = new byte[0]; + } + } + else { - cachedresp.WearableData[i] = new AgentCachedTextureResponsePacket.WearableDataBlock(); - cachedresp.WearableData[i].TextureIndex = cachedtex.WearableData[i].TextureIndex; + for (int i = 0; i < cachedtex.WearableData.Length; i++) + { + cachedresp.WearableData[i] = new AgentCachedTextureResponsePacket.WearableDataBlock(); + cachedresp.WearableData[i].TextureIndex = cachedtex.WearableData[i].TextureIndex; - if (cache.Check(cachedtex.WearableData[i].ID.ToString())) - cachedresp.WearableData[i].TextureID = UUID.Zero; + if (cache.GetCached(cachedresp.WearableData[i].TextureID.ToString()) == null) + cachedresp.WearableData[i].TextureID = UUID.Zero; //UUID.Parse("8334fb6e-c2f5-46ee-807d-a435f61a8d46"); - else - cachedresp.WearableData[i].TextureID = UUID.Zero; // UUID.Parse("8334fb6e-c2f5-46ee-807d-a435f61a8d46"); - cachedresp.WearableData[i].HostName = new byte[0]; + else + cachedresp.WearableData[i].TextureID = UUID.Zero; + // UUID.Parse("8334fb6e-c2f5-46ee-807d-a435f61a8d46"); + cachedresp.WearableData[i].HostName = new byte[0]; + } } } cachedresp.Header.Zerocoded = true; -- cgit v1.1 From 2805ec64662494d680925c6034e59b823e051a9d Mon Sep 17 00:00:00 2001 From: teravus Date: Mon, 31 Dec 2012 23:04:28 -0500 Subject: * Fixed a bug that replayed old cached appearance when changing outfits * Added suser(bad client) DOS protection by limiting the max cacheitems to the maximum sane amount. * Prevents potential numerous loops from running amok and index errors if the client purposely provides bad cache info. * If the XBakes service wasn't running, the SetAvatarAppearance routine would crash when contacting the XBakes service even though it was in a Try/Catch for the appropriate error type. It only properly error handles with the type Exception :(. (commented on that because it's unusual) --- .../Linden/Caps/UploadBakedTextureModule.cs | 123 ++++++++++++++------- .../Region/ClientStack/Linden/UDP/LLClientView.cs | 34 +++++- 2 files changed, 111 insertions(+), 46 deletions(-) (limited to 'OpenSim/Region/ClientStack/Linden') diff --git a/OpenSim/Region/ClientStack/Linden/Caps/UploadBakedTextureModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/UploadBakedTextureModule.cs index 6778ba5..6bed95f 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/UploadBakedTextureModule.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/UploadBakedTextureModule.cs @@ -119,13 +119,20 @@ namespace OpenSim.Region.ClientStack.Linden private void CaptureAppearanceSettings(IClientAPI remoteClient, Primitive.TextureEntry textureEntry, byte[] visualParams, Vector3 avSize, WearableCacheItem[] cacheItems) { + int maxCacheitemsLoop = cacheItems.Length; + if (maxCacheitemsLoop > AvatarWearable.MAX_WEARABLES) + { + maxCacheitemsLoop = AvatarWearable.MAX_WEARABLES; + m_log.WarnFormat("[CACHEDBAKES]: Too Many Cache items Provided {0}, the max is {1}. Truncating!", cacheItems.Length, AvatarWearable.MAX_WEARABLES); + } + m_BakedTextureModule = m_scene.RequestModuleInterface(); if (cacheItems.Length > 0) { - m_log.Info("[Cacheitems]: " + cacheItems.Length); - for (int iter = 0; iter < cacheItems.Length; iter++) + m_log.Debug("[Cacheitems]: " + cacheItems.Length); + for (int iter = 0; iter < maxCacheitemsLoop; iter++) { - m_log.Info("[Cacheitems] {" + iter + "/" + cacheItems[iter].TextureIndex + "}: c-" + cacheItems[iter].CacheId + ", t-" + + m_log.Debug("[Cacheitems] {" + iter + "/" + cacheItems[iter].TextureIndex + "}: c-" + cacheItems[iter].CacheId + ", t-" + cacheItems[iter].TextureID); } @@ -133,65 +140,99 @@ namespace OpenSim.Region.ClientStack.Linden if (m_scene.TryGetScenePresence(remoteClient.AgentId, out p)) { - WearableCacheItem[] existingitems = p.Appearance.WearableCacheItems; - if (existingitems == null) + WearableCacheItem[] existingitems = p.Appearance.WearableCacheItems; + if (existingitems == null) + { + if (m_BakedTextureModule != null) { - if (m_BakedTextureModule != null) + WearableCacheItem[] savedcache = null; + try { - WearableCacheItem[] savedcache = null; - try - { - if (p.Appearance.WearableCacheItemsDirty) - { - savedcache = m_BakedTextureModule.Get(p.UUID); - p.Appearance.WearableCacheItems = savedcache; - p.Appearance.WearableCacheItemsDirty = false; - } - - } - catch (InvalidOperationException) + if (p.Appearance.WearableCacheItemsDirty) { + savedcache = m_BakedTextureModule.Get(p.UUID); + p.Appearance.WearableCacheItems = savedcache; + p.Appearance.WearableCacheItemsDirty = false; } - if (savedcache != null) - existingitems = savedcache; } + /* + * The following Catch types DO NOT WORK with m_BakedTextureModule.Get + * it jumps to the General Packet Exception Handler if you don't catch Exception! + * + catch (System.Net.Sockets.SocketException) + { + cacheItems = null; + } + catch (WebException) + { + cacheItems = null; + } + catch (InvalidOperationException) + { + cacheItems = null; + } */ + catch (Exception) + { + // The service logs a sufficient error message. + } + + + if (savedcache != null) + existingitems = savedcache; } - // Existing items null means it's a fully new appearance - if (existingitems == null) - { + } + // Existing items null means it's a fully new appearance + if (existingitems == null) + { - for (int iter = 0; iter < cacheItems.Length; iter++) + for (int i = 0; i < maxCacheitemsLoop; i++) + { + if (textureEntry.FaceTextures.Length > cacheItems[i].TextureIndex) { - - cacheItems[iter].TextureID = textureEntry.FaceTextures[cacheItems[iter].TextureIndex].TextureID; + cacheItems[i].TextureID = + textureEntry.FaceTextures[cacheItems[i].TextureIndex].TextureID; if (m_scene.AssetService != null) - cacheItems[iter].TextureAsset = m_scene.AssetService.GetCached(cacheItems[iter].TextureID.ToString()); - - + cacheItems[i].TextureAsset = + m_scene.AssetService.GetCached(cacheItems[i].TextureID.ToString()); + } + else + { + m_log.WarnFormat("[CACHEDBAKES]: Invalid Texture Index Provided, Texture doesn't exist or hasn't been uploaded yet {0}, the max is {1}. Skipping!", cacheItems[i].TextureIndex, textureEntry.FaceTextures.Length); } + + } - else - - + } + else + + + { + // for each uploaded baked texture + for (int i = 0; i < maxCacheitemsLoop; i++) { - // for each uploaded baked texture - for (int i = 0; i < cacheItems.Length; i++) + if (textureEntry.FaceTextures.Length > cacheItems[i].TextureIndex) { cacheItems[i].TextureID = textureEntry.FaceTextures[cacheItems[i].TextureIndex].TextureID; } - - for (int i = 0; i < cacheItems.Length; i++) + else { - if (cacheItems[i].TextureAsset == null) - { - cacheItems[i].TextureAsset = m_scene.AssetService.GetCached(cacheItems[i].TextureID.ToString()); - } + m_log.WarnFormat("[CACHEDBAKES]: Invalid Texture Index Provided, Texture doesn't exist or hasn't been uploaded yet {0}, the max is {1}. Skipping!", cacheItems[i].TextureIndex, textureEntry.FaceTextures.Length); } } - + for (int i = 0; i < maxCacheitemsLoop; i++) + { + if (cacheItems[i].TextureAsset == null) + { + cacheItems[i].TextureAsset = + m_scene.AssetService.GetCached(cacheItems[i].TextureID.ToString()); + } + } + } + + p.Appearance.WearableCacheItems = cacheItems; diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 9e39699..d46adb8 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -11727,6 +11727,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP IAssetService cache = m_scene.AssetService; IBakedTextureModule bakedTextureModule = m_scene.RequestModuleInterface(); + //bakedTextureModule = null; + int maxWearablesLoop = cachedtex.WearableData.Length; + if (maxWearablesLoop > AvatarWearable.MAX_WEARABLES) + maxWearablesLoop = AvatarWearable.MAX_WEARABLES; + if (bakedTextureModule != null && cache != null) { // 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 @@ -11742,10 +11747,27 @@ namespace OpenSim.Region.ClientStack.LindenUDP p.Appearance.WearableCacheItems = cacheItems; p.Appearance.WearableCacheItemsDirty = false; } + + /* + * The following Catch types DO NOT WORK, it jumps to the General Packet Exception Handler if you don't catch Exception! + * + catch (System.Net.Sockets.SocketException) + { + cacheItems = null; + } + catch (WebException) + { + cacheItems = null; + } catch (InvalidOperationException) { cacheItems = null; + } */ + catch (Exception) + { + cacheItems = null; } + } else if (p.Appearance.WearableCacheItems != null) { @@ -11766,10 +11788,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP } } + if (cacheItems != null) { - for (int i = 0; i < cachedtex.WearableData.Length; i++) + for (int i = 0; i < maxWearablesLoop; i++) { WearableCacheItem item = WearableCacheItem.SearchTextureIndex(cachedtex.WearableData[i].TextureIndex,cacheItems); @@ -11777,8 +11800,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP cachedresp.WearableData[i] = new AgentCachedTextureResponsePacket.WearableDataBlock(); cachedresp.WearableData[i].TextureIndex= cachedtex.WearableData[i].TextureIndex; cachedresp.WearableData[i].HostName = new byte[0]; - if (item != null) + if (item != null && cachedtex.WearableData[i].ID == item.CacheId) { + cachedresp.WearableData[i].TextureID = item.TextureID; } else @@ -11789,7 +11813,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP } else { - for (int i = 0; i < cachedtex.WearableData.Length; i++) + for (int i = 0; i < maxWearablesLoop; i++) { cachedresp.WearableData[i] = new AgentCachedTextureResponsePacket.WearableDataBlock(); cachedresp.WearableData[i].TextureIndex = cachedtex.WearableData[i].TextureIndex; @@ -11803,7 +11827,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP { if (cache == null) { - for (int i = 0; i < cachedtex.WearableData.Length; i++) + for (int i = 0; i < maxWearablesLoop; i++) { cachedresp.WearableData[i] = new AgentCachedTextureResponsePacket.WearableDataBlock(); cachedresp.WearableData[i].TextureIndex = cachedtex.WearableData[i].TextureIndex; @@ -11814,7 +11838,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP } else { - for (int i = 0; i < cachedtex.WearableData.Length; i++) + for (int i = 0; i < maxWearablesLoop; i++) { cachedresp.WearableData[i] = new AgentCachedTextureResponsePacket.WearableDataBlock(); cachedresp.WearableData[i].TextureIndex = cachedtex.WearableData[i].TextureIndex; -- cgit v1.1