aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--OpenSim/Capabilities/Handlers/GetMesh/GetMeshHandler.cs185
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/GetMeshModule.cs68
-rw-r--r--bin/OpenSimDefaults.ini1
3 files changed, 105 insertions, 149 deletions
diff --git a/OpenSim/Capabilities/Handlers/GetMesh/GetMeshHandler.cs b/OpenSim/Capabilities/Handlers/GetMesh/GetMeshHandler.cs
index 506f9d2..ed42efe 100644
--- a/OpenSim/Capabilities/Handlers/GetMesh/GetMeshHandler.cs
+++ b/OpenSim/Capabilities/Handlers/GetMesh/GetMeshHandler.cs
@@ -41,9 +41,6 @@ using OpenSim.Framework.Servers.HttpServer;
41using OpenSim.Services.Interfaces; 41using OpenSim.Services.Interfaces;
42using Caps = OpenSim.Framework.Capabilities.Caps; 42using Caps = OpenSim.Framework.Capabilities.Caps;
43 43
44
45
46
47namespace OpenSim.Capabilities.Handlers 44namespace OpenSim.Capabilities.Handlers
48{ 45{
49 public class GetMeshHandler 46 public class GetMeshHandler
@@ -61,145 +58,99 @@ namespace OpenSim.Capabilities.Handlers
61 } 58 }
62 public Hashtable Handle(Hashtable request) 59 public Hashtable Handle(Hashtable request)
63 { 60 {
64 Hashtable ret = new Hashtable(); 61 return ProcessGetMesh(request, UUID.Zero, null); ;
65 ret["int_response_code"] = (int)System.Net.HttpStatusCode.NotFound; 62 }
66 ret["content_type"] = "text/plain";
67 ret["int_bytes"] = 0;
68 string MeshStr = (string)request["mesh_id"];
69
70
71 //m_log.DebugFormat("[GETMESH]: called {0}", MeshStr);
72 63
64 public Hashtable ProcessGetMesh(Hashtable request, UUID AgentId, Caps cap)
65 {
66 Hashtable responsedata = new Hashtable();
73 if (m_assetService == null) 67 if (m_assetService == null)
74 { 68 {
75 m_log.Error("[GETMESH]: Cannot fetch mesh " + MeshStr + " without an asset service"); 69 responsedata["int_response_code"] = (int)System.Net.HttpStatusCode.ServiceUnavailable;
76 ret["keepalive"] = false; 70 responsedata["str_response_string"] = "The asset service is unavailable";
77 return ret; 71 responsedata["keepalive"] = false;
72 return responsedata;
78 } 73 }
79 74
80 UUID meshID; 75 responsedata["int_response_code"] = (int)System.Net.HttpStatusCode.BadRequest;
81 if (!String.IsNullOrEmpty(MeshStr) && UUID.TryParse(MeshStr, out meshID)) 76 responsedata["content_type"] = "text/plain";
82 { 77 responsedata["int_bytes"] = 0;
83 // m_log.DebugFormat("[GETMESH]: Received request for mesh id {0}", meshID);
84 78
79 string meshStr = string.Empty;
80 if (request.ContainsKey("mesh_id"))
81 meshStr = request["mesh_id"].ToString();
85 82
86 ret = ProcessGetMesh(request, UUID.Zero, null); 83 if (String.IsNullOrEmpty(meshStr))
84 return responsedata;
87 85
86 UUID meshID = UUID.Zero;
87 if(!UUID.TryParse(meshStr, out meshID))
88 return responsedata;
88 89
90 AssetBase mesh = m_assetService.Get(meshID.ToString());
91 if(mesh == null)
92 {
93 responsedata["int_response_code"] = (int)System.Net.HttpStatusCode.NotFound;
94 responsedata["str_response_string"] = "Mesh not found.";
95 return responsedata;
89 } 96 }
90 else 97
98 if (mesh.Type != (SByte)AssetType.Mesh)
91 { 99 {
92 m_log.Warn("[GETMESH]: Failed to parse a mesh_id from GetMesh request: " + (string)request["uri"]); 100 responsedata["str_response_string"] = "Asset isn't a mesh.";
101 return responsedata;
93 } 102 }
94 103
104 Hashtable headers = new Hashtable();
105 responsedata["headers"] = headers;
95 106
96 return ret; 107 string range = String.Empty;
97 }
98 public Hashtable ProcessGetMesh(Hashtable request, UUID AgentId, Caps cap)
99 {
100 Hashtable responsedata = new Hashtable();
101 responsedata["int_response_code"] = 400; //501; //410; //404;
102 responsedata["content_type"] = "text/plain";
103 responsedata["int_bytes"] = 0;
104 108
105 string meshStr = string.Empty; 109 if (((Hashtable)request["headers"])["range"] != null)
110 range = (string)((Hashtable)request["headers"])["range"];
111 else if (((Hashtable)request["headers"])["Range"] != null)
112 range = (string)((Hashtable)request["headers"])["Range"];
106 113
107 if (request.ContainsKey("mesh_id")) 114 if (String.IsNullOrEmpty(range))
108 meshStr = request["mesh_id"].ToString(); 115 {
116 // full mesh
117 responsedata["str_response_string"] = Convert.ToBase64String(mesh.Data);
118 responsedata["content_type"] = "application/vnd.ll.mesh";
119 responsedata["int_response_code"] = (int)System.Net.HttpStatusCode.OK;
120 return responsedata;
121 }
109 122
110 UUID meshID = UUID.Zero; 123 // range request
111 if (!String.IsNullOrEmpty(meshStr) && UUID.TryParse(meshStr, out meshID)) 124 int start, end;
125 if (TryParseRange(range, out start, out end))
112 { 126 {
113 if (m_assetService == null) 127 // Before clamping start make sure we can satisfy it in order to avoid
128 // sending back the last byte instead of an error status
129 if (start >= mesh.Data.Length)
114 { 130 {
115 responsedata["int_response_code"] = 404; //501; //410; //404; 131 responsedata["str_response_string"] = "This range doesnt exist.";
116 responsedata["keepalive"] = false;
117 responsedata["str_response_string"] = "The asset service is unavailable. So is your mesh.";
118 return responsedata; 132 return responsedata;
119 } 133 }
120 134
121 AssetBase mesh = m_assetService.Get(meshID.ToString()); 135 end = Utils.Clamp(end, 0, mesh.Data.Length - 1);
136 start = Utils.Clamp(start, 0, end);
137 int len = end - start + 1;
122 138
123 if (mesh != null) 139 //m_log.Debug("Serving " + start + " to " + end + " of " + texture.Data.Length + " bytes for texture " + texture.ID);
124 { 140 responsedata["int_response_code"] = (int)System.Net.HttpStatusCode.PartialContent;
125 if (mesh.Type == (SByte)AssetType.Mesh) 141 headers["Content-Range"] = String.Format("bytes {0}-{1}/{2}", start, end, mesh.Data.Length);
126 { 142
127 Hashtable headers = new Hashtable(); 143 byte[] d = new byte[len];
128 responsedata["headers"] = headers; 144 Array.Copy(mesh.Data, start, d, 0, len);
129 145 responsedata["bin_response_data"] = d;
130 string range = String.Empty; 146 responsedata["int_bytes"] = len;
131 147 return responsedata;
132 if (((Hashtable)request["headers"])["range"] != null)
133 range = (string)((Hashtable)request["headers"])["range"];
134
135 else if (((Hashtable)request["headers"])["Range"] != null)
136 range = (string)((Hashtable)request["headers"])["Range"];
137
138 if (!String.IsNullOrEmpty(range)) // Mesh Asset LOD // Physics
139 {
140 // Range request
141 int start, end;
142 if (TryParseRange(range, out start, out end))
143 {
144 // Before clamping start make sure we can satisfy it in order to avoid
145 // sending back the last byte instead of an error status
146 if (start >= mesh.Data.Length)
147 {
148 responsedata["int_response_code"] = 404; //501; //410; //404;
149 responsedata["content_type"] = "text/plain";
150 responsedata["str_response_string"] = "This range doesnt exist.";
151 return responsedata;
152 }
153 else
154 {
155 end = Utils.Clamp(end, 0, mesh.Data.Length - 1);
156 start = Utils.Clamp(start, 0, end);
157 int len = end - start + 1;
158
159 //m_log.Debug("Serving " + start + " to " + end + " of " + texture.Data.Length + " bytes for texture " + texture.ID);
160 responsedata["int_response_code"] =
161 (int)System.Net.HttpStatusCode.PartialContent;
162 headers["Content-Range"] = String.Format("bytes {0}-{1}/{2}", start, end, mesh.Data.Length);
163
164 byte[] d = new byte[len];
165 Array.Copy(mesh.Data, start, d, 0, len);
166 responsedata["bin_response_data"] = d;
167 responsedata["int_bytes"] = len;
168 }
169 }
170 else
171 {
172 m_log.Warn("[GETMESH]: Failed to parse a range from GetMesh request, sending full asset: " + (string)request["uri"]);
173 responsedata["str_response_string"] = Convert.ToBase64String(mesh.Data);
174 responsedata["content_type"] = "application/vnd.ll.mesh";
175 responsedata["int_response_code"] = 200;
176 }
177 }
178 else
179 {
180 responsedata["str_response_string"] = Convert.ToBase64String(mesh.Data);
181 responsedata["content_type"] = "application/vnd.ll.mesh";
182 responsedata["int_response_code"] = 200;
183 }
184 }
185 // Optionally add additional mesh types here
186 else
187 {
188 responsedata["int_response_code"] = 404; //501; //410; //404;
189 responsedata["content_type"] = "text/plain";
190 responsedata["str_response_string"] = "Unfortunately, this asset isn't a mesh.";
191 return responsedata;
192 }
193 }
194 else
195 {
196 responsedata["int_response_code"] = 404; //501; //410; //404;
197 responsedata["content_type"] = "text/plain";
198 responsedata["str_response_string"] = "Your Mesh wasn't found. Sorry!";
199 return responsedata;
200 }
201 } 148 }
202 149
150 m_log.Warn("[GETMESH]: Failed to parse a range from GetMesh request, sending full asset: " + (string)request["uri"]);
151 responsedata["str_response_string"] = Convert.ToBase64String(mesh.Data);
152 responsedata["content_type"] = "application/vnd.ll.mesh";
153 responsedata["int_response_code"] = (int)System.Net.HttpStatusCode.OK;
203 return responsedata; 154 return responsedata;
204 } 155 }
205 156
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/GetMeshModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/GetMeshModule.cs
index 754ec8b..b866e49 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/GetMeshModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/GetMeshModule.cs
@@ -56,10 +56,7 @@ namespace OpenSim.Region.ClientStack.Linden
56 private Scene m_scene; 56 private Scene m_scene;
57 private bool m_Enabled = true; 57 private bool m_Enabled = true;
58 private string m_URL; 58 private string m_URL;
59
60 private string m_URL2; 59 private string m_URL2;
61 private string m_RedirectURL = null;
62 private string m_RedirectURL2 = null;
63 60
64 class APollRequest 61 class APollRequest
65 { 62 {
@@ -81,12 +78,11 @@ namespace OpenSim.Region.ClientStack.Linden
81 private IAssetService m_assetService = null; 78 private IAssetService m_assetService = null;
82 79
83 private Dictionary<UUID, string> m_capsDict = new Dictionary<UUID, string>(); 80 private Dictionary<UUID, string> m_capsDict = new Dictionary<UUID, string>();
81 private Dictionary<UUID, string> m_capsDict2 = new Dictionary<UUID, string>();
84 private static Thread[] m_workerThreads = null; 82 private static Thread[] m_workerThreads = null;
85 private static int m_NumberScenes = 0; 83 private static int m_NumberScenes = 0;
86 private static BlockingCollection<APollRequest> m_queue = new BlockingCollection<APollRequest>(); 84 private static BlockingCollection<APollRequest> m_queue = new BlockingCollection<APollRequest>();
87 85
88 private Dictionary<UUID, PollServiceMeshEventArgs> m_pollservices = new Dictionary<UUID, PollServiceMeshEventArgs>();
89
90 #region Region Module interfaceBase Members 86 #region Region Module interfaceBase Members
91 87
92 public Type ReplaceableInterface 88 public Type ReplaceableInterface
@@ -103,19 +99,12 @@ namespace OpenSim.Region.ClientStack.Linden
103 m_URL = config.GetString("Cap_GetMesh", string.Empty); 99 m_URL = config.GetString("Cap_GetMesh", string.Empty);
104 // Cap doesn't exist 100 // Cap doesn't exist
105 if (m_URL != string.Empty) 101 if (m_URL != string.Empty)
106 {
107 m_Enabled = true; 102 m_Enabled = true;
108 m_RedirectURL = config.GetString("GetMeshRedirectURL");
109 }
110 103
111 m_URL2 = config.GetString("Cap_GetMesh2", string.Empty); 104 m_URL2 = config.GetString("Cap_GetMesh2", string.Empty);
112 // Cap doesn't exist 105 // Cap doesn't exist
113 if (m_URL2 != string.Empty) 106 if (m_URL2 != string.Empty)
114 {
115 m_Enabled = true; 107 m_Enabled = true;
116
117 m_RedirectURL2 = config.GetString("GetMesh2RedirectURL");
118 }
119 } 108 }
120 109
121 public void AddRegion(Scene pScene) 110 public void AddRegion(Scene pScene)
@@ -146,6 +135,12 @@ namespace OpenSim.Region.ClientStack.Linden
146 { 135 {
147 m_assetService = m_scene.RequestModuleInterface<IAssetService>(); 136 m_assetService = m_scene.RequestModuleInterface<IAssetService>();
148 // We'll reuse the same handler for all requests. 137 // We'll reuse the same handler for all requests.
138 if(m_assetService == null)
139 {
140 m_Enabled = false;
141 return;
142 }
143
149 m_getMeshHandler = new GetMeshHandler(m_assetService); 144 m_getMeshHandler = new GetMeshHandler(m_assetService);
150 } 145 }
151 146
@@ -355,49 +350,58 @@ namespace OpenSim.Region.ClientStack.Linden
355 350
356 public void RegisterCaps(UUID agentID, Caps caps) 351 public void RegisterCaps(UUID agentID, Caps caps)
357 { 352 {
358// UUID capID = UUID.Random(); 353 string hostName = m_scene.RegionInfo.ExternalHostName;
354 uint port = (MainServer.Instance == null) ? 0 : MainServer.Instance.Port;
355 string protocol = "http";
356 if (MainServer.Instance.UseSSL)
357 {
358 hostName = MainServer.Instance.SSLCommonName;
359 port = MainServer.Instance.SSLPort;
360 protocol = "https";
361 }
362
359 if (m_URL == "localhost") 363 if (m_URL == "localhost")
360 { 364 {
361 string capUrl = "/CAPS/" + UUID.Random() + "/"; 365 string capUrl = "/CAPS/" + UUID.Random() + "/";
362 366
363 // Register this as a poll service 367 // Register this as a poll service
364 PollServiceMeshEventArgs args = new PollServiceMeshEventArgs(capUrl, agentID, m_scene); 368 PollServiceMeshEventArgs args = new PollServiceMeshEventArgs(capUrl, agentID, m_scene);
365
366 args.Type = PollServiceEventArgs.EventType.Mesh; 369 args.Type = PollServiceEventArgs.EventType.Mesh;
367 MainServer.Instance.AddPollServiceHTTPHandler(capUrl, args); 370 MainServer.Instance.AddPollServiceHTTPHandler(capUrl, args);
368 371
369 string hostName = m_scene.RegionInfo.ExternalHostName;
370 uint port = (MainServer.Instance == null) ? 0 : MainServer.Instance.Port;
371 string protocol = "http";
372
373 if (MainServer.Instance.UseSSL)
374 {
375 hostName = MainServer.Instance.SSLCommonName;
376 port = MainServer.Instance.SSLPort;
377 protocol = "https";
378 }
379 caps.RegisterHandler("GetMesh", String.Format("{0}://{1}:{2}{3}", protocol, hostName, port, capUrl)); 372 caps.RegisterHandler("GetMesh", String.Format("{0}://{1}:{2}{3}", protocol, hostName, port, capUrl));
380 m_pollservices[agentID] = args;
381 m_capsDict[agentID] = capUrl; 373 m_capsDict[agentID] = capUrl;
382 } 374 }
383 else 375 else if (m_URL != string.Empty)
384 {
385 caps.RegisterHandler("GetMesh", m_URL); 376 caps.RegisterHandler("GetMesh", m_URL);
377
378 if (m_URL2 == "localhost")
379 {
380 string capUrl = "/CAPS/" + UUID.Random() + "/";
381
382 // Register this as a poll service
383 PollServiceMeshEventArgs args = new PollServiceMeshEventArgs(capUrl, agentID, m_scene);
384 args.Type = PollServiceEventArgs.EventType.Mesh;
385 MainServer.Instance.AddPollServiceHTTPHandler(capUrl, args);
386 caps.RegisterHandler("GetMesh2", String.Format("{0}://{1}:{2}{3}", protocol, hostName, port, capUrl));
387 m_capsDict2[agentID] = capUrl;
386 } 388 }
389 else if(m_URL2 != string.Empty)
390 caps.RegisterHandler("GetMesh2", m_URL2);
387 } 391 }
388 392
389 private void DeregisterCaps(UUID agentID, Caps caps) 393 private void DeregisterCaps(UUID agentID, Caps caps)
390 { 394 {
391 string capUrl; 395 string capUrl;
392 PollServiceMeshEventArgs args;
393 if (m_capsDict.TryGetValue(agentID, out capUrl)) 396 if (m_capsDict.TryGetValue(agentID, out capUrl))
394 { 397 {
395 MainServer.Instance.RemoveHTTPHandler("", capUrl); 398 MainServer.Instance.RemovePollServiceHTTPHandler("", capUrl);
396 m_capsDict.Remove(agentID); 399 m_capsDict.Remove(agentID);
397 } 400 }
398 if (m_pollservices.TryGetValue(agentID, out args)) 401 if (m_capsDict2.TryGetValue(agentID, out capUrl))
399 { 402 {
400 m_pollservices.Remove(agentID); 403 MainServer.Instance.RemovePollServiceHTTPHandler("", capUrl);
404 m_capsDict2.Remove(agentID);
401 } 405 }
402 } 406 }
403 } 407 }
diff --git a/bin/OpenSimDefaults.ini b/bin/OpenSimDefaults.ini
index da934c1..60db143 100644
--- a/bin/OpenSimDefaults.ini
+++ b/bin/OpenSimDefaults.ini
@@ -791,6 +791,7 @@
791 Cap_GetDisplayNames = "localhost" 791 Cap_GetDisplayNames = "localhost"
792 Cap_GetTexture = "localhost" 792 Cap_GetTexture = "localhost"
793 Cap_GetMesh = "localhost" 793 Cap_GetMesh = "localhost"
794 Cap_GetMesh2 = "localhost"
794 Cap_GetObjectCost = "" 795 Cap_GetObjectCost = ""
795 Cap_GetObjectPhysicsData = "" 796 Cap_GetObjectPhysicsData = ""
796 Cap_GroupProposalBallot = "" 797 Cap_GroupProposalBallot = ""