diff options
Diffstat (limited to 'OpenSim/Region/CoreModules/Scripting')
3 files changed, 262 insertions, 232 deletions
diff --git a/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs b/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs index d328eb3..9dac6b9 100644 --- a/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs +++ b/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs | |||
@@ -382,6 +382,10 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest | |||
382 | try | 382 | try |
383 | { | 383 | { |
384 | Request = (HttpWebRequest) WebRequest.Create(Url); | 384 | Request = (HttpWebRequest) WebRequest.Create(Url); |
385 | |||
386 | //This works around some buggy HTTP Servers like Lighttpd | ||
387 | Request.ServicePoint.Expect100Continue = false; | ||
388 | |||
385 | Request.Method = HttpMethod; | 389 | Request.Method = HttpMethod; |
386 | Request.ContentType = HttpMIMEType; | 390 | Request.ContentType = HttpMIMEType; |
387 | 391 | ||
@@ -458,15 +462,36 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest | |||
458 | 462 | ||
459 | // continue building the string | 463 | // continue building the string |
460 | sb.Append(tempString); | 464 | sb.Append(tempString); |
465 | if (sb.Length > 2048) | ||
466 | break; | ||
461 | } | 467 | } |
462 | } while (count > 0); // any more data to read? | 468 | } while (count > 0); // any more data to read? |
463 | 469 | ||
464 | ResponseBody = sb.ToString(); | 470 | ResponseBody = sb.ToString().Replace("\r", ""); |
465 | } | 471 | } |
466 | catch (Exception e) | 472 | catch (Exception e) |
467 | { | 473 | { |
468 | Status = (int)OSHttpStatusCode.ClientErrorJoker; | 474 | if (e is WebException && ((WebException)e).Status == WebExceptionStatus.ProtocolError) |
469 | ResponseBody = e.Message; | 475 | { |
476 | HttpWebResponse webRsp = (HttpWebResponse)((WebException)e).Response; | ||
477 | Status = (int)webRsp.StatusCode; | ||
478 | try | ||
479 | { | ||
480 | using (Stream responseStream = webRsp.GetResponseStream()) | ||
481 | { | ||
482 | ResponseBody = responseStream.GetStreamString(); | ||
483 | } | ||
484 | } | ||
485 | catch | ||
486 | { | ||
487 | ResponseBody = webRsp.StatusDescription; | ||
488 | } | ||
489 | } | ||
490 | else | ||
491 | { | ||
492 | Status = (int)OSHttpStatusCode.ClientErrorJoker; | ||
493 | ResponseBody = e.Message; | ||
494 | } | ||
470 | 495 | ||
471 | _finished = true; | 496 | _finished = true; |
472 | return; | 497 | return; |
diff --git a/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs b/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs index 05d54f0..e0e358a 100644 --- a/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs | |||
@@ -41,39 +41,13 @@ using OpenSim.Region.Framework.Scenes; | |||
41 | 41 | ||
42 | namespace OpenSim.Region.CoreModules.Scripting.LSLHttp | 42 | namespace OpenSim.Region.CoreModules.Scripting.LSLHttp |
43 | { | 43 | { |
44 | /// <summary> | ||
45 | /// Data describing an external URL set up by a script. | ||
46 | /// </summary> | ||
47 | public class UrlData | 44 | public class UrlData |
48 | { | 45 | { |
49 | /// <summary> | ||
50 | /// Scene object part hosting the script | ||
51 | /// </summary> | ||
52 | public UUID hostID; | 46 | public UUID hostID; |
53 | |||
54 | /// <summary> | ||
55 | /// The item ID of the script that requested the URL. | ||
56 | /// </summary> | ||
57 | public UUID itemID; | 47 | public UUID itemID; |
58 | |||
59 | /// <summary> | ||
60 | /// The script engine that runs the script. | ||
61 | /// </summary> | ||
62 | public IScriptModule engine; | 48 | public IScriptModule engine; |
63 | |||
64 | /// <summary> | ||
65 | /// The generated URL. | ||
66 | /// </summary> | ||
67 | public string url; | 49 | public string url; |
68 | |||
69 | /// <summary> | ||
70 | /// The random UUID component of the generated URL. | ||
71 | /// </summary> | ||
72 | public UUID urlcode; | 50 | public UUID urlcode; |
73 | |||
74 | /// <summary> | ||
75 | /// The external requests currently being processed or awaiting retrieval for this URL. | ||
76 | /// </summary> | ||
77 | public Dictionary<UUID, RequestData> requests; | 51 | public Dictionary<UUID, RequestData> requests; |
78 | } | 52 | } |
79 | 53 | ||
@@ -87,37 +61,26 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp | |||
87 | //public ManualResetEvent ev; | 61 | //public ManualResetEvent ev; |
88 | public bool requestDone; | 62 | public bool requestDone; |
89 | public int startTime; | 63 | public int startTime; |
64 | public bool responseSent; | ||
90 | public string uri; | 65 | public string uri; |
91 | } | 66 | } |
92 | 67 | ||
93 | /// <summary> | ||
94 | /// This module provides external URLs for in-world scripts. | ||
95 | /// </summary> | ||
96 | public class UrlModule : ISharedRegionModule, IUrlModule | 68 | public class UrlModule : ISharedRegionModule, IUrlModule |
97 | { | 69 | { |
98 | private static readonly ILog m_log = | 70 | private static readonly ILog m_log = |
99 | LogManager.GetLogger( | 71 | LogManager.GetLogger( |
100 | MethodBase.GetCurrentMethod().DeclaringType); | 72 | MethodBase.GetCurrentMethod().DeclaringType); |
101 | 73 | ||
102 | /// <summary> | 74 | private Dictionary<UUID, UrlData> m_RequestMap = |
103 | /// Indexs the URL request metadata (which script requested it, outstanding requests, etc.) by the request ID | 75 | new Dictionary<UUID, UrlData>(); |
104 | /// randomly generated when a request is received for this URL. | ||
105 | /// </summary> | ||
106 | /// <remarks> | ||
107 | /// Manipulation or retrieval from this dictionary must be locked on m_UrlMap to preserve consistency with | ||
108 | /// m_UrlMap | ||
109 | /// </remarks> | ||
110 | private Dictionary<UUID, UrlData> m_RequestMap = new Dictionary<UUID, UrlData>(); | ||
111 | 76 | ||
112 | /// <summary> | 77 | private Dictionary<string, UrlData> m_UrlMap = |
113 | /// Indexs the URL request metadata (which script requested it, outstanding requests, etc.) by the full URL | 78 | new Dictionary<string, UrlData>(); |
114 | /// </summary> | ||
115 | private Dictionary<string, UrlData> m_UrlMap = new Dictionary<string, UrlData>(); | ||
116 | 79 | ||
117 | /// <summary> | 80 | /// <summary> |
118 | /// Maximum number of external urls that can be set up by this module. | 81 | /// Maximum number of external urls that can be set up by this module. |
119 | /// </summary> | 82 | /// </summary> |
120 | private int m_TotalUrls = 100; | 83 | private int m_TotalUrls = 15000; |
121 | 84 | ||
122 | private uint https_port = 0; | 85 | private uint https_port = 0; |
123 | private IHttpServer m_HttpServer = null; | 86 | private IHttpServer m_HttpServer = null; |
@@ -143,9 +106,10 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp | |||
143 | { | 106 | { |
144 | m_ExternalHostNameForLSL = config.Configs["Network"].GetString("ExternalHostNameForLSL", System.Environment.MachineName); | 107 | m_ExternalHostNameForLSL = config.Configs["Network"].GetString("ExternalHostNameForLSL", System.Environment.MachineName); |
145 | bool ssl_enabled = config.Configs["Network"].GetBoolean("https_listener",false); | 108 | bool ssl_enabled = config.Configs["Network"].GetBoolean("https_listener",false); |
146 | |||
147 | if (ssl_enabled) | 109 | if (ssl_enabled) |
110 | { | ||
148 | https_port = (uint) config.Configs["Network"].GetInt("https_port",0); | 111 | https_port = (uint) config.Configs["Network"].GetInt("https_port",0); |
112 | } | ||
149 | 113 | ||
150 | IConfig llFunctionsConfig = config.Configs["LL-Functions"]; | 114 | IConfig llFunctionsConfig = config.Configs["LL-Functions"]; |
151 | 115 | ||
@@ -206,7 +170,7 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp | |||
206 | engine.PostScriptEvent(itemID, "http_request", new Object[] { urlcode.ToString(), "URL_REQUEST_DENIED", "" }); | 170 | engine.PostScriptEvent(itemID, "http_request", new Object[] { urlcode.ToString(), "URL_REQUEST_DENIED", "" }); |
207 | return urlcode; | 171 | return urlcode; |
208 | } | 172 | } |
209 | string url = "http://" + m_ExternalHostNameForLSL + ":" + m_HttpServer.Port.ToString() + "/lslhttp/" + urlcode.ToString() + "/"; | 173 | string url = "http://" + m_ExternalHostNameForLSL + ":" + m_HttpServer.Port.ToString() + "/lslhttp/" + urlcode.ToString(); |
210 | 174 | ||
211 | UrlData urlData = new UrlData(); | 175 | UrlData urlData = new UrlData(); |
212 | urlData.hostID = host.UUID; | 176 | urlData.hostID = host.UUID; |
@@ -215,14 +179,14 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp | |||
215 | urlData.url = url; | 179 | urlData.url = url; |
216 | urlData.urlcode = urlcode; | 180 | urlData.urlcode = urlcode; |
217 | urlData.requests = new Dictionary<UUID, RequestData>(); | 181 | urlData.requests = new Dictionary<UUID, RequestData>(); |
218 | 182 | ||
219 | m_UrlMap[url] = urlData; | 183 | m_UrlMap[url] = urlData; |
220 | 184 | ||
221 | string uri = "/lslhttp/" + urlcode.ToString() + "/"; | 185 | string uri = "/lslhttp/" + urlcode.ToString(); |
222 | 186 | ||
223 | m_HttpServer.AddPollServiceHTTPHandler( | 187 | PollServiceEventArgs args = new PollServiceEventArgs(HttpRequestHandler, HasEvents, GetEvents, NoEvents, urlcode, 25000); |
224 | uri, | 188 | args.Type = PollServiceEventArgs.EventType.LslHttp; |
225 | new PollServiceEventArgs(HttpRequestHandler, HasEvents, GetEvents, NoEvents, urlcode)); | 189 | m_HttpServer.AddPollServiceHTTPHandler(uri, args); |
226 | 190 | ||
227 | m_log.DebugFormat( | 191 | m_log.DebugFormat( |
228 | "[URL MODULE]: Set up incoming request url {0} for {1} in {2} {3}", | 192 | "[URL MODULE]: Set up incoming request url {0} for {1} in {2} {3}", |
@@ -251,7 +215,7 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp | |||
251 | engine.PostScriptEvent(itemID, "http_request", new Object[] { urlcode.ToString(), "URL_REQUEST_DENIED", "" }); | 215 | engine.PostScriptEvent(itemID, "http_request", new Object[] { urlcode.ToString(), "URL_REQUEST_DENIED", "" }); |
252 | return urlcode; | 216 | return urlcode; |
253 | } | 217 | } |
254 | string url = "https://" + m_ExternalHostNameForLSL + ":" + m_HttpsServer.Port.ToString() + "/lslhttps/" + urlcode.ToString() + "/"; | 218 | string url = "https://" + m_ExternalHostNameForLSL + ":" + m_HttpsServer.Port.ToString() + "/lslhttps/" + urlcode.ToString(); |
255 | 219 | ||
256 | UrlData urlData = new UrlData(); | 220 | UrlData urlData = new UrlData(); |
257 | urlData.hostID = host.UUID; | 221 | urlData.hostID = host.UUID; |
@@ -261,13 +225,14 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp | |||
261 | urlData.urlcode = urlcode; | 225 | urlData.urlcode = urlcode; |
262 | urlData.requests = new Dictionary<UUID, RequestData>(); | 226 | urlData.requests = new Dictionary<UUID, RequestData>(); |
263 | 227 | ||
228 | |||
264 | m_UrlMap[url] = urlData; | 229 | m_UrlMap[url] = urlData; |
265 | 230 | ||
266 | string uri = "/lslhttps/" + urlcode.ToString() + "/"; | 231 | string uri = "/lslhttps/" + urlcode.ToString(); |
267 | 232 | ||
268 | m_HttpsServer.AddPollServiceHTTPHandler( | 233 | PollServiceEventArgs args = new PollServiceEventArgs(HttpRequestHandler, HasEvents, GetEvents, NoEvents, urlcode, 25000); |
269 | uri, | 234 | args.Type = PollServiceEventArgs.EventType.LslHttp; |
270 | new PollServiceEventArgs(HttpRequestHandler, HasEvents, GetEvents, NoEvents, urlcode)); | 235 | m_HttpsServer.AddPollServiceHTTPHandler(uri, args); |
271 | 236 | ||
272 | m_log.DebugFormat( | 237 | m_log.DebugFormat( |
273 | "[URL MODULE]: Set up incoming secure request url {0} for {1} in {2} {3}", | 238 | "[URL MODULE]: Set up incoming secure request url {0} for {1} in {2} {3}", |
@@ -290,12 +255,15 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp | |||
290 | return; | 255 | return; |
291 | } | 256 | } |
292 | 257 | ||
293 | foreach (UUID req in data.requests.Keys) | 258 | lock (m_RequestMap) |
294 | m_RequestMap.Remove(req); | 259 | { |
295 | 260 | foreach (UUID req in data.requests.Keys) | |
296 | m_log.DebugFormat( | 261 | m_RequestMap.Remove(req); |
297 | "[URL MODULE]: Releasing url {0} for {1} in {2}", | 262 | } |
298 | url, data.itemID, data.hostID); | 263 | |
264 | // m_log.DebugFormat( | ||
265 | // "[URL MODULE]: Releasing url {0} for {1} in {2}", | ||
266 | // url, data.itemID, data.hostID); | ||
299 | 267 | ||
300 | RemoveUrl(data); | 268 | RemoveUrl(data); |
301 | m_UrlMap.Remove(url); | 269 | m_UrlMap.Remove(url); |
@@ -304,15 +272,19 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp | |||
304 | 272 | ||
305 | public void HttpResponse(UUID request, int status, string body) | 273 | public void HttpResponse(UUID request, int status, string body) |
306 | { | 274 | { |
307 | lock (m_UrlMap) | 275 | lock (m_RequestMap) |
308 | { | 276 | { |
309 | if (m_RequestMap.ContainsKey(request)) | 277 | if (m_RequestMap.ContainsKey(request)) |
310 | { | 278 | { |
311 | UrlData urlData = m_RequestMap[request]; | 279 | UrlData urlData = m_RequestMap[request]; |
312 | urlData.requests[request].responseCode = status; | 280 | if (!urlData.requests[request].responseSent) |
313 | urlData.requests[request].responseBody = body; | 281 | { |
314 | //urlData.requests[request].ev.Set(); | 282 | urlData.requests[request].responseCode = status; |
315 | urlData.requests[request].requestDone =true; | 283 | urlData.requests[request].responseBody = body; |
284 | //urlData.requests[request].ev.Set(); | ||
285 | urlData.requests[request].requestDone = true; | ||
286 | urlData.requests[request].responseSent = true; | ||
287 | } | ||
316 | } | 288 | } |
317 | else | 289 | else |
318 | { | 290 | { |
@@ -323,7 +295,7 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp | |||
323 | 295 | ||
324 | public string GetHttpHeader(UUID requestId, string header) | 296 | public string GetHttpHeader(UUID requestId, string header) |
325 | { | 297 | { |
326 | lock (m_UrlMap) | 298 | lock (m_RequestMap) |
327 | { | 299 | { |
328 | if (m_RequestMap.ContainsKey(requestId)) | 300 | if (m_RequestMap.ContainsKey(requestId)) |
329 | { | 301 | { |
@@ -337,14 +309,12 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp | |||
337 | m_log.Warn("[HttpRequestHandler] There was no http-in request with id " + requestId); | 309 | m_log.Warn("[HttpRequestHandler] There was no http-in request with id " + requestId); |
338 | } | 310 | } |
339 | } | 311 | } |
340 | |||
341 | return String.Empty; | 312 | return String.Empty; |
342 | } | 313 | } |
343 | 314 | ||
344 | public int GetFreeUrls() | 315 | public int GetFreeUrls() |
345 | { | 316 | { |
346 | lock (m_UrlMap) | 317 | return m_TotalUrls - m_UrlMap.Count; |
347 | return m_TotalUrls - m_UrlMap.Count; | ||
348 | } | 318 | } |
349 | 319 | ||
350 | public void ScriptRemoved(UUID itemID) | 320 | public void ScriptRemoved(UUID itemID) |
@@ -361,8 +331,11 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp | |||
361 | { | 331 | { |
362 | RemoveUrl(url.Value); | 332 | RemoveUrl(url.Value); |
363 | removeURLs.Add(url.Key); | 333 | removeURLs.Add(url.Key); |
364 | foreach (UUID req in url.Value.requests.Keys) | 334 | lock (m_RequestMap) |
365 | m_RequestMap.Remove(req); | 335 | { |
336 | foreach (UUID req in url.Value.requests.Keys) | ||
337 | m_RequestMap.Remove(req); | ||
338 | } | ||
366 | } | 339 | } |
367 | } | 340 | } |
368 | 341 | ||
@@ -383,9 +356,11 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp | |||
383 | { | 356 | { |
384 | RemoveUrl(url.Value); | 357 | RemoveUrl(url.Value); |
385 | removeURLs.Add(url.Key); | 358 | removeURLs.Add(url.Key); |
386 | 359 | lock (m_RequestMap) | |
387 | foreach (UUID req in url.Value.requests.Keys) | 360 | { |
388 | m_RequestMap.Remove(req); | 361 | foreach (UUID req in url.Value.requests.Keys) |
362 | m_RequestMap.Remove(req); | ||
363 | } | ||
389 | } | 364 | } |
390 | } | 365 | } |
391 | 366 | ||
@@ -394,122 +369,125 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp | |||
394 | } | 369 | } |
395 | } | 370 | } |
396 | 371 | ||
372 | |||
397 | private void RemoveUrl(UrlData data) | 373 | private void RemoveUrl(UrlData data) |
398 | { | 374 | { |
399 | m_HttpServer.RemoveHTTPHandler("", "/lslhttp/" + data.urlcode.ToString() + "/"); | 375 | m_HttpServer.RemoveHTTPHandler("", "/lslhttp/"+data.urlcode.ToString()+"/"); |
400 | } | 376 | } |
401 | 377 | ||
402 | private Hashtable NoEvents(UUID requestID, UUID sessionID) | 378 | private Hashtable NoEvents(UUID requestID, UUID sessionID) |
403 | { | 379 | { |
404 | Hashtable response = new Hashtable(); | 380 | Hashtable response = new Hashtable(); |
405 | UrlData urlData; | 381 | UrlData url; |
406 | 382 | int startTime = 0; | |
407 | lock (m_UrlMap) | 383 | lock (m_RequestMap) |
408 | { | 384 | { |
409 | // We need to return a 404 here in case the request URL was removed at exactly the same time that a | ||
410 | // request was made. In this case, the request thread can outrace llRemoveURL() and still be polling | ||
411 | // for the request ID. | ||
412 | if (!m_RequestMap.ContainsKey(requestID)) | 385 | if (!m_RequestMap.ContainsKey(requestID)) |
413 | { | ||
414 | response["int_response_code"] = 404; | ||
415 | response["str_response_string"] = ""; | ||
416 | response["keepalive"] = false; | ||
417 | response["reusecontext"] = false; | ||
418 | |||
419 | return response; | 386 | return response; |
420 | } | 387 | url = m_RequestMap[requestID]; |
388 | startTime = url.requests[requestID].startTime; | ||
389 | } | ||
421 | 390 | ||
422 | urlData = m_RequestMap[requestID]; | 391 | if (System.Environment.TickCount - startTime > 25000) |
392 | { | ||
393 | response["int_response_code"] = 500; | ||
394 | response["str_response_string"] = "Script timeout"; | ||
395 | response["content_type"] = "text/plain"; | ||
396 | response["keepalive"] = false; | ||
397 | response["reusecontext"] = false; | ||
423 | 398 | ||
424 | if (System.Environment.TickCount - urlData.requests[requestID].startTime > 25000) | 399 | //remove from map |
400 | lock (url.requests) | ||
401 | { | ||
402 | url.requests.Remove(requestID); | ||
403 | } | ||
404 | lock (m_RequestMap) | ||
425 | { | 405 | { |
426 | response["int_response_code"] = 500; | ||
427 | response["str_response_string"] = "Script timeout"; | ||
428 | response["content_type"] = "text/plain"; | ||
429 | response["keepalive"] = false; | ||
430 | response["reusecontext"] = false; | ||
431 | |||
432 | //remove from map | ||
433 | urlData.requests.Remove(requestID); | ||
434 | m_RequestMap.Remove(requestID); | 406 | m_RequestMap.Remove(requestID); |
435 | |||
436 | return response; | ||
437 | } | 407 | } |
408 | |||
409 | return response; | ||
438 | } | 410 | } |
439 | 411 | ||
412 | |||
440 | return response; | 413 | return response; |
441 | } | 414 | } |
442 | 415 | ||
443 | private bool HasEvents(UUID requestID, UUID sessionID) | 416 | private bool HasEvents(UUID requestID, UUID sessionID) |
444 | { | 417 | { |
445 | lock (m_UrlMap) | 418 | UrlData url=null; |
419 | |||
420 | lock (m_RequestMap) | ||
446 | { | 421 | { |
447 | // We return true here because an external URL request that happened at the same time as an llRemoveURL() | ||
448 | // can still make it through to HttpRequestHandler(). That will return without setting up a request | ||
449 | // when it detects that the URL has been removed. The poller, however, will continue to ask for | ||
450 | // events for that request, so here we will signal that there are events and in GetEvents we will | ||
451 | // return a 404. | ||
452 | if (!m_RequestMap.ContainsKey(requestID)) | 422 | if (!m_RequestMap.ContainsKey(requestID)) |
453 | { | 423 | { |
454 | return true; | 424 | return false; |
455 | } | 425 | } |
456 | 426 | url = m_RequestMap[requestID]; | |
457 | UrlData urlData = m_RequestMap[requestID]; | 427 | } |
458 | 428 | lock (url.requests) | |
459 | if (!urlData.requests.ContainsKey(requestID)) | 429 | { |
430 | if (!url.requests.ContainsKey(requestID)) | ||
460 | { | 431 | { |
461 | return true; | 432 | return false; |
462 | } | 433 | } |
463 | 434 | else | |
464 | // Trigger return of timeout response. | ||
465 | if (System.Environment.TickCount - urlData.requests[requestID].startTime > 25000) | ||
466 | { | 435 | { |
467 | return true; | 436 | if (System.Environment.TickCount - url.requests[requestID].startTime > 25000) |
437 | { | ||
438 | return true; | ||
439 | } | ||
440 | if (url.requests[requestID].requestDone) | ||
441 | return true; | ||
442 | else | ||
443 | return false; | ||
468 | } | 444 | } |
469 | |||
470 | return urlData.requests[requestID].requestDone; | ||
471 | } | 445 | } |
472 | } | 446 | } |
473 | |||
474 | private Hashtable GetEvents(UUID requestID, UUID sessionID, string request) | 447 | private Hashtable GetEvents(UUID requestID, UUID sessionID, string request) |
475 | { | 448 | { |
476 | Hashtable response; | 449 | UrlData url = null; |
450 | RequestData requestData = null; | ||
477 | 451 | ||
478 | lock (m_UrlMap) | 452 | lock (m_RequestMap) |
479 | { | 453 | { |
480 | UrlData url = null; | ||
481 | RequestData requestData = null; | ||
482 | |||
483 | if (!m_RequestMap.ContainsKey(requestID)) | 454 | if (!m_RequestMap.ContainsKey(requestID)) |
484 | return NoEvents(requestID, sessionID); | 455 | return NoEvents(requestID,sessionID); |
485 | |||
486 | url = m_RequestMap[requestID]; | 456 | url = m_RequestMap[requestID]; |
457 | } | ||
458 | lock (url.requests) | ||
459 | { | ||
487 | requestData = url.requests[requestID]; | 460 | requestData = url.requests[requestID]; |
461 | } | ||
462 | |||
463 | if (!requestData.requestDone) | ||
464 | return NoEvents(requestID,sessionID); | ||
465 | |||
466 | Hashtable response = new Hashtable(); | ||
488 | 467 | ||
489 | if (!requestData.requestDone) | 468 | if (System.Environment.TickCount - requestData.startTime > 25000) |
490 | return NoEvents(requestID, sessionID); | 469 | { |
491 | 470 | response["int_response_code"] = 500; | |
492 | response = new Hashtable(); | 471 | response["str_response_string"] = "Script timeout"; |
493 | |||
494 | if (System.Environment.TickCount - requestData.startTime > 25000) | ||
495 | { | ||
496 | response["int_response_code"] = 500; | ||
497 | response["str_response_string"] = "Script timeout"; | ||
498 | response["content_type"] = "text/plain"; | ||
499 | response["keepalive"] = false; | ||
500 | response["reusecontext"] = false; | ||
501 | return response; | ||
502 | } | ||
503 | |||
504 | //put response | ||
505 | response["int_response_code"] = requestData.responseCode; | ||
506 | response["str_response_string"] = requestData.responseBody; | ||
507 | response["content_type"] = "text/plain"; | 472 | response["content_type"] = "text/plain"; |
508 | response["keepalive"] = false; | 473 | response["keepalive"] = false; |
509 | response["reusecontext"] = false; | 474 | response["reusecontext"] = false; |
510 | 475 | return response; | |
511 | //remove from map | 476 | } |
477 | //put response | ||
478 | response["int_response_code"] = requestData.responseCode; | ||
479 | response["str_response_string"] = requestData.responseBody; | ||
480 | response["content_type"] = "text/plain"; | ||
481 | response["keepalive"] = false; | ||
482 | response["reusecontext"] = false; | ||
483 | |||
484 | //remove from map | ||
485 | lock (url.requests) | ||
486 | { | ||
512 | url.requests.Remove(requestID); | 487 | url.requests.Remove(requestID); |
488 | } | ||
489 | lock (m_RequestMap) | ||
490 | { | ||
513 | m_RequestMap.Remove(requestID); | 491 | m_RequestMap.Remove(requestID); |
514 | } | 492 | } |
515 | 493 | ||
@@ -518,41 +496,45 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp | |||
518 | 496 | ||
519 | public void HttpRequestHandler(UUID requestID, Hashtable request) | 497 | public void HttpRequestHandler(UUID requestID, Hashtable request) |
520 | { | 498 | { |
521 | string uri = request["uri"].ToString(); | 499 | lock (request) |
522 | bool is_ssl = uri.Contains("lslhttps"); | ||
523 | |||
524 | try | ||
525 | { | 500 | { |
526 | Hashtable headers = (Hashtable)request["headers"]; | 501 | string uri = request["uri"].ToString(); |
527 | 502 | bool is_ssl = uri.Contains("lslhttps"); | |
528 | // string uri_full = "http://" + m_ExternalHostNameForLSL + ":" + m_HttpServer.Port.ToString() + uri;// "/lslhttp/" + urlcode.ToString() + "/"; | ||
529 | 503 | ||
530 | int pos1 = uri.IndexOf("/");// /lslhttp | 504 | try |
531 | int pos2 = uri.IndexOf("/", pos1 + 1);// /lslhttp/ | ||
532 | int pos3 = uri.IndexOf("/", pos2 + 1);// /lslhttp/<UUID>/ | ||
533 | string uri_tmp = uri.Substring(0, pos3 + 1); | ||
534 | //HTTP server code doesn't provide us with QueryStrings | ||
535 | string pathInfo; | ||
536 | string queryString; | ||
537 | queryString = ""; | ||
538 | |||
539 | pathInfo = uri.Substring(pos3); | ||
540 | |||
541 | UrlData urlData = null; | ||
542 | |||
543 | lock (m_UrlMap) | ||
544 | { | 505 | { |
545 | string url; | 506 | Hashtable headers = (Hashtable)request["headers"]; |
507 | |||
508 | // string uri_full = "http://" + m_ExternalHostNameForLSL + ":" + m_HttpServer.Port.ToString() + uri;// "/lslhttp/" + urlcode.ToString() + "/"; | ||
546 | 509 | ||
547 | if (is_ssl) | 510 | int pos1 = uri.IndexOf("/");// /lslhttp |
548 | url = "https://" + m_ExternalHostNameForLSL + ":" + m_HttpsServer.Port.ToString() + uri_tmp; | 511 | int pos2 = uri.IndexOf("/", pos1 + 1);// /lslhttp/ |
512 | int pos3 = pos2 + 37; // /lslhttp/urlcode | ||
513 | string uri_tmp = uri.Substring(0, pos3); | ||
514 | //HTTP server code doesn't provide us with QueryStrings | ||
515 | string pathInfo; | ||
516 | string queryString; | ||
517 | queryString = ""; | ||
518 | |||
519 | pathInfo = uri.Substring(pos3); | ||
520 | |||
521 | UrlData url = null; | ||
522 | string urlkey; | ||
523 | if (!is_ssl) | ||
524 | urlkey = "http://" + m_ExternalHostNameForLSL + ":" + m_HttpServer.Port.ToString() + uri_tmp; | ||
525 | //m_UrlMap[]; | ||
549 | else | 526 | else |
550 | url = "http://" + m_ExternalHostNameForLSL + ":" + m_HttpServer.Port.ToString() + uri_tmp; | 527 | urlkey = "https://" + m_ExternalHostNameForLSL + ":" + m_HttpsServer.Port.ToString() + uri_tmp; |
551 | 528 | ||
552 | // Avoid a race - the request URL may have been released via llRequestUrl() whilst this | 529 | if (m_UrlMap.ContainsKey(urlkey)) |
553 | // request was being processed. | 530 | { |
554 | if (!m_UrlMap.TryGetValue(url, out urlData)) | 531 | url = m_UrlMap[urlkey]; |
532 | } | ||
533 | else | ||
534 | { | ||
535 | //m_log.Warn("[HttpRequestHandler]: http-in request failed; no such url: "+urlkey.ToString()); | ||
555 | return; | 536 | return; |
537 | } | ||
556 | 538 | ||
557 | //for llGetHttpHeader support we need to store original URI here | 539 | //for llGetHttpHeader support we need to store original URI here |
558 | //to make x-path-info / x-query-string / x-script-url / x-remote-ip headers | 540 | //to make x-path-info / x-query-string / x-script-url / x-remote-ip headers |
@@ -572,7 +554,6 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp | |||
572 | string value = (string)header.Value; | 554 | string value = (string)header.Value; |
573 | requestData.headers.Add(key, value); | 555 | requestData.headers.Add(key, value); |
574 | } | 556 | } |
575 | |||
576 | foreach (DictionaryEntry de in request) | 557 | foreach (DictionaryEntry de in request) |
577 | { | 558 | { |
578 | if (de.Key.ToString() == "querystringkeys") | 559 | if (de.Key.ToString() == "querystringkeys") |
@@ -583,13 +564,21 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp | |||
583 | if (request.ContainsKey(key)) | 564 | if (request.ContainsKey(key)) |
584 | { | 565 | { |
585 | string val = (String)request[key]; | 566 | string val = (String)request[key]; |
586 | queryString = queryString + key + "=" + val + "&"; | 567 | if (key != "") |
568 | { | ||
569 | queryString = queryString + key + "=" + val + "&"; | ||
570 | } | ||
571 | else | ||
572 | { | ||
573 | queryString = queryString + val + "&"; | ||
574 | } | ||
587 | } | 575 | } |
588 | } | 576 | } |
589 | |||
590 | if (queryString.Length > 1) | 577 | if (queryString.Length > 1) |
591 | queryString = queryString.Substring(0, queryString.Length - 1); | 578 | queryString = queryString.Substring(0, queryString.Length - 1); |
579 | |||
592 | } | 580 | } |
581 | |||
593 | } | 582 | } |
594 | 583 | ||
595 | //if this machine is behind DNAT/port forwarding, currently this is being | 584 | //if this machine is behind DNAT/port forwarding, currently this is being |
@@ -597,23 +586,34 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp | |||
597 | requestData.headers["x-remote-ip"] = requestData.headers["remote_addr"]; | 586 | requestData.headers["x-remote-ip"] = requestData.headers["remote_addr"]; |
598 | requestData.headers["x-path-info"] = pathInfo; | 587 | requestData.headers["x-path-info"] = pathInfo; |
599 | requestData.headers["x-query-string"] = queryString; | 588 | requestData.headers["x-query-string"] = queryString; |
600 | requestData.headers["x-script-url"] = urlData.url; | 589 | requestData.headers["x-script-url"] = url.url; |
601 | 590 | ||
602 | urlData.requests.Add(requestID, requestData); | 591 | //requestData.ev = new ManualResetEvent(false); |
603 | m_RequestMap.Add(requestID, urlData); | 592 | lock (url.requests) |
604 | } | 593 | { |
594 | url.requests.Add(requestID, requestData); | ||
595 | } | ||
596 | lock (m_RequestMap) | ||
597 | { | ||
598 | //add to request map | ||
599 | m_RequestMap.Add(requestID, url); | ||
600 | } | ||
605 | 601 | ||
606 | urlData.engine.PostScriptEvent( | 602 | url.engine.PostScriptEvent(url.itemID, "http_request", new Object[] { requestID.ToString(), request["http-method"].ToString(), request["body"].ToString() }); |
607 | urlData.itemID, | 603 | |
608 | "http_request", | 604 | //send initial response? |
609 | new Object[] { requestID.ToString(), request["http-method"].ToString(), request["body"].ToString() }); | 605 | // Hashtable response = new Hashtable(); |
610 | } | 606 | |
611 | catch (Exception we) | 607 | return; |
612 | { | 608 | |
613 | //Hashtable response = new Hashtable(); | 609 | } |
614 | m_log.Warn("[HttpRequestHandler]: http-in request failed"); | 610 | catch (Exception we) |
615 | m_log.Warn(we.Message); | 611 | { |
616 | m_log.Warn(we.StackTrace); | 612 | //Hashtable response = new Hashtable(); |
613 | m_log.Warn("[HttpRequestHandler]: http-in request failed"); | ||
614 | m_log.Warn(we.Message); | ||
615 | m_log.Warn(we.StackTrace); | ||
616 | } | ||
617 | } | 617 | } |
618 | } | 618 | } |
619 | 619 | ||
@@ -622,4 +622,4 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp | |||
622 | ScriptRemoved(itemID); | 622 | ScriptRemoved(itemID); |
623 | } | 623 | } |
624 | } | 624 | } |
625 | } \ No newline at end of file | 625 | } |
diff --git a/OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs b/OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs index 8358bc0..07bb291 100644 --- a/OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs | |||
@@ -90,6 +90,8 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm | |||
90 | // private static readonly ILog m_log = | 90 | // private static readonly ILog m_log = |
91 | // LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 91 | // LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
92 | 92 | ||
93 | private const int DEBUG_CHANNEL = 2147483647; | ||
94 | |||
93 | private ListenerManager m_listenerManager; | 95 | private ListenerManager m_listenerManager; |
94 | private Queue m_pending; | 96 | private Queue m_pending; |
95 | private Queue m_pendingQ; | 97 | private Queue m_pendingQ; |
@@ -308,56 +310,59 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm | |||
308 | /// <param name='msg'> | 310 | /// <param name='msg'> |
309 | /// Message. | 311 | /// Message. |
310 | /// </param> | 312 | /// </param> |
311 | public void DeliverMessageTo(UUID target, int channel, Vector3 pos, string name, UUID id, string msg) | 313 | public bool DeliverMessageTo(UUID target, int channel, Vector3 pos, string name, UUID id, string msg, out string error) |
312 | { | 314 | { |
315 | error = null; | ||
316 | |||
317 | if (channel == DEBUG_CHANNEL) | ||
318 | return true; | ||
319 | |||
313 | // Is id an avatar? | 320 | // Is id an avatar? |
314 | ScenePresence sp = m_scene.GetScenePresence(target); | 321 | ScenePresence sp = m_scene.GetScenePresence(target); |
315 | 322 | ||
316 | if (sp != null) | 323 | if (sp != null) |
317 | { | 324 | { |
318 | // ignore if a child agent this is restricted to inside one region | 325 | // Send message to avatar |
319 | if (sp.IsChildAgent) | ||
320 | return; | ||
321 | |||
322 | // Send message to the avatar. | ||
323 | // Channel zero only goes to the avatar | ||
324 | // non zero channel messages only go to the attachments | ||
325 | if (channel == 0) | 326 | if (channel == 0) |
326 | { | 327 | { |
327 | m_scene.SimChatToAgent(target, Utils.StringToBytes(msg), pos, name, id, false); | 328 | // Channel 0 goes to viewer ONLY |
328 | } | 329 | m_scene.SimChat(Utils.StringToBytes(msg), ChatTypeEnum.Broadcast, 0, pos, name, id, false, false, target); |
329 | else | 330 | return true; |
330 | { | 331 | } |
331 | List<SceneObjectGroup> attachments = sp.GetAttachments(); | ||
332 | if (attachments.Count == 0) | ||
333 | return; | ||
334 | 332 | ||
335 | // Get uuid of attachments | 333 | List<SceneObjectGroup> attachments = sp.GetAttachments(); |
336 | List<UUID> targets = new List<UUID>(); | ||
337 | foreach (SceneObjectGroup sog in attachments) | ||
338 | { | ||
339 | if (!sog.IsDeleted) | ||
340 | targets.Add(sog.UUID); | ||
341 | } | ||
342 | 334 | ||
343 | // Need to check each attachment | 335 | if (attachments.Count == 0) |
344 | foreach (ListenerInfo li in m_listenerManager.GetListeners(UUID.Zero, channel, name, id, msg)) | 336 | return true; |
345 | { | ||
346 | if (li.GetHostID().Equals(id)) | ||
347 | continue; | ||
348 | 337 | ||
349 | if (m_scene.GetSceneObjectPart(li.GetHostID()) == null) | 338 | // Get uuid of attachments |
350 | continue; | 339 | List<UUID> targets = new List<UUID>(); |
340 | foreach (SceneObjectGroup sog in attachments) | ||
341 | { | ||
342 | if (!sog.IsDeleted) | ||
343 | targets.Add(sog.UUID); | ||
344 | } | ||
351 | 345 | ||
352 | if (targets.Contains(li.GetHostID())) | 346 | // Need to check each attachment |
353 | QueueMessage(new ListenerInfo(li, name, id, msg)); | 347 | foreach (ListenerInfo li in m_listenerManager.GetListeners(UUID.Zero, channel, name, id, msg)) |
354 | } | 348 | { |
349 | if (li.GetHostID().Equals(id)) | ||
350 | continue; | ||
351 | |||
352 | if (m_scene.GetSceneObjectPart(li.GetHostID()) == null) | ||
353 | continue; | ||
354 | |||
355 | if (targets.Contains(li.GetHostID())) | ||
356 | QueueMessage(new ListenerInfo(li, name, id, msg)); | ||
355 | } | 357 | } |
356 | 358 | ||
357 | return; | 359 | return true; |
358 | } | 360 | } |
359 | 361 | ||
360 | // No avatar found so look for an object | 362 | SceneObjectPart part = m_scene.GetSceneObjectPart(target); |
363 | if (part == null) // Not even an object | ||
364 | return true; // No error | ||
365 | |||
361 | foreach (ListenerInfo li in m_listenerManager.GetListeners(UUID.Zero, channel, name, id, msg)) | 366 | foreach (ListenerInfo li in m_listenerManager.GetListeners(UUID.Zero, channel, name, id, msg)) |
362 | { | 367 | { |
363 | // Dont process if this message is from yourself! | 368 | // Dont process if this message is from yourself! |
@@ -375,7 +380,7 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm | |||
375 | } | 380 | } |
376 | } | 381 | } |
377 | 382 | ||
378 | return; | 383 | return true; |
379 | } | 384 | } |
380 | 385 | ||
381 | protected void QueueMessage(ListenerInfo li) | 386 | protected void QueueMessage(ListenerInfo li) |