From 5e4d6cab00cb29cd088ab7b62ab13aff103b64cb Mon Sep 17 00:00:00 2001
From: onefang
Date: Sun, 19 May 2019 21:24:15 +1000
Subject: Dump OpenSim 0.9.0.1 into it's own branch.
---
.../Handlers/GetMesh/GetMeshHandler.cs | 332 +++++++++++----------
1 file changed, 175 insertions(+), 157 deletions(-)
(limited to 'OpenSim/Capabilities/Handlers/GetMesh/GetMeshHandler.cs')
diff --git a/OpenSim/Capabilities/Handlers/GetMesh/GetMeshHandler.cs b/OpenSim/Capabilities/Handlers/GetMesh/GetMeshHandler.cs
index 6b67da1..a9b81f3 100644
--- a/OpenSim/Capabilities/Handlers/GetMesh/GetMeshHandler.cs
+++ b/OpenSim/Capabilities/Handlers/GetMesh/GetMeshHandler.cs
@@ -25,224 +25,242 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+using System;
+using System.Collections;
+using System.Collections.Specialized;
+using System.Reflection;
+using System.IO;
+using System.Web;
using log4net;
+using Nini.Config;
using OpenMetaverse;
-using OpenMetaverse.Imaging;
+using OpenMetaverse.StructuredData;
using OpenSim.Framework;
+using OpenSim.Framework.Servers;
using OpenSim.Framework.Servers.HttpServer;
using OpenSim.Services.Interfaces;
-using System;
-using System.Collections.Specialized;
-using System.Drawing;
-using System.Drawing.Imaging;
-using System.IO;
-using System.Reflection;
-using System.Web;
+using Caps = OpenSim.Framework.Capabilities.Caps;
+
+
+
namespace OpenSim.Capabilities.Handlers
{
- public class GetMeshHandler : BaseStreamHandler
+ public class GetMeshHandler
{
private static readonly ILog m_log =
- LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
+ LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
+
private IAssetService m_assetService;
- // TODO: Change this to a config option
- private string m_RedirectURL = null;
+ public const string DefaultFormat = "vnd.ll.mesh";
- public GetMeshHandler(string path, IAssetService assService, string name, string description, string redirectURL)
- : base("GET", path, name, description)
+ public GetMeshHandler(IAssetService assService)
{
m_assetService = assService;
- m_RedirectURL = redirectURL;
- if (m_RedirectURL != null && !m_RedirectURL.EndsWith("/"))
- m_RedirectURL += "/";
}
-
- protected override byte[] ProcessRequest(string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
+ public Hashtable Handle(Hashtable request)
{
- // Try to parse the texture ID from the request URL
- NameValueCollection query = HttpUtility.ParseQueryString(httpRequest.Url.Query);
- string textureStr = query.GetOne("mesh_id");
+ Hashtable ret = new Hashtable();
+ ret["int_response_code"] = (int)System.Net.HttpStatusCode.NotFound;
+ ret["content_type"] = "text/plain";
+ ret["keepalive"] = false;
+ ret["reusecontext"] = false;
+ ret["int_bytes"] = 0;
+ ret["int_lod"] = 0;
+ string MeshStr = (string)request["mesh_id"];
+
+
+ //m_log.DebugFormat("[GETMESH]: called {0}", MeshStr);
if (m_assetService == null)
{
- m_log.Error("[GETMESH]: Cannot fetch mesh " + textureStr + " without an asset service");
- httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound;
+ m_log.Error("[GETMESH]: Cannot fetch mesh " + MeshStr + " without an asset service");
}
UUID meshID;
- if (!String.IsNullOrEmpty(textureStr) && UUID.TryParse(textureStr, out meshID))
+ if (!String.IsNullOrEmpty(MeshStr) && UUID.TryParse(MeshStr, out meshID))
{
- // OK, we have an array with preferred formats, possibly with only one entry
-
- httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound;
- AssetBase mesh;
-
- if (!String.IsNullOrEmpty(m_RedirectURL))
- {
- // Only try to fetch locally cached meshes. Misses are redirected
- mesh = m_assetService.GetCached(meshID.ToString());
+ // m_log.DebugFormat("[GETMESH]: Received request for mesh id {0}", meshID);
- if (mesh != null)
- {
- if (mesh.Type != (sbyte)AssetType.Mesh)
- {
- httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound;
- }
- WriteMeshData(httpRequest, httpResponse, mesh);
- }
- else
- {
- string textureUrl = m_RedirectURL + "?mesh_id="+ meshID.ToString();
- m_log.Debug("[GETMESH]: Redirecting mesh request to " + textureUrl);
- httpResponse.StatusCode = (int)OSHttpStatusCode.RedirectMovedPermanently;
- httpResponse.RedirectLocation = textureUrl;
- return null;
- }
- }
- else // no redirect
- {
- // try the cache
- mesh = m_assetService.GetCached(meshID.ToString());
- if (mesh == null)
- {
- // Fetch locally or remotely. Misses return a 404
- mesh = m_assetService.Get(meshID.ToString());
+ ret = ProcessGetMesh(request, UUID.Zero, null);
- if (mesh != null)
- {
- if (mesh.Type != (sbyte)AssetType.Mesh)
- {
- httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound;
- return null;
- }
- WriteMeshData(httpRequest, httpResponse, mesh);
- return null;
- }
- }
- else // it was on the cache
- {
- if (mesh.Type != (sbyte)AssetType.Mesh)
- {
- httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound;
- return null;
- }
- WriteMeshData(httpRequest, httpResponse, mesh);
- return null;
- }
- }
- // not found
- httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound;
- return null;
}
else
{
- m_log.Warn("[GETTEXTURE]: Failed to parse a mesh_id from GetMesh request: " + httpRequest.Url);
+ m_log.Warn("[GETMESH]: Failed to parse a mesh_id from GetMesh request: " + (string)request["uri"]);
}
- return null;
- }
- private void WriteMeshData(IOSHttpRequest request, IOSHttpResponse response, AssetBase texture)
+ return ret;
+ }
+ public Hashtable ProcessGetMesh(Hashtable request, UUID AgentId, Caps cap)
{
- string range = request.Headers.GetOne("Range");
+ Hashtable responsedata = new Hashtable();
+ responsedata["int_response_code"] = 400; //501; //410; //404;
+ responsedata["content_type"] = "text/plain";
+ responsedata["keepalive"] = false;
+ responsedata["str_response_string"] = "Request wasn't what was expected";
+ responsedata["reusecontext"] = false;
+ responsedata["int_lod"] = 0;
+ responsedata["int_bytes"] = 0;
+
+ string meshStr = string.Empty;
- if (!String.IsNullOrEmpty(range))
+ if (request.ContainsKey("mesh_id"))
+ meshStr = request["mesh_id"].ToString();
+
+ UUID meshID = UUID.Zero;
+ if (!String.IsNullOrEmpty(meshStr) && UUID.TryParse(meshStr, out meshID))
{
- // Range request
- int start, end;
- if (TryParseRange(range, out start, out end))
+ if (m_assetService == null)
{
- // Before clamping start make sure we can satisfy it in order to avoid
- // sending back the last byte instead of an error status
- if (start >= texture.Data.Length)
- {
- response.StatusCode = (int)System.Net.HttpStatusCode.PartialContent;
- response.ContentType = texture.Metadata.ContentType;
- }
- else
+ responsedata["int_response_code"] = 404; //501; //410; //404;
+ responsedata["content_type"] = "text/plain";
+ responsedata["keepalive"] = false;
+ responsedata["str_response_string"] = "The asset service is unavailable. So is your mesh.";
+ responsedata["reusecontext"] = false;
+ return responsedata;
+ }
+
+ AssetBase mesh = m_assetService.Get(meshID.ToString());
+
+ if (mesh != null)
+ {
+ if (mesh.Type == (SByte)AssetType.Mesh)
{
- // Handle the case where no second range value was given. This is equivalent to requesting
- // the rest of the entity.
- if (end == -1)
- end = int.MaxValue;
- end = Utils.Clamp(end, 0, texture.Data.Length - 1);
- start = Utils.Clamp(start, 0, end);
- int len = end - start + 1;
+ Hashtable headers = new Hashtable();
+ responsedata["headers"] = headers;
+
+ string range = String.Empty;
+
+ if (((Hashtable)request["headers"])["range"] != null)
+ range = (string)((Hashtable)request["headers"])["range"];
- if (0 == start && len == texture.Data.Length)
+ else if (((Hashtable)request["headers"])["Range"] != null)
+ range = (string)((Hashtable)request["headers"])["Range"];
+
+ if (!String.IsNullOrEmpty(range)) // Mesh Asset LOD // Physics
{
- response.StatusCode = (int)System.Net.HttpStatusCode.OK;
+ // Range request
+ int start, end;
+ if (TryParseRange(range, out start, out end))
+ {
+ // Before clamping start make sure we can satisfy it in order to avoid
+ // sending back the last byte instead of an error status
+ if (start >= mesh.Data.Length)
+ {
+ responsedata["int_response_code"] = 404; //501; //410; //404;
+ responsedata["content_type"] = "text/plain";
+ responsedata["keepalive"] = false;
+ responsedata["str_response_string"] = "This range doesnt exist.";
+ responsedata["reusecontext"] = false;
+ responsedata["int_lod"] = 3;
+ return responsedata;
+ }
+ else
+ {
+ end = Utils.Clamp(end, 0, mesh.Data.Length - 1);
+ start = Utils.Clamp(start, 0, end);
+ int len = end - start + 1;
+
+ //m_log.Debug("Serving " + start + " to " + end + " of " + texture.Data.Length + " bytes for texture " + texture.ID);
+
+ if (start > 20000)
+ {
+ responsedata["int_lod"] = 3;
+ }
+ else if (start < 4097)
+ {
+ responsedata["int_lod"] = 1;
+ }
+ else
+ {
+ responsedata["int_lod"] = 2;
+ }
+
+
+ if (start == 0 && len == mesh.Data.Length) // well redudante maybe
+ {
+ responsedata["int_response_code"] = (int)System.Net.HttpStatusCode.OK;
+ responsedata["bin_response_data"] = mesh.Data;
+ responsedata["int_bytes"] = mesh.Data.Length;
+ responsedata["reusecontext"] = false;
+ responsedata["int_lod"] = 3;
+
+ }
+ else
+ {
+ responsedata["int_response_code"] =
+ (int)System.Net.HttpStatusCode.PartialContent;
+ headers["Content-Range"] = String.Format("bytes {0}-{1}/{2}", start, end,
+ mesh.Data.Length);
+
+ byte[] d = new byte[len];
+ Array.Copy(mesh.Data, start, d, 0, len);
+ responsedata["bin_response_data"] = d;
+ responsedata["int_bytes"] = len;
+ responsedata["reusecontext"] = false;
+ }
+ }
+ }
+ else
+ {
+ m_log.Warn("[GETMESH]: Failed to parse a range from GetMesh request, sending full asset: " + (string)request["uri"]);
+ responsedata["str_response_string"] = Convert.ToBase64String(mesh.Data);
+ responsedata["content_type"] = "application/vnd.ll.mesh";
+ responsedata["int_response_code"] = 200;
+ responsedata["reusecontext"] = false;
+ responsedata["int_lod"] = 3;
+ }
}
else
{
- response.StatusCode = (int)System.Net.HttpStatusCode.PartialContent;
- response.AddHeader("Content-Range", String.Format("bytes {0}-{1}/{2}", start, end, texture.Data.Length));
+ responsedata["str_response_string"] = Convert.ToBase64String(mesh.Data);
+ responsedata["content_type"] = "application/vnd.ll.mesh";
+ responsedata["int_response_code"] = 200;
+ responsedata["reusecontext"] = false;
+ responsedata["int_lod"] = 3;
}
-
- response.ContentLength = len;
- response.ContentType = "application/vnd.ll.mesh";
-
- response.Body.Write(texture.Data, start, len);
+ }
+ // Optionally add additional mesh types here
+ else
+ {
+ responsedata["int_response_code"] = 404; //501; //410; //404;
+ responsedata["content_type"] = "text/plain";
+ responsedata["keepalive"] = false;
+ responsedata["str_response_string"] = "Unfortunately, this asset isn't a mesh.";
+ responsedata["reusecontext"] = false;
+ responsedata["int_lod"] = 1;
+ return responsedata;
}
}
else
{
- m_log.Warn("[GETMESH]: Malformed Range header: " + range);
- response.StatusCode = (int)System.Net.HttpStatusCode.BadRequest;
+ responsedata["int_response_code"] = 404; //501; //410; //404;
+ responsedata["content_type"] = "text/plain";
+ responsedata["keepalive"] = false;
+ responsedata["str_response_string"] = "Your Mesh wasn't found. Sorry!";
+ responsedata["reusecontext"] = false;
+ responsedata["int_lod"] = 0;
+ return responsedata;
}
}
- else
- {
- // Full content request
- response.StatusCode = (int)System.Net.HttpStatusCode.OK;
- response.ContentLength = texture.Data.Length;
- response.ContentType = "application/vnd.ll.mesh";
- response.Body.Write(texture.Data, 0, texture.Data.Length);
- }
- }
- ///
- /// Parse a range header.
- ///
- ///
- /// As per http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html,
- /// this obeys range headers with two values (e.g. 533-4165) and no second value (e.g. 533-).
- /// Where there is no value, -1 is returned.
- /// FIXME: Need to cover the case where only a second value is specified (e.g. -4165), probably by returning -1
- /// for start.
- ///
- ///
- /// Start of the range. Undefined if this was not a number.
- /// End of the range. Will be -1 if no end specified. Undefined if there was a raw string but this was not a number.
+ return responsedata;
+ }
private bool TryParseRange(string header, out int start, out int end)
{
- start = end = 0;
-
if (header.StartsWith("bytes="))
{
string[] rangeValues = header.Substring(6).Split('-');
-
if (rangeValues.Length == 2)
{
- if (!Int32.TryParse(rangeValues[0], out start))
- return false;
-
- string rawEnd = rangeValues[1];
-
- if (rawEnd == "")
- {
- end = -1;
+ if (Int32.TryParse(rangeValues[0], out start) && Int32.TryParse(rangeValues[1], out end))
return true;
- }
- else if (Int32.TryParse(rawEnd, out end))
- {
- return true;
- }
}
}
--
cgit v1.1