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.cs194
1 files changed, 164 insertions, 30 deletions
diff --git a/OpenSim/Capabilities/Handlers/GetMesh/GetMeshHandler.cs b/OpenSim/Capabilities/Handlers/GetMesh/GetMeshHandler.cs
index 6b67da1..7fcc798 100644
--- a/OpenSim/Capabilities/Handlers/GetMesh/GetMeshHandler.cs
+++ b/OpenSim/Capabilities/Handlers/GetMesh/GetMeshHandler.cs
@@ -44,26 +44,64 @@ namespace OpenSim.Capabilities.Handlers
44 public class GetMeshHandler : BaseStreamHandler 44 public class GetMeshHandler : BaseStreamHandler
45 { 45 {
46 private static readonly ILog m_log = 46 private static readonly ILog m_log =
47 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 47 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
48
48 private IAssetService m_assetService; 49 private IAssetService m_assetService;
49 50
50 // TODO: Change this to a config option 51 public const string DefaultFormat = "vnd.ll.mesh";
51 private string m_RedirectURL = null; 52
52 53 public GetMeshHandler(IAssetService assService)
53 public GetMeshHandler(string path, IAssetService assService, string name, string description, string redirectURL)
54 : base("GET", path, name, description)
55 { 54 {
56 m_assetService = assService; 55 m_assetService = assService;
57 m_RedirectURL = redirectURL; 56 m_RedirectURL = redirectURL;
58 if (m_RedirectURL != null && !m_RedirectURL.EndsWith("/")) 57 if (m_RedirectURL != null && !m_RedirectURL.EndsWith("/"))
59 m_RedirectURL += "/"; 58 m_RedirectURL += "/";
60 } 59 }
60 public Hashtable Handle(Hashtable request)
61 {
62 Hashtable ret = new Hashtable();
63 ret["int_response_code"] = (int)System.Net.HttpStatusCode.NotFound;
64 ret["content_type"] = "text/plain";
65 ret["keepalive"] = false;
66 ret["reusecontext"] = false;
67 ret["int_bytes"] = 0;
68 ret["int_lod"] = 0;
69 string MeshStr = (string)request["mesh_id"];
70
71
72 //m_log.DebugFormat("[GETMESH]: called {0}", MeshStr);
73
74 if (m_assetService == null)
75 {
76 m_log.Error("[GETMESH]: Cannot fetch mesh " + MeshStr + " without an asset service");
77 }
78
79 UUID meshID;
80 if (!String.IsNullOrEmpty(MeshStr) && UUID.TryParse(MeshStr, out meshID))
81 {
82 // m_log.DebugFormat("[GETMESH]: Received request for mesh id {0}", meshID);
83
84
85 ret = ProcessGetMesh(request, UUID.Zero, null);
86
87
88 }
89 else
90 {
91 m_log.Warn("[GETMESH]: Failed to parse a mesh_id from GetMesh request: " + (string)request["uri"]);
92 }
61 93
62 protected override byte[] ProcessRequest(string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) 94
95 return ret;
96 }
97 public Hashtable ProcessGetMesh(Hashtable request, UUID AgentId, Caps cap)
63 { 98 {
64 // Try to parse the texture ID from the request URL 99 // Try to parse the texture ID from the request URL
65 NameValueCollection query = HttpUtility.ParseQueryString(httpRequest.Url.Query); 100 NameValueCollection query = HttpUtility.ParseQueryString(httpRequest.Url.Query);
66 string textureStr = query.GetOne("mesh_id"); 101 string textureStr = query.GetOne("mesh_id");
102 responsedata["reusecontext"] = false;
103 responsedata["int_lod"] = 0;
104 responsedata["int_bytes"] = 0;
67 105
68 if (m_assetService == null) 106 if (m_assetService == null)
69 { 107 {
@@ -160,40 +198,121 @@ namespace OpenSim.Capabilities.Handlers
160 // sending back the last byte instead of an error status 198 // sending back the last byte instead of an error status
161 if (start >= texture.Data.Length) 199 if (start >= texture.Data.Length)
162 { 200 {
163 response.StatusCode = (int)System.Net.HttpStatusCode.PartialContent;
164 response.ContentType = texture.Metadata.ContentType;
165 }
166 else
167 {
168 // Handle the case where no second range value was given. This is equivalent to requesting
169 // the rest of the entity.
170 if (end == -1)
171 end = int.MaxValue;
172 201
173 end = Utils.Clamp(end, 0, texture.Data.Length - 1); 202 Hashtable headers = new Hashtable();
174 start = Utils.Clamp(start, 0, end); 203 responsedata["headers"] = headers;
175 int len = end - start + 1; 204
205 string range = String.Empty;
206
207 if (((Hashtable)request["headers"])["range"] != null)
208 range = (string)((Hashtable)request["headers"])["range"];
176 209
177 if (0 == start && len == texture.Data.Length) 210 else if (((Hashtable)request["headers"])["Range"] != null)
211 range = (string)((Hashtable)request["headers"])["Range"];
212
213 if (!String.IsNullOrEmpty(range)) // Mesh Asset LOD // Physics
178 { 214 {
179 response.StatusCode = (int)System.Net.HttpStatusCode.OK; 215 // Range request
216 int start, end;
217 if (TryParseRange(range, out start, out end))
218 {
219 // Before clamping start make sure we can satisfy it in order to avoid
220 // sending back the last byte instead of an error status
221 if (start >= mesh.Data.Length)
222 {
223 responsedata["int_response_code"] = 404; //501; //410; //404;
224 responsedata["content_type"] = "text/plain";
225 responsedata["keepalive"] = false;
226 responsedata["str_response_string"] = "This range doesnt exist.";
227 responsedata["reusecontext"] = false;
228 responsedata["int_lod"] = 3;
229 return responsedata;
230 }
231 else
232 {
233 end = Utils.Clamp(end, 0, mesh.Data.Length - 1);
234 start = Utils.Clamp(start, 0, end);
235 int len = end - start + 1;
236
237 //m_log.Debug("Serving " + start + " to " + end + " of " + texture.Data.Length + " bytes for texture " + texture.ID);
238
239 if (start > 20000)
240 {
241 responsedata["int_lod"] = 3;
242 }
243 else if (start < 4097)
244 {
245 responsedata["int_lod"] = 1;
246 }
247 else
248 {
249 responsedata["int_lod"] = 2;
250 }
251
252
253 if (start == 0 && len == mesh.Data.Length) // well redudante maybe
254 {
255 responsedata["int_response_code"] = (int) System.Net.HttpStatusCode.OK;
256 responsedata["bin_response_data"] = mesh.Data;
257 responsedata["int_bytes"] = mesh.Data.Length;
258 responsedata["reusecontext"] = false;
259 responsedata["int_lod"] = 3;
260
261 }
262 else
263 {
264 responsedata["int_response_code"] =
265 (int) System.Net.HttpStatusCode.PartialContent;
266 headers["Content-Range"] = String.Format("bytes {0}-{1}/{2}", start, end,
267 mesh.Data.Length);
268
269 byte[] d = new byte[len];
270 Array.Copy(mesh.Data, start, d, 0, len);
271 responsedata["bin_response_data"] = d;
272 responsedata["int_bytes"] = len;
273 responsedata["reusecontext"] = false;
274 }
275 }
276 }
277 else
278 {
279 m_log.Warn("[GETMESH]: Failed to parse a range from GetMesh request, sending full asset: " + (string)request["uri"]);
280 responsedata["str_response_string"] = Convert.ToBase64String(mesh.Data);
281 responsedata["content_type"] = "application/vnd.ll.mesh";
282 responsedata["int_response_code"] = 200;
283 responsedata["reusecontext"] = false;
284 responsedata["int_lod"] = 3;
285 }
180 } 286 }
181 else 287 else
182 { 288 {
183 response.StatusCode = (int)System.Net.HttpStatusCode.PartialContent; 289 responsedata["str_response_string"] = Convert.ToBase64String(mesh.Data);
184 response.AddHeader("Content-Range", String.Format("bytes {0}-{1}/{2}", start, end, texture.Data.Length)); 290 responsedata["content_type"] = "application/vnd.ll.mesh";
291 responsedata["int_response_code"] = 200;
292 responsedata["reusecontext"] = false;
293 responsedata["int_lod"] = 3;
185 } 294 }
186 295 }
187 response.ContentLength = len; 296 else
188 response.ContentType = "application/vnd.ll.mesh"; 297 {
189 298 responsedata["int_response_code"] = 404; //501; //410; //404;
190 response.Body.Write(texture.Data, start, len); 299 responsedata["content_type"] = "text/plain";
300 responsedata["keepalive"] = false;
301 responsedata["str_response_string"] = "Unfortunately, this asset isn't a mesh.";
302 responsedata["reusecontext"] = false;
303 responsedata["int_lod"] = 1;
304 return responsedata;
191 } 305 }
192 } 306 }
193 else 307 else
194 { 308 {
195 m_log.Warn("[GETMESH]: Malformed Range header: " + range); 309 responsedata["int_response_code"] = 404; //501; //410; //404;
196 response.StatusCode = (int)System.Net.HttpStatusCode.BadRequest; 310 responsedata["content_type"] = "text/plain";
311 responsedata["keepalive"] = false;
312 responsedata["str_response_string"] = "Your Mesh wasn't found. Sorry!";
313 responsedata["reusecontext"] = false;
314 responsedata["int_lod"] = 0;
315 return responsedata;
197 } 316 }
198 } 317 }
199 else 318 else
@@ -249,5 +368,20 @@ namespace OpenSim.Capabilities.Handlers
249 start = end = 0; 368 start = end = 0;
250 return false; 369 return false;
251 } 370 }
371 private bool TryParseRange(string header, out int start, out int end)
372 {
373 if (header.StartsWith("bytes="))
374 {
375 string[] rangeValues = header.Substring(6).Split('-');
376 if (rangeValues.Length == 2)
377 {
378 if (Int32.TryParse(rangeValues[0], out start) && Int32.TryParse(rangeValues[1], out end))
379 return true;
380 }
381 }
382
383 start = end = 0;
384 return false;
385 }
252 } 386 }
253} \ No newline at end of file 387} \ No newline at end of file