From 5460f2e035f50aade96b3daa0cb284bcb6faeea7 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 1 Dec 2011 23:24:15 +0000 Subject: refactor: Separate the upload baked texture handler out from BunchOfCaps --- .../Handlers/GetTexture/GetTextureHandler.cs | 4 +- .../UploadBakedTextureHandler.cs | 179 +++++++++++++++++++++ 2 files changed, 180 insertions(+), 3 deletions(-) create mode 100644 OpenSim/Capabilities/Handlers/UploadBakedTexture/UploadBakedTextureHandler.cs (limited to 'OpenSim/Capabilities') diff --git a/OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs b/OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs index e1b4fe7..245d931 100644 --- a/OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs +++ b/OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs @@ -350,7 +350,5 @@ namespace OpenSim.Capabilities.Handlers } return null; } - - } -} +} \ No newline at end of file diff --git a/OpenSim/Capabilities/Handlers/UploadBakedTexture/UploadBakedTextureHandler.cs b/OpenSim/Capabilities/Handlers/UploadBakedTexture/UploadBakedTextureHandler.cs new file mode 100644 index 0000000..97b558c --- /dev/null +++ b/OpenSim/Capabilities/Handlers/UploadBakedTexture/UploadBakedTextureHandler.cs @@ -0,0 +1,179 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections; +using System.Collections.Specialized; +using System.Drawing; +using System.Drawing.Imaging; +using System.Reflection; +using System.IO; +using System.Web; +using log4net; +using Nini.Config; +using OpenMetaverse; +using OpenMetaverse.StructuredData; +using OpenMetaverse.Imaging; +using OpenSim.Framework; +using OpenSim.Framework.Capabilities; +using OpenSim.Framework.Servers; +using OpenSim.Framework.Servers.HttpServer; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Services.Interfaces; +using Caps = OpenSim.Framework.Capabilities.Caps; + +namespace OpenSim.Capabilities.Handlers +{ + public class UploadBakedTextureHandler + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private Caps m_HostCapsObj; + private IAssetService m_assetService; + private bool m_persistBakedTextures; + + public UploadBakedTextureHandler(Caps caps, IAssetService assetService, bool persistBakedTextures) + { + m_HostCapsObj = caps; + m_assetService = assetService; + m_persistBakedTextures = persistBakedTextures; + } + + /// + /// Handle a request from the client for a Uri to upload a baked texture. + /// + /// + /// + /// + /// + /// + /// The upload response if the request is successful, null otherwise. + public string UploadBakedTexture( + string request, string path, string param, OSHttpRequest httpRequest, OSHttpResponse httpResponse) + { + try + { +// m_log.Debug("[CAPS]: UploadBakedTexture Request in region: " + m_regionName); + + string capsBase = "/CAPS/" + m_HostCapsObj.CapsObjectPath; + string uploaderPath = Util.RandomClass.Next(5000, 8000).ToString("0000"); + + BakedTextureUploader uploader = + new BakedTextureUploader(capsBase + uploaderPath, m_HostCapsObj.HttpListener); + uploader.OnUpLoad += BakedTextureUploaded; + + m_HostCapsObj.HttpListener.AddStreamHandler( + new BinaryStreamHandler("POST", capsBase + uploaderPath, + uploader.uploaderCaps)); + + string protocol = "http://"; + + if (m_HostCapsObj.SSLCaps) + protocol = "https://"; + + string uploaderURL = protocol + m_HostCapsObj.HostName + ":" + + m_HostCapsObj.Port.ToString() + capsBase + uploaderPath; + + LLSDAssetUploadResponse uploadResponse = new LLSDAssetUploadResponse(); + uploadResponse.uploader = uploaderURL; + uploadResponse.state = "upload"; + + return LLSDHelpers.SerialiseLLSDReply(uploadResponse); + } + catch (Exception e) + { + m_log.Error("[CAPS]: " + e.ToString()); + } + + return null; + } + + /// + /// Called when a baked texture has been successfully uploaded by a client. + /// + /// + /// + private void BakedTextureUploaded(UUID assetID, byte[] data) + { + // m_log.WarnFormat("[CAPS]: Received baked texture {0}", assetID.ToString()); + + AssetBase asset; + asset = new AssetBase(assetID, "Baked Texture", (sbyte)AssetType.Texture, m_HostCapsObj.AgentID.ToString()); + asset.Data = data; + asset.Temporary = true; + asset.Local = !m_persistBakedTextures; // Local assets aren't persisted, non-local are + m_assetService.Store(asset); + } + } + + class BakedTextureUploader + { + public event Action OnUpLoad; + + private string uploaderPath = String.Empty; + private UUID newAssetID; + private IHttpServer httpListener; + + public BakedTextureUploader(string path, IHttpServer httpServer) + { + newAssetID = UUID.Random(); + uploaderPath = path; + httpListener = httpServer; + // m_log.InfoFormat("[CAPS] baked texture upload starting for {0}",newAssetID); + } + + /// + /// Handle raw uploaded baked texture data. + /// + /// + /// + /// + /// + public string uploaderCaps(byte[] data, string path, string param) + { + Action handlerUpLoad = OnUpLoad; + if (handlerUpLoad != null) + { + Util.FireAndForget(delegate(object o) { handlerUpLoad(newAssetID, data); }); + } + + string res = String.Empty; + LLSDAssetUploadComplete uploadComplete = new LLSDAssetUploadComplete(); + uploadComplete.new_asset = newAssetID.ToString(); + uploadComplete.new_inventory_item = UUID.Zero; + uploadComplete.state = "complete"; + + res = LLSDHelpers.SerialiseLLSDReply(uploadComplete); + + httpListener.RemoveStreamHandler("POST", uploaderPath); + + // m_log.InfoFormat("[CAPS] baked texture upload completed for {0}",newAssetID); + + return res; + } + } +} \ No newline at end of file -- cgit v1.1 From 1854c52ea3c60d0a47f9793a7f5ec405e15489ca Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 1 Dec 2011 23:38:25 +0000 Subject: Stop performing the asset save part of baked texture uploading on the UploadBakedTexture cap asynchronously. This prevents a possible race condition where the client would be told all baked textures had updated before they were in the asset service. The client would then trigger a set appearance which, after a delay, would send the avatar appearance out to other clients. The race condition seems unlikely because of this delay but it's still possible. Might help with grey avatar appearances. --- .../UploadBakedTexture/UploadBakedTextureHandler.cs | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'OpenSim/Capabilities') diff --git a/OpenSim/Capabilities/Handlers/UploadBakedTexture/UploadBakedTextureHandler.cs b/OpenSim/Capabilities/Handlers/UploadBakedTexture/UploadBakedTextureHandler.cs index 97b558c..b89fd6a 100644 --- a/OpenSim/Capabilities/Handlers/UploadBakedTexture/UploadBakedTextureHandler.cs +++ b/OpenSim/Capabilities/Handlers/UploadBakedTexture/UploadBakedTextureHandler.cs @@ -106,7 +106,7 @@ namespace OpenSim.Capabilities.Handlers } catch (Exception e) { - m_log.Error("[CAPS]: " + e.ToString()); + m_log.Error("[UPLOAD BAKED TEXTURE HANDLER]: " + e.ToString()); } return null; @@ -132,6 +132,8 @@ namespace OpenSim.Capabilities.Handlers class BakedTextureUploader { +// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + public event Action OnUpLoad; private string uploaderPath = String.Empty; @@ -156,10 +158,12 @@ namespace OpenSim.Capabilities.Handlers public string uploaderCaps(byte[] data, string path, string param) { Action handlerUpLoad = OnUpLoad; + + // Don't do this asynchronously, otherwise it's possible for the client to send set appearance information + // on another thread which might send out avatar updates before the asset has been put into the asset + // service. if (handlerUpLoad != null) - { - Util.FireAndForget(delegate(object o) { handlerUpLoad(newAssetID, data); }); - } + handlerUpLoad(newAssetID, data); string res = String.Empty; LLSDAssetUploadComplete uploadComplete = new LLSDAssetUploadComplete(); @@ -171,7 +175,7 @@ namespace OpenSim.Capabilities.Handlers httpListener.RemoveStreamHandler("POST", uploaderPath); - // m_log.InfoFormat("[CAPS] baked texture upload completed for {0}",newAssetID); +// m_log.DebugFormat("[BAKED TEXTURE UPLOADER]: baked texture upload completed for {0}", newAssetID); return res; } -- cgit v1.1