aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Capabilities/Handlers/GetMesh/GetMeshHandler.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Capabilities/Handlers/GetMesh/GetMeshHandler.cs')
-rw-r--r--OpenSim/Capabilities/Handlers/GetMesh/GetMeshHandler.cs271
1 files changed, 271 insertions, 0 deletions
diff --git a/OpenSim/Capabilities/Handlers/GetMesh/GetMeshHandler.cs b/OpenSim/Capabilities/Handlers/GetMesh/GetMeshHandler.cs
new file mode 100644
index 0000000..a9b81f3
--- /dev/null
+++ b/OpenSim/Capabilities/Handlers/GetMesh/GetMeshHandler.cs
@@ -0,0 +1,271 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections;
30using System.Collections.Specialized;
31using System.Reflection;
32using System.IO;
33using System.Web;
34using log4net;
35using Nini.Config;
36using OpenMetaverse;
37using OpenMetaverse.StructuredData;
38using OpenSim.Framework;
39using OpenSim.Framework.Servers;
40using OpenSim.Framework.Servers.HttpServer;
41using OpenSim.Services.Interfaces;
42using Caps = OpenSim.Framework.Capabilities.Caps;
43
44
45
46
47namespace OpenSim.Capabilities.Handlers
48{
49 public class GetMeshHandler
50 {
51 private static readonly ILog m_log =
52 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
53
54 private IAssetService m_assetService;
55
56 public const string DefaultFormat = "vnd.ll.mesh";
57
58 public GetMeshHandler(IAssetService assService)
59 {
60 m_assetService = assService;
61 }
62 public Hashtable Handle(Hashtable request)
63 {
64 Hashtable ret = new Hashtable();
65 ret["int_response_code"] = (int)System.Net.HttpStatusCode.NotFound;
66 ret["content_type"] = "text/plain";
67 ret["keepalive"] = false;
68 ret["reusecontext"] = false;
69 ret["int_bytes"] = 0;
70 ret["int_lod"] = 0;
71 string MeshStr = (string)request["mesh_id"];
72
73
74 //m_log.DebugFormat("[GETMESH]: called {0}", MeshStr);
75
76 if (m_assetService == null)
77 {
78 m_log.Error("[GETMESH]: Cannot fetch mesh " + MeshStr + " without an asset service");
79 }
80
81 UUID meshID;
82 if (!String.IsNullOrEmpty(MeshStr) && UUID.TryParse(MeshStr, out meshID))
83 {
84 // m_log.DebugFormat("[GETMESH]: Received request for mesh id {0}", meshID);
85
86
87 ret = ProcessGetMesh(request, UUID.Zero, null);
88
89
90 }
91 else
92 {
93 m_log.Warn("[GETMESH]: Failed to parse a mesh_id from GetMesh request: " + (string)request["uri"]);
94 }
95
96
97 return ret;
98 }
99 public Hashtable ProcessGetMesh(Hashtable request, UUID AgentId, Caps cap)
100 {
101 Hashtable responsedata = new Hashtable();
102 responsedata["int_response_code"] = 400; //501; //410; //404;
103 responsedata["content_type"] = "text/plain";
104 responsedata["keepalive"] = false;
105 responsedata["str_response_string"] = "Request wasn't what was expected";
106 responsedata["reusecontext"] = false;
107 responsedata["int_lod"] = 0;
108 responsedata["int_bytes"] = 0;
109
110 string meshStr = string.Empty;
111
112 if (request.ContainsKey("mesh_id"))
113 meshStr = request["mesh_id"].ToString();
114
115 UUID meshID = UUID.Zero;
116 if (!String.IsNullOrEmpty(meshStr) && UUID.TryParse(meshStr, out meshID))
117 {
118 if (m_assetService == null)
119 {
120 responsedata["int_response_code"] = 404; //501; //410; //404;
121 responsedata["content_type"] = "text/plain";
122 responsedata["keepalive"] = false;
123 responsedata["str_response_string"] = "The asset service is unavailable. So is your mesh.";
124 responsedata["reusecontext"] = false;
125 return responsedata;
126 }
127
128 AssetBase mesh = m_assetService.Get(meshID.ToString());
129
130 if (mesh != null)
131 {
132 if (mesh.Type == (SByte)AssetType.Mesh)
133 {
134
135 Hashtable headers = new Hashtable();
136 responsedata["headers"] = headers;
137
138 string range = String.Empty;
139
140 if (((Hashtable)request["headers"])["range"] != null)
141 range = (string)((Hashtable)request["headers"])["range"];
142
143 else if (((Hashtable)request["headers"])["Range"] != null)
144 range = (string)((Hashtable)request["headers"])["Range"];
145
146 if (!String.IsNullOrEmpty(range)) // Mesh Asset LOD // Physics
147 {
148 // Range request
149 int start, end;
150 if (TryParseRange(range, out start, out end))
151 {
152 // Before clamping start make sure we can satisfy it in order to avoid
153 // sending back the last byte instead of an error status
154 if (start >= mesh.Data.Length)
155 {
156 responsedata["int_response_code"] = 404; //501; //410; //404;
157 responsedata["content_type"] = "text/plain";
158 responsedata["keepalive"] = false;
159 responsedata["str_response_string"] = "This range doesnt exist.";
160 responsedata["reusecontext"] = false;
161 responsedata["int_lod"] = 3;
162 return responsedata;
163 }
164 else
165 {
166 end = Utils.Clamp(end, 0, mesh.Data.Length - 1);
167 start = Utils.Clamp(start, 0, end);
168 int len = end - start + 1;
169
170 //m_log.Debug("Serving " + start + " to " + end + " of " + texture.Data.Length + " bytes for texture " + texture.ID);
171
172 if (start > 20000)
173 {
174 responsedata["int_lod"] = 3;
175 }
176 else if (start < 4097)
177 {
178 responsedata["int_lod"] = 1;
179 }
180 else
181 {
182 responsedata["int_lod"] = 2;
183 }
184
185
186 if (start == 0 && len == mesh.Data.Length) // well redudante maybe
187 {
188 responsedata["int_response_code"] = (int)System.Net.HttpStatusCode.OK;
189 responsedata["bin_response_data"] = mesh.Data;
190 responsedata["int_bytes"] = mesh.Data.Length;
191 responsedata["reusecontext"] = false;
192 responsedata["int_lod"] = 3;
193
194 }
195 else
196 {
197 responsedata["int_response_code"] =
198 (int)System.Net.HttpStatusCode.PartialContent;
199 headers["Content-Range"] = String.Format("bytes {0}-{1}/{2}", start, end,
200 mesh.Data.Length);
201
202 byte[] d = new byte[len];
203 Array.Copy(mesh.Data, start, d, 0, len);
204 responsedata["bin_response_data"] = d;
205 responsedata["int_bytes"] = len;
206 responsedata["reusecontext"] = false;
207 }
208 }
209 }
210 else
211 {
212 m_log.Warn("[GETMESH]: Failed to parse a range from GetMesh request, sending full asset: " + (string)request["uri"]);
213 responsedata["str_response_string"] = Convert.ToBase64String(mesh.Data);
214 responsedata["content_type"] = "application/vnd.ll.mesh";
215 responsedata["int_response_code"] = 200;
216 responsedata["reusecontext"] = false;
217 responsedata["int_lod"] = 3;
218 }
219 }
220 else
221 {
222 responsedata["str_response_string"] = Convert.ToBase64String(mesh.Data);
223 responsedata["content_type"] = "application/vnd.ll.mesh";
224 responsedata["int_response_code"] = 200;
225 responsedata["reusecontext"] = false;
226 responsedata["int_lod"] = 3;
227 }
228 }
229 // Optionally add additional mesh types here
230 else
231 {
232 responsedata["int_response_code"] = 404; //501; //410; //404;
233 responsedata["content_type"] = "text/plain";
234 responsedata["keepalive"] = false;
235 responsedata["str_response_string"] = "Unfortunately, this asset isn't a mesh.";
236 responsedata["reusecontext"] = false;
237 responsedata["int_lod"] = 1;
238 return responsedata;
239 }
240 }
241 else
242 {
243 responsedata["int_response_code"] = 404; //501; //410; //404;
244 responsedata["content_type"] = "text/plain";
245 responsedata["keepalive"] = false;
246 responsedata["str_response_string"] = "Your Mesh wasn't found. Sorry!";
247 responsedata["reusecontext"] = false;
248 responsedata["int_lod"] = 0;
249 return responsedata;
250 }
251 }
252
253 return responsedata;
254 }
255 private bool TryParseRange(string header, out int start, out int end)
256 {
257 if (header.StartsWith("bytes="))
258 {
259 string[] rangeValues = header.Substring(6).Split('-');
260 if (rangeValues.Length == 2)
261 {
262 if (Int32.TryParse(rangeValues[0], out start) && Int32.TryParse(rangeValues[1], out end))
263 return true;
264 }
265 }
266
267 start = end = 0;
268 return false;
269 }
270 }
271} \ No newline at end of file