From 4df1d25d23d76ee3ae8c7da155462b57735f6418 Mon Sep 17 00:00:00 2001 From: Melanie Date: Thu, 9 Dec 2010 01:55:32 +0000 Subject: Plumb a code path for the entity transfer module to ask a destination scene whether or not an agent is allowed there as a root agent. --- .../Simulation/LocalSimulationConnector.cs | 17 +++++++++++++++++ .../Simulation/RemoteSimulationConnector.cs | 17 +++++++++++++++++ 2 files changed, 34 insertions(+) (limited to 'OpenSim/Region/CoreModules') diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs index e32dbb3..37b403e 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs @@ -257,6 +257,23 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation return false; } + public bool QueryAccess(GridRegion destination, UUID id) + { + if (destination == null) + return false; + + foreach (Scene s in m_sceneList) + { + if (s.RegionInfo.RegionHandle == destination.RegionHandle) + { + //m_log.Debug("[LOCAL COMMS]: Found region to send QueryAccess"); + return s.QueryAccess(id); + } + } + //m_log.Debug("[LOCAL COMMS]: region not found for QueryAccess"); + return false; + } + public bool ReleaseAgent(UUID origin, UUID id, string uri) { foreach (Scene s in m_sceneList) diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs index 3f577f2..387a9b8 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs @@ -239,6 +239,23 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation } + public bool QueryAccess(GridRegion destination, UUID id) + { + if (destination == null) + return false; + + // Try local first + if (m_localBackend.QueryAccess(destination, id)) + return true; + + // else do the remote thing + if (!m_localBackend.IsLocalRegion(destination.RegionHandle)) + return m_remoteConnector.QueryAccess(destination, id); + + return false; + + } + public bool ReleaseAgent(UUID origin, UUID id, string uri) { // Try local first -- cgit v1.1 From 1070cffcf905f77d694e140d0c9e978f5d0052c0 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Wed, 8 Dec 2010 18:53:15 -0800 Subject: Added ability for GetTexture to serve multiple formats. The format may come as an extra query parameter in the URL format= (this was tested and working) or it may come in the Accept header (code added, but not tested). The result of the conversion is placed in the asset cache, under the name -. --- .../CoreModules/Avatar/Assets/GetTextureModule.cs | 244 +++++++++++++++++---- 1 file changed, 202 insertions(+), 42 deletions(-) (limited to 'OpenSim/Region/CoreModules') diff --git a/OpenSim/Region/CoreModules/Avatar/Assets/GetTextureModule.cs b/OpenSim/Region/CoreModules/Avatar/Assets/GetTextureModule.cs index 97581e5..ac2ad7a 100644 --- a/OpenSim/Region/CoreModules/Avatar/Assets/GetTextureModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Assets/GetTextureModule.cs @@ -28,6 +28,8 @@ 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; @@ -35,6 +37,7 @@ using log4net; using Nini.Config; using OpenMetaverse; using OpenMetaverse.StructuredData; +using OpenMetaverse.Imaging; using OpenSim.Framework; using OpenSim.Framework.Servers; using OpenSim.Framework.Servers.HttpServer; @@ -74,6 +77,12 @@ namespace OpenSim.Region.CoreModules.Avatar.ObjectCaps private Scene m_scene; private IAssetService m_assetService; + public const string DefaultFormat = "x-j2c"; + + // TODO: Change this to a config option + const string REDIRECT_URL = null; + + #region IRegionModule Members public void Initialise(Scene pScene, IConfigSource pSource) @@ -96,7 +105,7 @@ namespace OpenSim.Region.CoreModules.Avatar.ObjectCaps { UUID capID = UUID.Random(); - m_log.Info("[GETTEXTURE]: /CAPS/" + capID); + m_log.InfoFormat("[GETTEXTURE]: /CAPS/{0} in region {1}", capID, m_scene.RegionInfo.RegionName); caps.RegisterHandler("GetTexture", new StreamHandler("GET", "/CAPS/" + capID, ProcessGetTexture)); } @@ -104,12 +113,12 @@ namespace OpenSim.Region.CoreModules.Avatar.ObjectCaps private byte[] ProcessGetTexture(string path, Stream request, OSHttpRequest httpRequest, OSHttpResponse httpResponse) { - // TODO: Change this to a config option - const string REDIRECT_URL = null; + //m_log.DebugFormat("[GETTEXTURE]: called in {0}", m_scene.RegionInfo.RegionName); // Try to parse the texture ID from the request URL NameValueCollection query = HttpUtility.ParseQueryString(httpRequest.Url.Query); string textureStr = query.GetOne("texture_id"); + string format = query.GetOne("format"); if (m_assetService == null) { @@ -121,33 +130,85 @@ namespace OpenSim.Region.CoreModules.Avatar.ObjectCaps UUID textureID; if (!String.IsNullOrEmpty(textureStr) && UUID.TryParse(textureStr, out textureID)) { - //m_log.DebugFormat("[GETTEXTURE]: {0}", textureID); - AssetBase texture; + string[] formats; + if (format != null && format != string.Empty) + { + formats = new string[1] { format.ToLower() }; + } + else + { + formats = WebUtil.GetPreferredImageTypes(httpRequest.Headers.Get("Accept")); + if (formats.Length == 0) + formats = new string[1] { DefaultFormat }; // default - if (!String.IsNullOrEmpty(REDIRECT_URL)) + } + // OK, we have an array with preferred formats, possibly with only one entry + + httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound; + foreach (string f in formats) { - // Only try to fetch locally cached textures. Misses are redirected - texture = m_assetService.GetCached(textureID.ToString()); + if (FetchTexture(httpRequest, httpResponse, textureID, f)) + break; + } - if (texture != null) - { - if (texture.Type != (sbyte)AssetType.Texture) - { - httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound; - httpResponse.Send(); - return null; - } - SendTexture(httpRequest, httpResponse, texture); - } - else + } + else + { + m_log.Warn("[GETTEXTURE]: Failed to parse a texture_id from GetTexture request: " + httpRequest.Url); + } + + httpResponse.Send(); + return null; + } + + /// + /// + /// + /// + /// + /// + /// + /// False for "caller try another codec"; true otherwise + private bool FetchTexture(OSHttpRequest httpRequest, OSHttpResponse httpResponse, UUID textureID, string format) + { + m_log.DebugFormat("[GETTEXTURE]: {0} with requested format {1}", textureID, format); + AssetBase texture; + + string fullID = textureID.ToString(); + if (format != DefaultFormat) + fullID = fullID + "-" + format; + + if (!String.IsNullOrEmpty(REDIRECT_URL)) + { + // Only try to fetch locally cached textures. Misses are redirected + texture = m_assetService.GetCached(fullID); + + if (texture != null) + { + if (texture.Type != (sbyte)AssetType.Texture) { - string textureUrl = REDIRECT_URL + textureID.ToString(); - m_log.Debug("[GETTEXTURE]: Redirecting texture request to " + textureUrl); - httpResponse.RedirectLocation = textureUrl; + httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound; + return true; } + WriteTextureData(httpRequest, httpResponse, texture, format); } else { + string textureUrl = REDIRECT_URL + textureID.ToString(); + m_log.Debug("[GETTEXTURE]: Redirecting texture request to " + textureUrl); + httpResponse.RedirectLocation = textureUrl; + return true; + } + } + else // no redirect + { + // try the cache + texture = m_assetService.GetCached(fullID); + + if (texture == null) + { + //m_log.DebugFormat("[GETTEXTURE]: texture was not in the cache"); + // Fetch locally or remotely. Misses return a 404 texture = m_assetService.Get(textureID.ToString()); @@ -156,32 +217,49 @@ namespace OpenSim.Region.CoreModules.Avatar.ObjectCaps if (texture.Type != (sbyte)AssetType.Texture) { httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound; - httpResponse.Send(); - return null; + return true; + } + if (format == DefaultFormat) + { + WriteTextureData(httpRequest, httpResponse, texture, format); + return true; + } + else + { + AssetBase newTexture = new AssetBase(texture.ID + "-" + format, texture.Name, (sbyte)AssetType.Texture, texture.CreatorID); + newTexture.Data = ConvertTextureData(texture, format); + if (newTexture.Data.Length == 0) + return false; // !!! Caller try another codec, please! + + newTexture.Flags = AssetFlags.Collectable; + newTexture.Temporary = true; + m_assetService.Store(newTexture); + WriteTextureData(httpRequest, httpResponse, newTexture, format); + return true; } - SendTexture(httpRequest, httpResponse, texture); - } - else - { - m_log.Warn("[GETTEXTURE]: Texture " + textureID + " not found"); - httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound; } - } - } - else - { - m_log.Warn("[GETTEXTURE]: Failed to parse a texture_id from GetTexture request: " + httpRequest.Url); + } + else // it was on the cache + { + //m_log.DebugFormat("[GETTEXTURE]: texture was in the cache"); + WriteTextureData(httpRequest, httpResponse, texture, format); + return true; + } + } - httpResponse.Send(); - return null; + // not found + m_log.Warn("[GETTEXTURE]: Texture " + textureID + " not found"); + httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound; + return true; + } - private void SendTexture(OSHttpRequest request, OSHttpResponse response, AssetBase texture) + private void WriteTextureData(OSHttpRequest request, OSHttpResponse response, AssetBase texture, string format) { string range = request.Headers.GetOne("Range"); //m_log.DebugFormat("[GETTEXTURE]: Range {0}", range); - if (!String.IsNullOrEmpty(range)) + if (!String.IsNullOrEmpty(range)) // JP2's only { // Range request int start, end; @@ -212,15 +290,19 @@ namespace OpenSim.Region.CoreModules.Avatar.ObjectCaps } else { - m_log.Warn("Malformed Range header: " + range); + m_log.Warn("[GETTEXTURE]: Malformed Range header: " + range); response.StatusCode = (int)System.Net.HttpStatusCode.BadRequest; } } - else + else // JP2's or other formats { // Full content request + response.StatusCode = (int)System.Net.HttpStatusCode.OK; response.ContentLength = texture.Data.Length; - response.ContentType = texture.Metadata.ContentType; + if (format == DefaultFormat) + response.ContentType = texture.Metadata.ContentType; + else + response.ContentType = "image/" + format; response.Body.Write(texture.Data, 0, texture.Data.Length); } } @@ -240,5 +322,83 @@ namespace OpenSim.Region.CoreModules.Avatar.ObjectCaps start = end = 0; return false; } + + + private byte[] ConvertTextureData(AssetBase texture, string format) + { + m_log.DebugFormat("[GETTEXTURE]: Converting texture {0} to {1}", texture.ID, format); + byte[] data = new byte[0]; + + MemoryStream imgstream = new MemoryStream(); + Bitmap mTexture = new Bitmap(1, 1); + ManagedImage managedImage; + Image image = (Image)mTexture; + + try + { + // Taking our jpeg2000 data, decoding it, then saving it to a byte array with regular jpeg data + + imgstream = new MemoryStream(); + + // Decode image to System.Drawing.Image + if (OpenJPEG.DecodeToImage(texture.Data, out managedImage, out image)) + { + // Save to bitmap + mTexture = new Bitmap(image); + + EncoderParameters myEncoderParameters = new EncoderParameters(); + myEncoderParameters.Param[0] = new EncoderParameter(Encoder.Quality, 95L); + + // Save bitmap to stream + ImageCodecInfo codec = GetEncoderInfo("image/" + format); + if (codec != null) + { + mTexture.Save(imgstream, codec, myEncoderParameters); + // Write the stream to a byte array for output + data = imgstream.ToArray(); + } + else + m_log.WarnFormat("[GETTEXTURE]: No such codec {0}", format); + + } + } + catch (Exception e) + { + m_log.WarnFormat("[GETTEXTURE]: Unable to convert texture {0} to {1}: {2}", texture.ID, format, e.Message); + } + finally + { + // Reclaim memory, these are unmanaged resources + // If we encountered an exception, one or more of these will be null + if (mTexture != null) + mTexture.Dispose(); + + if (image != null) + image.Dispose(); + + if (imgstream != null) + { + imgstream.Close(); + imgstream.Dispose(); + } + } + + return data; + } + + // From msdn + private static ImageCodecInfo GetEncoderInfo(String mimeType) + { + ImageCodecInfo[] encoders; + encoders = ImageCodecInfo.GetImageEncoders(); + for (int j = 0; j < encoders.Length; ++j) + { + if (encoders[j].MimeType == mimeType) + return encoders[j]; + } + return null; + } + + } } -- cgit v1.1