diff options
author | onefang | 2019-05-19 21:24:15 +1000 |
---|---|---|
committer | onefang | 2019-05-19 21:24:15 +1000 |
commit | 5e4d6cab00cb29cd088ab7b62ab13aff103b64cb (patch) | |
tree | a9fbc62df9eb2d1d9ba2698d8552eae71eca20d8 /OpenSim/Region/CoreModules/Scripting/LSLHttp | |
parent | Add a build script. (diff) | |
download | opensim-SC_OLD-5e4d6cab00cb29cd088ab7b62ab13aff103b64cb.zip opensim-SC_OLD-5e4d6cab00cb29cd088ab7b62ab13aff103b64cb.tar.gz opensim-SC_OLD-5e4d6cab00cb29cd088ab7b62ab13aff103b64cb.tar.bz2 opensim-SC_OLD-5e4d6cab00cb29cd088ab7b62ab13aff103b64cb.tar.xz |
Dump OpenSim 0.9.0.1 into it's own branch.
Diffstat (limited to 'OpenSim/Region/CoreModules/Scripting/LSLHttp')
-rw-r--r-- | OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs | 542 |
1 files changed, 326 insertions, 216 deletions
diff --git a/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs b/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs index 99a3122..11fc513 100644 --- a/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs | |||
@@ -26,10 +26,11 @@ | |||
26 | */ | 26 | */ |
27 | 27 | ||
28 | using System; | 28 | using System; |
29 | using System.Threading; | ||
30 | using System.Collections.Generic; | 29 | using System.Collections.Generic; |
31 | using System.Collections; | 30 | using System.Collections; |
32 | using System.Reflection; | 31 | using System.Reflection; |
32 | using System.Net; | ||
33 | using System.Net.Sockets; | ||
33 | using log4net; | 34 | using log4net; |
34 | using Mono.Addins; | 35 | using Mono.Addins; |
35 | using Nini.Config; | 36 | using Nini.Config; |
@@ -42,40 +43,17 @@ using OpenSim.Region.Framework.Scenes; | |||
42 | 43 | ||
43 | namespace OpenSim.Region.CoreModules.Scripting.LSLHttp | 44 | namespace OpenSim.Region.CoreModules.Scripting.LSLHttp |
44 | { | 45 | { |
45 | /// <summary> | ||
46 | /// Data describing an external URL set up by a script. | ||
47 | /// </summary> | ||
48 | public class UrlData | 46 | public class UrlData |
49 | { | 47 | { |
50 | /// <summary> | ||
51 | /// Scene object part hosting the script | ||
52 | /// </summary> | ||
53 | public UUID hostID; | 48 | public UUID hostID; |
54 | |||
55 | /// <summary> | ||
56 | /// The item ID of the script that requested the URL. | ||
57 | /// </summary> | ||
58 | public UUID itemID; | 49 | public UUID itemID; |
59 | |||
60 | /// <summary> | ||
61 | /// The script engine that runs the script. | ||
62 | /// </summary> | ||
63 | public IScriptModule engine; | 50 | public IScriptModule engine; |
64 | |||
65 | /// <summary> | ||
66 | /// The generated URL. | ||
67 | /// </summary> | ||
68 | public string url; | 51 | public string url; |
69 | |||
70 | /// <summary> | ||
71 | /// The random UUID component of the generated URL. | ||
72 | /// </summary> | ||
73 | public UUID urlcode; | 52 | public UUID urlcode; |
74 | |||
75 | /// <summary> | ||
76 | /// The external requests currently being processed or awaiting retrieval for this URL. | ||
77 | /// </summary> | ||
78 | public Dictionary<UUID, RequestData> requests; | 53 | public Dictionary<UUID, RequestData> requests; |
54 | public bool isSsl; | ||
55 | public Scene scene; | ||
56 | public bool allowXss; | ||
79 | } | 57 | } |
80 | 58 | ||
81 | public class RequestData | 59 | public class RequestData |
@@ -89,7 +67,11 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp | |||
89 | //public ManualResetEvent ev; | 67 | //public ManualResetEvent ev; |
90 | public bool requestDone; | 68 | public bool requestDone; |
91 | public int startTime; | 69 | public int startTime; |
70 | public bool responseSent; | ||
92 | public string uri; | 71 | public string uri; |
72 | public bool allowResponseType = false; | ||
73 | public UUID hostID; | ||
74 | public Scene scene; | ||
93 | } | 75 | } |
94 | 76 | ||
95 | /// <summary> | 77 | /// <summary> |
@@ -102,40 +84,33 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp | |||
102 | LogManager.GetLogger( | 84 | LogManager.GetLogger( |
103 | MethodBase.GetCurrentMethod().DeclaringType); | 85 | MethodBase.GetCurrentMethod().DeclaringType); |
104 | 86 | ||
105 | /// <summary> | 87 | protected Dictionary<UUID, UrlData> m_RequestMap = |
106 | /// Indexs the URL request metadata (which script requested it, outstanding requests, etc.) by the request ID | 88 | new Dictionary<UUID, UrlData>(); |
107 | /// randomly generated when a request is received for this URL. | ||
108 | /// </summary> | ||
109 | /// <remarks> | ||
110 | /// Manipulation or retrieval from this dictionary must be locked on m_UrlMap to preserve consistency with | ||
111 | /// m_UrlMap | ||
112 | /// </remarks> | ||
113 | private Dictionary<UUID, UrlData> m_RequestMap = new Dictionary<UUID, UrlData>(); | ||
114 | 89 | ||
115 | /// <summary> | 90 | protected Dictionary<string, UrlData> m_UrlMap = |
116 | /// Indexs the URL request metadata (which script requested it, outstanding requests, etc.) by the full URL | 91 | new Dictionary<string, UrlData>(); |
117 | /// </summary> | ||
118 | private Dictionary<string, UrlData> m_UrlMap = new Dictionary<string, UrlData>(); | ||
119 | 92 | ||
120 | private uint m_HttpsPort = 0; | 93 | protected bool m_enabled = false; |
121 | private IHttpServer m_HttpServer = null; | 94 | protected string m_ErrorStr; |
122 | private IHttpServer m_HttpsServer = null; | 95 | protected uint m_HttpsPort = 0; |
96 | protected IHttpServer m_HttpServer = null; | ||
97 | protected IHttpServer m_HttpsServer = null; | ||
123 | 98 | ||
124 | public string ExternalHostNameForLSL { get; private set; } | 99 | public string ExternalHostNameForLSL { get; protected set; } |
125 | 100 | ||
126 | /// <summary> | 101 | /// <summary> |
127 | /// The default maximum number of urls | 102 | /// The default maximum number of urls |
128 | /// </summary> | 103 | /// </summary> |
129 | public const int DefaultTotalUrls = 100; | 104 | public const int DefaultTotalUrls = 15000; |
130 | 105 | ||
131 | /// <summary> | 106 | /// <summary> |
132 | /// Maximum number of external urls that can be set up by this module. | 107 | /// Maximum number of external urls that can be set up by this module. |
133 | /// </summary> | 108 | /// </summary> |
134 | public int TotalUrls { get; set; } | 109 | public int TotalUrls { get; set; } |
135 | 110 | ||
136 | public Type ReplaceableInterface | 111 | public Type ReplaceableInterface |
137 | { | 112 | { |
138 | get { return null; } | 113 | get { return typeof(IUrlModule); } |
139 | } | 114 | } |
140 | 115 | ||
141 | public string Name | 116 | public string Name |
@@ -146,6 +121,7 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp | |||
146 | public void Initialise(IConfigSource config) | 121 | public void Initialise(IConfigSource config) |
147 | { | 122 | { |
148 | IConfig networkConfig = config.Configs["Network"]; | 123 | IConfig networkConfig = config.Configs["Network"]; |
124 | m_enabled = false; | ||
149 | 125 | ||
150 | if (networkConfig != null) | 126 | if (networkConfig != null) |
151 | { | 127 | { |
@@ -156,9 +132,31 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp | |||
156 | if (ssl_enabled) | 132 | if (ssl_enabled) |
157 | m_HttpsPort = (uint)config.Configs["Network"].GetInt("https_port", (int)m_HttpsPort); | 133 | m_HttpsPort = (uint)config.Configs["Network"].GetInt("https_port", (int)m_HttpsPort); |
158 | } | 134 | } |
135 | else | ||
136 | { | ||
137 | m_ErrorStr = "[Network] configuration missing, HTTP listener for LSL disabled"; | ||
138 | m_log.Warn("[URL MODULE]: " + m_ErrorStr); | ||
139 | return; | ||
140 | } | ||
159 | 141 | ||
160 | if (ExternalHostNameForLSL == null) | 142 | if (String.IsNullOrWhiteSpace(ExternalHostNameForLSL)) |
161 | ExternalHostNameForLSL = System.Environment.MachineName; | 143 | { |
144 | m_ErrorStr = "ExternalHostNameForLSL not defined in configuration, HTTP listener for LSL disabled"; | ||
145 | m_log.Warn("[URL MODULE]: " + m_ErrorStr); | ||
146 | return; | ||
147 | } | ||
148 | |||
149 | IPAddress ia = null; | ||
150 | ia = Util.GetHostFromDNS(ExternalHostNameForLSL); | ||
151 | if (ia == null) | ||
152 | { | ||
153 | m_ErrorStr = "Could not resolve ExternalHostNameForLSL, HTTP listener for LSL disabled"; | ||
154 | m_log.Warn("[URL MODULE]: " + m_ErrorStr); | ||
155 | return; | ||
156 | } | ||
157 | |||
158 | m_enabled = true; | ||
159 | m_ErrorStr = String.Empty; | ||
162 | 160 | ||
163 | IConfig llFunctionsConfig = config.Configs["LL-Functions"]; | 161 | IConfig llFunctionsConfig = config.Configs["LL-Functions"]; |
164 | 162 | ||
@@ -174,7 +172,7 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp | |||
174 | 172 | ||
175 | public void AddRegion(Scene scene) | 173 | public void AddRegion(Scene scene) |
176 | { | 174 | { |
177 | if (m_HttpServer == null) | 175 | if (m_enabled && m_HttpServer == null) |
178 | { | 176 | { |
179 | // There can only be one | 177 | // There can only be one |
180 | // | 178 | // |
@@ -204,21 +202,39 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp | |||
204 | 202 | ||
205 | public void RemoveRegion(Scene scene) | 203 | public void RemoveRegion(Scene scene) |
206 | { | 204 | { |
205 | // Drop references to that scene | ||
206 | foreach (KeyValuePair<string, UrlData> kvp in m_UrlMap) | ||
207 | { | ||
208 | if (kvp.Value.scene == scene) | ||
209 | kvp.Value.scene = null; | ||
210 | } | ||
211 | foreach (KeyValuePair<UUID, UrlData> kvp in m_RequestMap) | ||
212 | { | ||
213 | if (kvp.Value.scene == scene) | ||
214 | kvp.Value.scene = null; | ||
215 | } | ||
207 | } | 216 | } |
208 | 217 | ||
209 | public void Close() | 218 | public void Close() |
210 | { | 219 | { |
211 | } | 220 | } |
212 | 221 | ||
213 | public UUID RequestURL(IScriptModule engine, SceneObjectPart host, UUID itemID) | 222 | public UUID RequestURL(IScriptModule engine, SceneObjectPart host, UUID itemID, Hashtable options) |
214 | { | 223 | { |
215 | UUID urlcode = UUID.Random(); | 224 | UUID urlcode = UUID.Random(); |
216 | 225 | ||
226 | if(!m_enabled) | ||
227 | { | ||
228 | engine.PostScriptEvent(itemID, "http_request", new Object[] { urlcode.ToString(), "URL_REQUEST_DENIED", m_ErrorStr }); | ||
229 | return urlcode; | ||
230 | } | ||
231 | |||
217 | lock (m_UrlMap) | 232 | lock (m_UrlMap) |
218 | { | 233 | { |
219 | if (m_UrlMap.Count >= TotalUrls) | 234 | if (m_UrlMap.Count >= TotalUrls) |
220 | { | 235 | { |
221 | engine.PostScriptEvent(itemID, "http_request", new Object[] { urlcode.ToString(), "URL_REQUEST_DENIED", "" }); | 236 | engine.PostScriptEvent(itemID, "http_request", new Object[] { urlcode.ToString(), "URL_REQUEST_DENIED", |
237 | "Too many URLs already open" }); | ||
222 | return urlcode; | 238 | return urlcode; |
223 | } | 239 | } |
224 | string url = "http://" + ExternalHostNameForLSL + ":" + m_HttpServer.Port.ToString() + "/lslhttp/" + urlcode.ToString() + "/"; | 240 | string url = "http://" + ExternalHostNameForLSL + ":" + m_HttpServer.Port.ToString() + "/lslhttp/" + urlcode.ToString() + "/"; |
@@ -229,20 +245,26 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp | |||
229 | urlData.engine = engine; | 245 | urlData.engine = engine; |
230 | urlData.url = url; | 246 | urlData.url = url; |
231 | urlData.urlcode = urlcode; | 247 | urlData.urlcode = urlcode; |
248 | urlData.isSsl = false; | ||
232 | urlData.requests = new Dictionary<UUID, RequestData>(); | 249 | urlData.requests = new Dictionary<UUID, RequestData>(); |
233 | 250 | urlData.scene = host.ParentGroup.Scene; | |
251 | urlData.allowXss = false; | ||
252 | |||
253 | if (options != null && options["allowXss"] != null) | ||
254 | urlData.allowXss = true; | ||
255 | |||
234 | m_UrlMap[url] = urlData; | 256 | m_UrlMap[url] = urlData; |
235 | 257 | ||
236 | string uri = "/lslhttp/" + urlcode.ToString() + "/"; | 258 | string uri = "/lslhttp/" + urlcode.ToString() + "/"; |
237 | 259 | ||
238 | PollServiceEventArgs args | 260 | PollServiceEventArgs args |
239 | = new PollServiceEventArgs(HttpRequestHandler, uri, HasEvents, GetEvents, NoEvents, urlcode, 25000); | 261 | = new PollServiceEventArgs(HttpRequestHandler, uri, HasEvents, GetEvents, NoEvents, urlcode, 25000); |
240 | args.Type = PollServiceEventArgs.EventType.LslHttp; | 262 | args.Type = PollServiceEventArgs.EventType.LslHttp; |
241 | m_HttpServer.AddPollServiceHTTPHandler(uri, args); | 263 | m_HttpServer.AddPollServiceHTTPHandler(uri, args); |
242 | 264 | ||
243 | m_log.DebugFormat( | 265 | // m_log.DebugFormat( |
244 | "[URL MODULE]: Set up incoming request url {0} for {1} in {2} {3}", | 266 | // "[URL MODULE]: Set up incoming request url {0} for {1} in {2} {3}", |
245 | uri, itemID, host.Name, host.LocalId); | 267 | // uri, itemID, host.Name, host.LocalId); |
246 | 268 | ||
247 | engine.PostScriptEvent(itemID, "http_request", new Object[] { urlcode.ToString(), "URL_REQUEST_GRANTED", url }); | 269 | engine.PostScriptEvent(itemID, "http_request", new Object[] { urlcode.ToString(), "URL_REQUEST_GRANTED", url }); |
248 | } | 270 | } |
@@ -250,10 +272,16 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp | |||
250 | return urlcode; | 272 | return urlcode; |
251 | } | 273 | } |
252 | 274 | ||
253 | public UUID RequestSecureURL(IScriptModule engine, SceneObjectPart host, UUID itemID) | 275 | public UUID RequestSecureURL(IScriptModule engine, SceneObjectPart host, UUID itemID, Hashtable options) |
254 | { | 276 | { |
255 | UUID urlcode = UUID.Random(); | 277 | UUID urlcode = UUID.Random(); |
256 | 278 | ||
279 | if(!m_enabled) | ||
280 | { | ||
281 | engine.PostScriptEvent(itemID, "http_request", new Object[] { urlcode.ToString(), "URL_REQUEST_DENIED", m_ErrorStr }); | ||
282 | return urlcode; | ||
283 | } | ||
284 | |||
257 | if (m_HttpsServer == null) | 285 | if (m_HttpsServer == null) |
258 | { | 286 | { |
259 | engine.PostScriptEvent(itemID, "http_request", new Object[] { urlcode.ToString(), "URL_REQUEST_DENIED", "" }); | 287 | engine.PostScriptEvent(itemID, "http_request", new Object[] { urlcode.ToString(), "URL_REQUEST_DENIED", "" }); |
@@ -264,7 +292,8 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp | |||
264 | { | 292 | { |
265 | if (m_UrlMap.Count >= TotalUrls) | 293 | if (m_UrlMap.Count >= TotalUrls) |
266 | { | 294 | { |
267 | engine.PostScriptEvent(itemID, "http_request", new Object[] { urlcode.ToString(), "URL_REQUEST_DENIED", "" }); | 295 | engine.PostScriptEvent(itemID, "http_request", new Object[] { urlcode.ToString(), "URL_REQUEST_DENIED", |
296 | "Too many URLs already open" }); | ||
268 | return urlcode; | 297 | return urlcode; |
269 | } | 298 | } |
270 | string url = "https://" + ExternalHostNameForLSL + ":" + m_HttpsServer.Port.ToString() + "/lslhttps/" + urlcode.ToString() + "/"; | 299 | string url = "https://" + ExternalHostNameForLSL + ":" + m_HttpsServer.Port.ToString() + "/lslhttps/" + urlcode.ToString() + "/"; |
@@ -275,20 +304,25 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp | |||
275 | urlData.engine = engine; | 304 | urlData.engine = engine; |
276 | urlData.url = url; | 305 | urlData.url = url; |
277 | urlData.urlcode = urlcode; | 306 | urlData.urlcode = urlcode; |
307 | urlData.isSsl = true; | ||
278 | urlData.requests = new Dictionary<UUID, RequestData>(); | 308 | urlData.requests = new Dictionary<UUID, RequestData>(); |
309 | urlData.allowXss = false; | ||
310 | |||
311 | if (options != null && options["allowXss"] != null) | ||
312 | urlData.allowXss = true; | ||
279 | 313 | ||
280 | m_UrlMap[url] = urlData; | 314 | m_UrlMap[url] = urlData; |
281 | 315 | ||
282 | string uri = "/lslhttps/" + urlcode.ToString() + "/"; | 316 | string uri = "/lslhttps/" + urlcode.ToString() + "/"; |
283 | 317 | ||
284 | PollServiceEventArgs args | 318 | PollServiceEventArgs args |
285 | = new PollServiceEventArgs(HttpRequestHandler, uri, HasEvents, GetEvents, NoEvents, urlcode, 25000); | 319 | = new PollServiceEventArgs(HttpRequestHandler, uri, HasEvents, GetEvents, NoEvents, urlcode, 25000); |
286 | args.Type = PollServiceEventArgs.EventType.LslHttp; | 320 | args.Type = PollServiceEventArgs.EventType.LslHttp; |
287 | m_HttpsServer.AddPollServiceHTTPHandler(uri, args); | 321 | m_HttpsServer.AddPollServiceHTTPHandler(uri, args); |
288 | 322 | ||
289 | m_log.DebugFormat( | 323 | // m_log.DebugFormat( |
290 | "[URL MODULE]: Set up incoming secure request url {0} for {1} in {2} {3}", | 324 | // "[URL MODULE]: Set up incoming secure request url {0} for {1} in {2} {3}", |
291 | uri, itemID, host.Name, host.LocalId); | 325 | // uri, itemID, host.Name, host.LocalId); |
292 | 326 | ||
293 | engine.PostScriptEvent(itemID, "http_request", new Object[] { urlcode.ToString(), "URL_REQUEST_GRANTED", url }); | 327 | engine.PostScriptEvent(itemID, "http_request", new Object[] { urlcode.ToString(), "URL_REQUEST_GRANTED", url }); |
294 | } | 328 | } |
@@ -307,18 +341,21 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp | |||
307 | return; | 341 | return; |
308 | } | 342 | } |
309 | 343 | ||
310 | foreach (UUID req in data.requests.Keys) | 344 | lock (m_RequestMap) |
311 | m_RequestMap.Remove(req); | 345 | { |
346 | foreach (UUID req in data.requests.Keys) | ||
347 | m_RequestMap.Remove(req); | ||
348 | } | ||
312 | 349 | ||
313 | m_log.DebugFormat( | 350 | // m_log.DebugFormat( |
314 | "[URL MODULE]: Releasing url {0} for {1} in {2}", | 351 | // "[URL MODULE]: Releasing url {0} for {1} in {2}", |
315 | url, data.itemID, data.hostID); | 352 | // url, data.itemID, data.hostID); |
316 | 353 | ||
317 | RemoveUrl(data); | 354 | RemoveUrl(data); |
318 | m_UrlMap.Remove(url); | 355 | m_UrlMap.Remove(url); |
319 | } | 356 | } |
320 | } | 357 | } |
321 | 358 | ||
322 | public void HttpContentType(UUID request, string type) | 359 | public void HttpContentType(UUID request, string type) |
323 | { | 360 | { |
324 | lock (m_UrlMap) | 361 | lock (m_UrlMap) |
@@ -334,32 +371,42 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp | |||
334 | } | 371 | } |
335 | } | 372 | } |
336 | } | 373 | } |
337 | 374 | ||
338 | public void HttpResponse(UUID request, int status, string body) | 375 | public void HttpResponse(UUID request, int status, string body) |
339 | { | 376 | { |
340 | lock (m_UrlMap) | 377 | lock (m_RequestMap) |
341 | { | 378 | { |
342 | if (m_RequestMap.ContainsKey(request)) | 379 | if (m_RequestMap.ContainsKey(request)) |
343 | { | 380 | { |
344 | UrlData urlData = m_RequestMap[request]; | 381 | UrlData urlData = m_RequestMap[request]; |
345 | string responseBody = body; | 382 | if (!urlData.requests[request].responseSent) |
346 | if (urlData.requests[request].responseType.Equals("text/plain")) | ||
347 | { | 383 | { |
348 | string value; | 384 | string responseBody = body; |
349 | if (urlData.requests[request].headers.TryGetValue("user-agent", out value)) | 385 | |
386 | // If we have no OpenID from built-in browser, disable this | ||
387 | if (!urlData.requests[request].allowResponseType) | ||
388 | urlData.requests[request].responseType = "text/plain"; | ||
389 | |||
390 | if (urlData.requests[request].responseType.Equals("text/plain")) | ||
350 | { | 391 | { |
351 | if (value != null && value.IndexOf("MSIE") >= 0) | 392 | string value; |
393 | if (urlData.requests[request].headers.TryGetValue("user-agent", out value)) | ||
352 | { | 394 | { |
353 | // wrap the html escaped response if the target client is IE | 395 | if (value != null && value.IndexOf("MSIE") >= 0) |
354 | // It ignores "text/plain" if the body is html | 396 | { |
355 | responseBody = "<html>" + System.Web.HttpUtility.HtmlEncode(body) + "</html>"; | 397 | // wrap the html escaped response if the target client is IE |
398 | // It ignores "text/plain" if the body is html | ||
399 | responseBody = "<html>" + System.Web.HttpUtility.HtmlEncode(body) + "</html>"; | ||
400 | } | ||
356 | } | 401 | } |
357 | } | 402 | } |
403 | |||
404 | urlData.requests[request].responseCode = status; | ||
405 | urlData.requests[request].responseBody = responseBody; | ||
406 | //urlData.requests[request].ev.Set(); | ||
407 | urlData.requests[request].requestDone = true; | ||
408 | urlData.requests[request].responseSent = true; | ||
358 | } | 409 | } |
359 | urlData.requests[request].responseCode = status; | ||
360 | urlData.requests[request].responseBody = responseBody; | ||
361 | //urlData.requests[request].ev.Set(); | ||
362 | urlData.requests[request].requestDone =true; | ||
363 | } | 410 | } |
364 | else | 411 | else |
365 | { | 412 | { |
@@ -370,7 +417,7 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp | |||
370 | 417 | ||
371 | public string GetHttpHeader(UUID requestId, string header) | 418 | public string GetHttpHeader(UUID requestId, string header) |
372 | { | 419 | { |
373 | lock (m_UrlMap) | 420 | lock (m_RequestMap) |
374 | { | 421 | { |
375 | if (m_RequestMap.ContainsKey(requestId)) | 422 | if (m_RequestMap.ContainsKey(requestId)) |
376 | { | 423 | { |
@@ -384,7 +431,6 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp | |||
384 | m_log.Warn("[HttpRequestHandler] There was no http-in request with id " + requestId); | 431 | m_log.Warn("[HttpRequestHandler] There was no http-in request with id " + requestId); |
385 | } | 432 | } |
386 | } | 433 | } |
387 | |||
388 | return String.Empty; | 434 | return String.Empty; |
389 | } | 435 | } |
390 | 436 | ||
@@ -397,7 +443,7 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp | |||
397 | public void ScriptRemoved(UUID itemID) | 443 | public void ScriptRemoved(UUID itemID) |
398 | { | 444 | { |
399 | // m_log.DebugFormat("[URL MODULE]: Removing script {0}", itemID); | 445 | // m_log.DebugFormat("[URL MODULE]: Removing script {0}", itemID); |
400 | 446 | ||
401 | lock (m_UrlMap) | 447 | lock (m_UrlMap) |
402 | { | 448 | { |
403 | List<string> removeURLs = new List<string>(); | 449 | List<string> removeURLs = new List<string>(); |
@@ -408,8 +454,11 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp | |||
408 | { | 454 | { |
409 | RemoveUrl(url.Value); | 455 | RemoveUrl(url.Value); |
410 | removeURLs.Add(url.Key); | 456 | removeURLs.Add(url.Key); |
411 | foreach (UUID req in url.Value.requests.Keys) | 457 | lock (m_RequestMap) |
412 | m_RequestMap.Remove(req); | 458 | { |
459 | foreach (UUID req in url.Value.requests.Keys) | ||
460 | m_RequestMap.Remove(req); | ||
461 | } | ||
413 | } | 462 | } |
414 | } | 463 | } |
415 | 464 | ||
@@ -430,9 +479,11 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp | |||
430 | { | 479 | { |
431 | RemoveUrl(url.Value); | 480 | RemoveUrl(url.Value); |
432 | removeURLs.Add(url.Key); | 481 | removeURLs.Add(url.Key); |
433 | 482 | lock (m_RequestMap) | |
434 | foreach (UUID req in url.Value.requests.Keys) | 483 | { |
435 | m_RequestMap.Remove(req); | 484 | foreach (UUID req in url.Value.requests.Keys) |
485 | m_RequestMap.Remove(req); | ||
486 | } | ||
436 | } | 487 | } |
437 | } | 488 | } |
438 | 489 | ||
@@ -441,123 +492,131 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp | |||
441 | } | 492 | } |
442 | } | 493 | } |
443 | 494 | ||
444 | private void RemoveUrl(UrlData data) | 495 | |
496 | protected void RemoveUrl(UrlData data) | ||
445 | { | 497 | { |
446 | m_HttpServer.RemoveHTTPHandler("", "/lslhttp/" + data.urlcode.ToString() + "/"); | 498 | if (data.isSsl) |
499 | m_HttpsServer.RemoveHTTPHandler("", "/lslhttps/"+data.urlcode.ToString()+"/"); | ||
500 | else | ||
501 | m_HttpServer.RemoveHTTPHandler("", "/lslhttp/"+data.urlcode.ToString()+"/"); | ||
447 | } | 502 | } |
448 | 503 | ||
449 | private Hashtable NoEvents(UUID requestID, UUID sessionID) | 504 | protected Hashtable NoEvents(UUID requestID, UUID sessionID) |
450 | { | 505 | { |
451 | Hashtable response = new Hashtable(); | 506 | Hashtable response = new Hashtable(); |
452 | UrlData urlData; | 507 | UrlData url; |
453 | 508 | int startTime = 0; | |
454 | lock (m_UrlMap) | 509 | lock (m_RequestMap) |
455 | { | 510 | { |
456 | // We need to return a 404 here in case the request URL was removed at exactly the same time that a | ||
457 | // request was made. In this case, the request thread can outrace llRemoveURL() and still be polling | ||
458 | // for the request ID. | ||
459 | if (!m_RequestMap.ContainsKey(requestID)) | 511 | if (!m_RequestMap.ContainsKey(requestID)) |
460 | { | ||
461 | response["int_response_code"] = 404; | ||
462 | response["str_response_string"] = ""; | ||
463 | response["keepalive"] = false; | ||
464 | response["reusecontext"] = false; | ||
465 | |||
466 | return response; | 512 | return response; |
467 | } | 513 | url = m_RequestMap[requestID]; |
514 | startTime = url.requests[requestID].startTime; | ||
515 | } | ||
468 | 516 | ||
469 | urlData = m_RequestMap[requestID]; | 517 | if (System.Environment.TickCount - startTime > 25000) |
518 | { | ||
519 | response["int_response_code"] = 500; | ||
520 | response["str_response_string"] = "Script timeout"; | ||
521 | response["content_type"] = "text/plain"; | ||
522 | response["keepalive"] = false; | ||
523 | response["reusecontext"] = false; | ||
470 | 524 | ||
471 | if (System.Environment.TickCount - urlData.requests[requestID].startTime > 25000) | 525 | //remove from map |
526 | lock (url.requests) | ||
527 | { | ||
528 | url.requests.Remove(requestID); | ||
529 | } | ||
530 | lock (m_RequestMap) | ||
472 | { | 531 | { |
473 | response["int_response_code"] = 500; | ||
474 | response["str_response_string"] = "Script timeout"; | ||
475 | response["content_type"] = "text/plain"; | ||
476 | response["keepalive"] = false; | ||
477 | response["reusecontext"] = false; | ||
478 | |||
479 | //remove from map | ||
480 | urlData.requests.Remove(requestID); | ||
481 | m_RequestMap.Remove(requestID); | 532 | m_RequestMap.Remove(requestID); |
482 | |||
483 | return response; | ||
484 | } | 533 | } |
534 | |||
535 | return response; | ||
485 | } | 536 | } |
486 | 537 | ||
538 | |||
487 | return response; | 539 | return response; |
488 | } | 540 | } |
489 | 541 | ||
490 | private bool HasEvents(UUID requestID, UUID sessionID) | 542 | protected bool HasEvents(UUID requestID, UUID sessionID) |
491 | { | 543 | { |
492 | lock (m_UrlMap) | 544 | UrlData url=null; |
545 | |||
546 | lock (m_RequestMap) | ||
493 | { | 547 | { |
494 | // We return true here because an external URL request that happened at the same time as an llRemoveURL() | ||
495 | // can still make it through to HttpRequestHandler(). That will return without setting up a request | ||
496 | // when it detects that the URL has been removed. The poller, however, will continue to ask for | ||
497 | // events for that request, so here we will signal that there are events and in GetEvents we will | ||
498 | // return a 404. | ||
499 | if (!m_RequestMap.ContainsKey(requestID)) | 548 | if (!m_RequestMap.ContainsKey(requestID)) |
500 | { | 549 | { |
501 | return true; | 550 | return false; |
502 | } | 551 | } |
503 | 552 | url = m_RequestMap[requestID]; | |
504 | UrlData urlData = m_RequestMap[requestID]; | 553 | } |
505 | 554 | lock (url.requests) | |
506 | if (!urlData.requests.ContainsKey(requestID)) | 555 | { |
556 | if (!url.requests.ContainsKey(requestID)) | ||
507 | { | 557 | { |
508 | return true; | 558 | return false; |
509 | } | 559 | } |
510 | 560 | else | |
511 | // Trigger return of timeout response. | ||
512 | if (System.Environment.TickCount - urlData.requests[requestID].startTime > 25000) | ||
513 | { | 561 | { |
514 | return true; | 562 | if (System.Environment.TickCount - url.requests[requestID].startTime > 25000) |
563 | { | ||
564 | return true; | ||
565 | } | ||
566 | if (url.requests[requestID].requestDone) | ||
567 | return true; | ||
568 | else | ||
569 | return false; | ||
515 | } | 570 | } |
516 | |||
517 | return urlData.requests[requestID].requestDone; | ||
518 | } | 571 | } |
519 | } | 572 | } |
520 | 573 | protected Hashtable GetEvents(UUID requestID, UUID sessionID) | |
521 | private Hashtable GetEvents(UUID requestID, UUID sessionID) | ||
522 | { | 574 | { |
523 | Hashtable response; | 575 | UrlData url = null; |
576 | RequestData requestData = null; | ||
524 | 577 | ||
525 | lock (m_UrlMap) | 578 | lock (m_RequestMap) |
526 | { | 579 | { |
527 | UrlData url = null; | ||
528 | RequestData requestData = null; | ||
529 | |||
530 | if (!m_RequestMap.ContainsKey(requestID)) | 580 | if (!m_RequestMap.ContainsKey(requestID)) |
531 | return NoEvents(requestID, sessionID); | 581 | return NoEvents(requestID,sessionID); |
532 | |||
533 | url = m_RequestMap[requestID]; | 582 | url = m_RequestMap[requestID]; |
583 | } | ||
584 | lock (url.requests) | ||
585 | { | ||
534 | requestData = url.requests[requestID]; | 586 | requestData = url.requests[requestID]; |
587 | } | ||
535 | 588 | ||
536 | if (!requestData.requestDone) | 589 | if (!requestData.requestDone) |
537 | return NoEvents(requestID, sessionID); | 590 | return NoEvents(requestID,sessionID); |
538 | |||
539 | response = new Hashtable(); | ||
540 | 591 | ||
541 | if (System.Environment.TickCount - requestData.startTime > 25000) | 592 | Hashtable response = new Hashtable(); |
542 | { | ||
543 | response["int_response_code"] = 500; | ||
544 | response["str_response_string"] = "Script timeout"; | ||
545 | response["content_type"] = "text/plain"; | ||
546 | response["keepalive"] = false; | ||
547 | response["reusecontext"] = false; | ||
548 | return response; | ||
549 | } | ||
550 | 593 | ||
551 | //put response | 594 | if (System.Environment.TickCount - requestData.startTime > 25000) |
552 | response["int_response_code"] = requestData.responseCode; | 595 | { |
553 | response["str_response_string"] = requestData.responseBody; | 596 | response["int_response_code"] = 500; |
554 | response["content_type"] = requestData.responseType; | 597 | response["str_response_string"] = "Script timeout"; |
555 | // response["content_type"] = "text/plain"; | 598 | response["content_type"] = "text/plain"; |
556 | response["keepalive"] = false; | 599 | response["keepalive"] = false; |
557 | response["reusecontext"] = false; | 600 | response["reusecontext"] = false; |
558 | 601 | return response; | |
559 | //remove from map | 602 | } |
603 | //put response | ||
604 | response["int_response_code"] = requestData.responseCode; | ||
605 | response["str_response_string"] = requestData.responseBody; | ||
606 | response["content_type"] = requestData.responseType; | ||
607 | response["keepalive"] = false; | ||
608 | response["reusecontext"] = false; | ||
609 | |||
610 | if (url.allowXss) | ||
611 | response["access_control_allow_origin"] = "*"; | ||
612 | |||
613 | //remove from map | ||
614 | lock (url.requests) | ||
615 | { | ||
560 | url.requests.Remove(requestID); | 616 | url.requests.Remove(requestID); |
617 | } | ||
618 | lock (m_RequestMap) | ||
619 | { | ||
561 | m_RequestMap.Remove(requestID); | 620 | m_RequestMap.Remove(requestID); |
562 | } | 621 | } |
563 | 622 | ||
@@ -566,44 +625,49 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp | |||
566 | 625 | ||
567 | public void HttpRequestHandler(UUID requestID, Hashtable request) | 626 | public void HttpRequestHandler(UUID requestID, Hashtable request) |
568 | { | 627 | { |
569 | string uri = request["uri"].ToString(); | 628 | lock (request) |
570 | bool is_ssl = uri.Contains("lslhttps"); | ||
571 | |||
572 | try | ||
573 | { | 629 | { |
574 | Hashtable headers = (Hashtable)request["headers"]; | 630 | string uri = request["uri"].ToString(); |
631 | bool is_ssl = uri.Contains("lslhttps"); | ||
575 | 632 | ||
576 | // string uri_full = "http://" + m_ExternalHostNameForLSL + ":" + m_HttpServer.Port.ToString() + uri;// "/lslhttp/" + urlcode.ToString() + "/"; | 633 | try |
634 | { | ||
635 | Hashtable headers = (Hashtable)request["headers"]; | ||
577 | 636 | ||
578 | int pos1 = uri.IndexOf("/");// /lslhttp | 637 | // string uri_full = "http://" + ExternalHostNameForLSL + ":" + m_HttpServer.Port.ToString() + uri;// "/lslhttp/" + urlcode.ToString() + "/"; |
579 | int pos2 = uri.IndexOf("/", pos1 + 1);// /lslhttp/ | ||
580 | int pos3 = uri.IndexOf("/", pos2 + 1);// /lslhttp/<UUID>/ | ||
581 | string uri_tmp = uri.Substring(0, pos3 + 1); | ||
582 | //HTTP server code doesn't provide us with QueryStrings | ||
583 | string pathInfo; | ||
584 | string queryString; | ||
585 | queryString = ""; | ||
586 | 638 | ||
587 | pathInfo = uri.Substring(pos3); | 639 | int pos1 = uri.IndexOf("/");// /lslhttp |
640 | int pos2 = uri.IndexOf("/", pos1 + 1);// /lslhttp/ | ||
641 | int pos3 = uri.IndexOf("/", pos2 + 1); // /lslhttp/urlcode | ||
588 | 642 | ||
589 | UrlData urlData = null; | 643 | string uri_tmp = uri.Substring(0, pos3 + 1); |
644 | //HTTP server code doesn't provide us with QueryStrings | ||
645 | string pathInfo; | ||
646 | string queryString; | ||
647 | queryString = ""; | ||
590 | 648 | ||
591 | lock (m_UrlMap) | 649 | pathInfo = uri.Substring(pos3); |
592 | { | ||
593 | string url; | ||
594 | 650 | ||
595 | if (is_ssl) | 651 | UrlData url = null; |
596 | url = "https://" + ExternalHostNameForLSL + ":" + m_HttpsServer.Port.ToString() + uri_tmp; | 652 | string urlkey; |
653 | if (!is_ssl) | ||
654 | urlkey = "http://" + ExternalHostNameForLSL + ":" + m_HttpServer.Port.ToString() + uri_tmp; | ||
655 | //m_UrlMap[]; | ||
597 | else | 656 | else |
598 | url = "http://" + ExternalHostNameForLSL + ":" + m_HttpServer.Port.ToString() + uri_tmp; | 657 | urlkey = "https://" + ExternalHostNameForLSL + ":" + m_HttpsServer.Port.ToString() + uri_tmp; |
599 | 658 | ||
600 | // Avoid a race - the request URL may have been released via llRequestUrl() whilst this | 659 | if (m_UrlMap.ContainsKey(urlkey)) |
601 | // request was being processed. | 660 | { |
602 | if (!m_UrlMap.TryGetValue(url, out urlData)) | 661 | url = m_UrlMap[urlkey]; |
662 | } | ||
663 | else | ||
664 | { | ||
665 | //m_log.Warn("[HttpRequestHandler]: http-in request failed; no such url: "+urlkey.ToString()); | ||
603 | return; | 666 | return; |
667 | } | ||
604 | 668 | ||
605 | //for llGetHttpHeader support we need to store original URI here | 669 | //for llGetHttpHeader support we need to store original URI here |
606 | //to make x-path-info / x-query-string / x-script-url / x-remote-ip headers | 670 | //to make x-path-info / x-query-string / x-script-url / x-remote-ip headers |
607 | //as per http://wiki.secondlife.com/wiki/LlGetHTTPHeader | 671 | //as per http://wiki.secondlife.com/wiki/LlGetHTTPHeader |
608 | 672 | ||
609 | RequestData requestData = new RequestData(); | 673 | RequestData requestData = new RequestData(); |
@@ -611,6 +675,8 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp | |||
611 | requestData.requestDone = false; | 675 | requestData.requestDone = false; |
612 | requestData.startTime = System.Environment.TickCount; | 676 | requestData.startTime = System.Environment.TickCount; |
613 | requestData.uri = uri; | 677 | requestData.uri = uri; |
678 | requestData.hostID = url.hostID; | ||
679 | requestData.scene = url.scene; | ||
614 | if (requestData.headers == null) | 680 | if (requestData.headers == null) |
615 | requestData.headers = new Dictionary<string, string>(); | 681 | requestData.headers = new Dictionary<string, string>(); |
616 | 682 | ||
@@ -619,8 +685,33 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp | |||
619 | string key = (string)header.Key; | 685 | string key = (string)header.Key; |
620 | string value = (string)header.Value; | 686 | string value = (string)header.Value; |
621 | requestData.headers.Add(key, value); | 687 | requestData.headers.Add(key, value); |
688 | if (key == "cookie") | ||
689 | { | ||
690 | string[] parts = value.Split(new char[] {'='}); | ||
691 | if (parts[0] == "agni_sl_session_id" && parts.Length > 1) | ||
692 | { | ||
693 | string cookie = Uri.UnescapeDataString(parts[1]); | ||
694 | string[] crumbs = cookie.Split(new char[] {':'}); | ||
695 | UUID owner; | ||
696 | if (crumbs.Length == 2 && UUID.TryParse(crumbs[0], out owner)) | ||
697 | { | ||
698 | if (crumbs[1].Length == 32) | ||
699 | { | ||
700 | Scene scene = requestData.scene; | ||
701 | if (scene != null) | ||
702 | { | ||
703 | SceneObjectPart host = scene.GetSceneObjectPart(requestData.hostID); | ||
704 | if (host != null) | ||
705 | { | ||
706 | if (host.OwnerID == owner) | ||
707 | requestData.allowResponseType = true; | ||
708 | } | ||
709 | } | ||
710 | } | ||
711 | } | ||
712 | } | ||
713 | } | ||
622 | } | 714 | } |
623 | |||
624 | foreach (DictionaryEntry de in request) | 715 | foreach (DictionaryEntry de in request) |
625 | { | 716 | { |
626 | if (de.Key.ToString() == "querystringkeys") | 717 | if (de.Key.ToString() == "querystringkeys") |
@@ -631,13 +722,21 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp | |||
631 | if (request.ContainsKey(key)) | 722 | if (request.ContainsKey(key)) |
632 | { | 723 | { |
633 | string val = (String)request[key]; | 724 | string val = (String)request[key]; |
634 | queryString = queryString + key + "=" + val + "&"; | 725 | if (key != "") |
726 | { | ||
727 | queryString = queryString + key + "=" + val + "&"; | ||
728 | } | ||
729 | else | ||
730 | { | ||
731 | queryString = queryString + val + "&"; | ||
732 | } | ||
635 | } | 733 | } |
636 | } | 734 | } |
637 | |||
638 | if (queryString.Length > 1) | 735 | if (queryString.Length > 1) |
639 | queryString = queryString.Substring(0, queryString.Length - 1); | 736 | queryString = queryString.Substring(0, queryString.Length - 1); |
737 | |||
640 | } | 738 | } |
739 | |||
641 | } | 740 | } |
642 | 741 | ||
643 | //if this machine is behind DNAT/port forwarding, currently this is being | 742 | //if this machine is behind DNAT/port forwarding, currently this is being |
@@ -645,27 +744,38 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp | |||
645 | requestData.headers["x-remote-ip"] = requestData.headers["remote_addr"]; | 744 | requestData.headers["x-remote-ip"] = requestData.headers["remote_addr"]; |
646 | requestData.headers["x-path-info"] = pathInfo; | 745 | requestData.headers["x-path-info"] = pathInfo; |
647 | requestData.headers["x-query-string"] = queryString; | 746 | requestData.headers["x-query-string"] = queryString; |
648 | requestData.headers["x-script-url"] = urlData.url; | 747 | requestData.headers["x-script-url"] = url.url; |
649 | 748 | ||
650 | urlData.requests.Add(requestID, requestData); | 749 | //requestData.ev = new ManualResetEvent(false); |
651 | m_RequestMap.Add(requestID, urlData); | 750 | lock (url.requests) |
652 | } | 751 | { |
752 | url.requests.Add(requestID, requestData); | ||
753 | } | ||
754 | lock (m_RequestMap) | ||
755 | { | ||
756 | //add to request map | ||
757 | m_RequestMap.Add(requestID, url); | ||
758 | } | ||
653 | 759 | ||
654 | urlData.engine.PostScriptEvent( | 760 | url.engine.PostScriptEvent(url.itemID, "http_request", new Object[] { requestID.ToString(), request["http-method"].ToString(), request["body"].ToString() }); |
655 | urlData.itemID, | 761 | |
656 | "http_request", | 762 | //send initial response? |
657 | new Object[] { requestID.ToString(), request["http-method"].ToString(), request["body"].ToString() }); | 763 | // Hashtable response = new Hashtable(); |
658 | } | 764 | |
659 | catch (Exception we) | 765 | return; |
660 | { | 766 | |
661 | //Hashtable response = new Hashtable(); | 767 | } |
662 | m_log.Warn("[HttpRequestHandler]: http-in request failed"); | 768 | catch (Exception we) |
663 | m_log.Warn(we.Message); | 769 | { |
664 | m_log.Warn(we.StackTrace); | 770 | //Hashtable response = new Hashtable(); |
771 | m_log.Warn("[HttpRequestHandler]: http-in request failed"); | ||
772 | m_log.Warn(we.Message); | ||
773 | m_log.Warn(we.StackTrace); | ||
774 | } | ||
665 | } | 775 | } |
666 | } | 776 | } |
667 | 777 | ||
668 | private void OnScriptReset(uint localID, UUID itemID) | 778 | protected void OnScriptReset(uint localID, UUID itemID) |
669 | { | 779 | { |
670 | ScriptRemoved(itemID); | 780 | ScriptRemoved(itemID); |
671 | } | 781 | } |