diff options
-rw-r--r-- | OpenSim/Capabilities/Handlers/GetMesh/GetMeshHandler.cs | 185 | ||||
-rw-r--r-- | OpenSim/Region/ClientStack/Linden/Caps/GetMeshModule.cs | 68 | ||||
-rw-r--r-- | bin/OpenSimDefaults.ini | 1 |
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; | |||
41 | using OpenSim.Services.Interfaces; | 41 | using OpenSim.Services.Interfaces; |
42 | using Caps = OpenSim.Framework.Capabilities.Caps; | 42 | using Caps = OpenSim.Framework.Capabilities.Caps; |
43 | 43 | ||
44 | |||
45 | |||
46 | |||
47 | namespace OpenSim.Capabilities.Handlers | 44 | namespace 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 = "" |