diff options
Diffstat (limited to 'OpenSim/Region/CoreModules/Scripting')
5 files changed, 436 insertions, 336 deletions
diff --git a/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs b/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs index 1a62405..6eb25ef 100644 --- a/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs +++ b/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs | |||
@@ -28,15 +28,12 @@ | |||
28 | using System; | 28 | using System; |
29 | using System.Collections.Generic; | 29 | using System.Collections.Generic; |
30 | using System.IO; | 30 | using System.IO; |
31 | using System.Linq; | ||
32 | using System.Net; | 31 | using System.Net; |
33 | using System.Net.Mail; | 32 | using System.Net.Mail; |
34 | using System.Net.Security; | 33 | using System.Net.Security; |
35 | using System.Reflection; | ||
36 | using System.Text; | 34 | using System.Text; |
37 | using System.Threading; | 35 | using System.Threading; |
38 | using System.Security.Cryptography.X509Certificates; | 36 | using System.Security.Cryptography.X509Certificates; |
39 | using log4net; | ||
40 | using Nini.Config; | 37 | using Nini.Config; |
41 | using OpenMetaverse; | 38 | using OpenMetaverse; |
42 | using OpenSim.Framework; | 39 | using OpenSim.Framework; |
@@ -45,6 +42,7 @@ using OpenSim.Framework.Servers.HttpServer; | |||
45 | using OpenSim.Region.Framework.Interfaces; | 42 | using OpenSim.Region.Framework.Interfaces; |
46 | using OpenSim.Region.Framework.Scenes; | 43 | using OpenSim.Region.Framework.Scenes; |
47 | using Mono.Addins; | 44 | using Mono.Addins; |
45 | using Amib.Threading; | ||
48 | 46 | ||
49 | /***************************************************** | 47 | /***************************************************** |
50 | * | 48 | * |
@@ -105,6 +103,7 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest | |||
105 | private Dictionary<UUID, HttpRequestClass> m_pendingRequests; | 103 | private Dictionary<UUID, HttpRequestClass> m_pendingRequests; |
106 | private Scene m_scene; | 104 | private Scene m_scene; |
107 | // private Queue<HttpRequestClass> rpcQueue = new Queue<HttpRequestClass>(); | 105 | // private Queue<HttpRequestClass> rpcQueue = new Queue<HttpRequestClass>(); |
106 | public static SmartThreadPool ThreadPool = null; | ||
108 | 107 | ||
109 | public HttpRequestModule() | 108 | public HttpRequestModule() |
110 | { | 109 | { |
@@ -253,29 +252,18 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest | |||
253 | return reqID; | 252 | return reqID; |
254 | } | 253 | } |
255 | 254 | ||
256 | public void StopHttpRequestsForScript(UUID id) | 255 | public void StopHttpRequest(uint m_localID, UUID m_itemID) |
257 | { | 256 | { |
258 | if (m_pendingRequests != null) | 257 | if (m_pendingRequests != null) |
259 | { | 258 | { |
260 | List<UUID> keysToRemove = null; | ||
261 | |||
262 | lock (HttpListLock) | 259 | lock (HttpListLock) |
263 | { | 260 | { |
264 | foreach (HttpRequestClass req in m_pendingRequests.Values) | 261 | HttpRequestClass tmpReq; |
262 | if (m_pendingRequests.TryGetValue(m_itemID, out tmpReq)) | ||
265 | { | 263 | { |
266 | if (req.ItemID == id) | 264 | tmpReq.Stop(); |
267 | { | 265 | m_pendingRequests.Remove(m_itemID); |
268 | req.Stop(); | ||
269 | |||
270 | if (keysToRemove == null) | ||
271 | keysToRemove = new List<UUID>(); | ||
272 | |||
273 | keysToRemove.Add(req.ReqID); | ||
274 | } | ||
275 | } | 266 | } |
276 | |||
277 | if (keysToRemove != null) | ||
278 | keysToRemove.ForEach(keyToRemove => m_pendingRequests.Remove(keyToRemove)); | ||
279 | } | 267 | } |
280 | } | 268 | } |
281 | } | 269 | } |
@@ -293,13 +281,19 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest | |||
293 | { | 281 | { |
294 | lock (HttpListLock) | 282 | lock (HttpListLock) |
295 | { | 283 | { |
296 | foreach (HttpRequestClass req in m_pendingRequests.Values) | 284 | foreach (UUID luid in m_pendingRequests.Keys) |
297 | { | 285 | { |
298 | if (req.Finished) | 286 | HttpRequestClass tmpReq; |
299 | return req; | 287 | |
288 | if (m_pendingRequests.TryGetValue(luid, out tmpReq)) | ||
289 | { | ||
290 | if (tmpReq.Finished) | ||
291 | { | ||
292 | return tmpReq; | ||
293 | } | ||
294 | } | ||
300 | } | 295 | } |
301 | } | 296 | } |
302 | |||
303 | return null; | 297 | return null; |
304 | } | 298 | } |
305 | 299 | ||
@@ -326,7 +320,30 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest | |||
326 | m_proxyurl = config.Configs["Startup"].GetString("HttpProxy"); | 320 | m_proxyurl = config.Configs["Startup"].GetString("HttpProxy"); |
327 | m_proxyexcepts = config.Configs["Startup"].GetString("HttpProxyExceptions"); | 321 | m_proxyexcepts = config.Configs["Startup"].GetString("HttpProxyExceptions"); |
328 | 322 | ||
323 | int maxThreads = 50; | ||
324 | |||
325 | IConfig httpConfig = config.Configs["HttpRequestModule"]; | ||
326 | if (httpConfig != null) | ||
327 | { | ||
328 | maxThreads = httpConfig.GetInt("MaxPoolThreads", maxThreads); | ||
329 | } | ||
330 | |||
329 | m_pendingRequests = new Dictionary<UUID, HttpRequestClass>(); | 331 | m_pendingRequests = new Dictionary<UUID, HttpRequestClass>(); |
332 | |||
333 | // First instance sets this up for all sims | ||
334 | if (ThreadPool == null) | ||
335 | { | ||
336 | STPStartInfo startInfo = new STPStartInfo(); | ||
337 | startInfo.IdleTimeout = 20000; | ||
338 | startInfo.MaxWorkerThreads = maxThreads; | ||
339 | startInfo.MinWorkerThreads = 5; | ||
340 | startInfo.ThreadPriority = ThreadPriority.BelowNormal; | ||
341 | startInfo.StartSuspended = true; | ||
342 | |||
343 | ThreadPool = new SmartThreadPool(startInfo); | ||
344 | |||
345 | ThreadPool.Start(); | ||
346 | } | ||
330 | } | 347 | } |
331 | 348 | ||
332 | public void AddRegion(Scene scene) | 349 | public void AddRegion(Scene scene) |
@@ -370,8 +387,6 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest | |||
370 | 387 | ||
371 | public class HttpRequestClass: IServiceRequest | 388 | public class HttpRequestClass: IServiceRequest |
372 | { | 389 | { |
373 | // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | ||
374 | |||
375 | // Constants for parameters | 390 | // Constants for parameters |
376 | // public const int HTTP_BODY_MAXLENGTH = 2; | 391 | // public const int HTTP_BODY_MAXLENGTH = 2; |
377 | // public const int HTTP_METHOD = 0; | 392 | // public const int HTTP_METHOD = 0; |
@@ -392,6 +407,8 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest | |||
392 | public string HttpMIMEType = "text/plain;charset=utf-8"; | 407 | public string HttpMIMEType = "text/plain;charset=utf-8"; |
393 | public int HttpTimeout; | 408 | public int HttpTimeout; |
394 | public bool HttpVerifyCert = true; | 409 | public bool HttpVerifyCert = true; |
410 | public IWorkItemResult WorkItem = null; | ||
411 | |||
395 | //public bool HttpVerboseThrottle = true; // not implemented | 412 | //public bool HttpVerboseThrottle = true; // not implemented |
396 | public List<string> HttpCustomHeaders = null; | 413 | public List<string> HttpCustomHeaders = null; |
397 | public bool HttpPragmaNoCache = true; | 414 | public bool HttpPragmaNoCache = true; |
@@ -419,7 +436,7 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest | |||
419 | get { return _reqID; } | 436 | get { return _reqID; } |
420 | set { _reqID = value; } | 437 | set { _reqID = value; } |
421 | } | 438 | } |
422 | public WebRequest Request; | 439 | public HttpWebRequest Request; |
423 | public string ResponseBody; | 440 | public string ResponseBody; |
424 | public List<string> ResponseMetadata; | 441 | public List<string> ResponseMetadata; |
425 | public Dictionary<string, string> ResponseHeaders; | 442 | public Dictionary<string, string> ResponseHeaders; |
@@ -428,14 +445,38 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest | |||
428 | 445 | ||
429 | public void Process() | 446 | public void Process() |
430 | { | 447 | { |
448 | _finished = false; | ||
449 | |||
450 | lock (HttpRequestModule.ThreadPool) | ||
451 | WorkItem = HttpRequestModule.ThreadPool.QueueWorkItem(new WorkItemCallback(StpSendWrapper), null); | ||
452 | } | ||
453 | |||
454 | private object StpSendWrapper(object o) | ||
455 | { | ||
431 | SendRequest(); | 456 | SendRequest(); |
457 | return null; | ||
432 | } | 458 | } |
433 | 459 | ||
460 | /* | ||
461 | * TODO: More work on the response codes. Right now | ||
462 | * returning 200 for success or 499 for exception | ||
463 | */ | ||
464 | |||
434 | public void SendRequest() | 465 | public void SendRequest() |
435 | { | 466 | { |
467 | HttpWebResponse response = null; | ||
468 | StringBuilder sb = new StringBuilder(); | ||
469 | byte[] buf = new byte[8192]; | ||
470 | string tempString = null; | ||
471 | int count = 0; | ||
472 | |||
436 | try | 473 | try |
437 | { | 474 | { |
438 | Request = WebRequest.Create(Url); | 475 | Request = (HttpWebRequest) WebRequest.Create(Url); |
476 | |||
477 | //This works around some buggy HTTP Servers like Lighttpd | ||
478 | Request.ServicePoint.Expect100Continue = false; | ||
479 | |||
439 | Request.Method = HttpMethod; | 480 | Request.Method = HttpMethod; |
440 | Request.ContentType = HttpMIMEType; | 481 | Request.ContentType = HttpMIMEType; |
441 | 482 | ||
@@ -443,7 +484,6 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest | |||
443 | { | 484 | { |
444 | // We could hijack Connection Group Name to identify | 485 | // We could hijack Connection Group Name to identify |
445 | // a desired security exception. But at the moment we'll use a dummy header instead. | 486 | // a desired security exception. But at the moment we'll use a dummy header instead. |
446 | // Request.ConnectionGroupName = "NoVerify"; | ||
447 | Request.Headers.Add("NoVerifyCert", "true"); | 487 | Request.Headers.Add("NoVerifyCert", "true"); |
448 | } | 488 | } |
449 | // else | 489 | // else |
@@ -473,17 +513,14 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest | |||
473 | } | 513 | } |
474 | } | 514 | } |
475 | 515 | ||
476 | if (ResponseHeaders != null) | 516 | foreach (KeyValuePair<string, string> entry in ResponseHeaders) |
477 | { | 517 | if (entry.Key.ToLower().Equals("user-agent")) |
478 | foreach (KeyValuePair<string, string> entry in ResponseHeaders) | 518 | Request.UserAgent = entry.Value; |
479 | if (entry.Key.ToLower().Equals("user-agent") && Request is HttpWebRequest) | 519 | else |
480 | ((HttpWebRequest)Request).UserAgent = entry.Value; | 520 | Request.Headers[entry.Key] = entry.Value; |
481 | else | ||
482 | Request.Headers[entry.Key] = entry.Value; | ||
483 | } | ||
484 | 521 | ||
485 | // Encode outbound data | 522 | // Encode outbound data |
486 | if (OutboundBody != null && OutboundBody.Length > 0) | 523 | if (OutboundBody.Length > 0) |
487 | { | 524 | { |
488 | byte[] data = Util.UTF8.GetBytes(OutboundBody); | 525 | byte[] data = Util.UTF8.GetBytes(OutboundBody); |
489 | 526 | ||
@@ -493,12 +530,11 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest | |||
493 | bstream.Close(); | 530 | bstream.Close(); |
494 | } | 531 | } |
495 | 532 | ||
533 | Request.Timeout = HttpTimeout; | ||
496 | try | 534 | try |
497 | { | 535 | { |
498 | IAsyncResult result = (IAsyncResult)Request.BeginGetResponse(ResponseCallback, null); | 536 | // execute the request |
499 | 537 | response = (HttpWebResponse) Request.GetResponse(); | |
500 | ThreadPool.RegisterWaitForSingleObject( | ||
501 | result.AsyncWaitHandle, new WaitOrTimerCallback(TimeoutCallback), null, HttpTimeout, true); | ||
502 | } | 538 | } |
503 | catch (WebException e) | 539 | catch (WebException e) |
504 | { | 540 | { |
@@ -506,82 +542,91 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest | |||
506 | { | 542 | { |
507 | throw; | 543 | throw; |
508 | } | 544 | } |
545 | response = (HttpWebResponse)e.Response; | ||
546 | } | ||
509 | 547 | ||
510 | HttpWebResponse response = (HttpWebResponse)e.Response; | 548 | Status = (int)response.StatusCode; |
511 | 549 | ||
512 | Status = (int)response.StatusCode; | 550 | Stream resStream = response.GetResponseStream(); |
513 | ResponseBody = response.StatusDescription; | ||
514 | _finished = true; | ||
515 | } | ||
516 | } | ||
517 | catch (Exception e) | ||
518 | { | ||
519 | // m_log.Debug( | ||
520 | // string.Format("[SCRIPTS HTTP REQUESTS]: Exception on request to {0} for {1} ", Url, ItemID), e); | ||
521 | 551 | ||
522 | Status = (int)OSHttpStatusCode.ClientErrorJoker; | 552 | do |
523 | ResponseBody = e.Message; | 553 | { |
524 | _finished = true; | 554 | // fill the buffer with data |
525 | } | 555 | count = resStream.Read(buf, 0, buf.Length); |
526 | } | ||
527 | 556 | ||
528 | private void ResponseCallback(IAsyncResult ar) | 557 | // make sure we read some data |
529 | { | 558 | if (count != 0) |
530 | HttpWebResponse response = null; | 559 | { |
560 | // translate from bytes to ASCII text | ||
561 | tempString = Util.UTF8.GetString(buf, 0, count); | ||
531 | 562 | ||
532 | try | 563 | // continue building the string |
564 | sb.Append(tempString); | ||
565 | if (sb.Length > 2048) | ||
566 | break; | ||
567 | } | ||
568 | } while (count > 0); // any more data to read? | ||
569 | |||
570 | ResponseBody = sb.ToString().Replace("\r", ""); | ||
571 | } | ||
572 | catch (WebException e) | ||
533 | { | 573 | { |
534 | try | 574 | if (e.Status == WebExceptionStatus.ProtocolError) |
535 | { | ||
536 | response = (HttpWebResponse)Request.EndGetResponse(ar); | ||
537 | } | ||
538 | catch (WebException e) | ||
539 | { | 575 | { |
540 | if (e.Status != WebExceptionStatus.ProtocolError) | 576 | HttpWebResponse webRsp = (HttpWebResponse)((WebException)e).Response; |
577 | Status = (int)webRsp.StatusCode; | ||
578 | try | ||
541 | { | 579 | { |
542 | throw; | 580 | using (Stream responseStream = webRsp.GetResponseStream()) |
581 | { | ||
582 | ResponseBody = responseStream.GetStreamString(); | ||
583 | } | ||
584 | } | ||
585 | catch | ||
586 | { | ||
587 | ResponseBody = webRsp.StatusDescription; | ||
543 | } | 588 | } |
544 | 589 | } | |
545 | response = (HttpWebResponse)e.Response; | 590 | else |
591 | { | ||
592 | Status = (int)OSHttpStatusCode.ClientErrorJoker; | ||
593 | ResponseBody = e.Message; | ||
546 | } | 594 | } |
547 | 595 | ||
548 | Status = (int)response.StatusCode; | 596 | if (ResponseBody == null) |
597 | ResponseBody = String.Empty; | ||
549 | 598 | ||
550 | using (Stream stream = response.GetResponseStream()) | 599 | _finished = true; |
551 | { | 600 | return; |
552 | StreamReader reader = new StreamReader(stream, Encoding.UTF8); | ||
553 | ResponseBody = reader.ReadToEnd(); | ||
554 | } | ||
555 | } | 601 | } |
556 | catch (Exception e) | 602 | catch (Exception e) |
557 | { | 603 | { |
558 | Status = (int)OSHttpStatusCode.ClientErrorJoker; | 604 | // Don't crash on anything else |
559 | ResponseBody = e.Message; | ||
560 | |||
561 | // m_log.Debug( | ||
562 | // string.Format("[SCRIPTS HTTP REQUESTS]: Exception on response to {0} for {1} ", Url, ItemID), e); | ||
563 | } | 605 | } |
564 | finally | 606 | finally |
565 | { | 607 | { |
566 | if (response != null) | 608 | if (response != null) |
567 | response.Close(); | 609 | response.Close(); |
568 | |||
569 | _finished = true; | ||
570 | } | 610 | } |
571 | } | ||
572 | 611 | ||
573 | private void TimeoutCallback(object state, bool timedOut) | 612 | if (ResponseBody == null) |
574 | { | 613 | ResponseBody = String.Empty; |
575 | if (timedOut) | 614 | |
576 | Request.Abort(); | 615 | _finished = true; |
577 | } | 616 | } |
578 | 617 | ||
579 | public void Stop() | 618 | public void Stop() |
580 | { | 619 | { |
581 | // m_log.DebugFormat("[SCRIPTS HTTP REQUESTS]: Stopping request to {0} for {1} ", Url, ItemID); | 620 | try |
582 | 621 | { | |
583 | if (Request != null) | 622 | if (!WorkItem.Cancel()) |
584 | Request.Abort(); | 623 | { |
624 | WorkItem.Cancel(true); | ||
625 | } | ||
626 | } | ||
627 | catch (Exception) | ||
628 | { | ||
629 | } | ||
585 | } | 630 | } |
586 | } | 631 | } |
587 | } \ No newline at end of file | 632 | } |
diff --git a/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs b/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs index 99a3122..1983fed 100644 --- a/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs | |||
@@ -42,40 +42,16 @@ using OpenSim.Region.Framework.Scenes; | |||
42 | 42 | ||
43 | namespace OpenSim.Region.CoreModules.Scripting.LSLHttp | 43 | namespace OpenSim.Region.CoreModules.Scripting.LSLHttp |
44 | { | 44 | { |
45 | /// <summary> | ||
46 | /// Data describing an external URL set up by a script. | ||
47 | /// </summary> | ||
48 | public class UrlData | 45 | public class UrlData |
49 | { | 46 | { |
50 | /// <summary> | ||
51 | /// Scene object part hosting the script | ||
52 | /// </summary> | ||
53 | public UUID hostID; | 47 | public UUID hostID; |
54 | |||
55 | /// <summary> | ||
56 | /// The item ID of the script that requested the URL. | ||
57 | /// </summary> | ||
58 | public UUID itemID; | 48 | public UUID itemID; |
59 | |||
60 | /// <summary> | ||
61 | /// The script engine that runs the script. | ||
62 | /// </summary> | ||
63 | public IScriptModule engine; | 49 | public IScriptModule engine; |
64 | |||
65 | /// <summary> | ||
66 | /// The generated URL. | ||
67 | /// </summary> | ||
68 | public string url; | 50 | public string url; |
69 | |||
70 | /// <summary> | ||
71 | /// The random UUID component of the generated URL. | ||
72 | /// </summary> | ||
73 | public UUID urlcode; | 51 | 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; | 52 | public Dictionary<UUID, RequestData> requests; |
53 | public bool isSsl; | ||
54 | public Scene scene; | ||
79 | } | 55 | } |
80 | 56 | ||
81 | public class RequestData | 57 | public class RequestData |
@@ -89,7 +65,11 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp | |||
89 | //public ManualResetEvent ev; | 65 | //public ManualResetEvent ev; |
90 | public bool requestDone; | 66 | public bool requestDone; |
91 | public int startTime; | 67 | public int startTime; |
68 | public bool responseSent; | ||
92 | public string uri; | 69 | public string uri; |
70 | public bool allowResponseType = false; | ||
71 | public UUID hostID; | ||
72 | public Scene scene; | ||
93 | } | 73 | } |
94 | 74 | ||
95 | /// <summary> | 75 | /// <summary> |
@@ -102,20 +82,11 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp | |||
102 | LogManager.GetLogger( | 82 | LogManager.GetLogger( |
103 | MethodBase.GetCurrentMethod().DeclaringType); | 83 | MethodBase.GetCurrentMethod().DeclaringType); |
104 | 84 | ||
105 | /// <summary> | 85 | private Dictionary<UUID, UrlData> m_RequestMap = |
106 | /// Indexs the URL request metadata (which script requested it, outstanding requests, etc.) by the request ID | 86 | 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 | 87 | ||
115 | /// <summary> | 88 | private Dictionary<string, UrlData> m_UrlMap = |
116 | /// Indexs the URL request metadata (which script requested it, outstanding requests, etc.) by the full URL | 89 | new Dictionary<string, UrlData>(); |
117 | /// </summary> | ||
118 | private Dictionary<string, UrlData> m_UrlMap = new Dictionary<string, UrlData>(); | ||
119 | 90 | ||
120 | private uint m_HttpsPort = 0; | 91 | private uint m_HttpsPort = 0; |
121 | private IHttpServer m_HttpServer = null; | 92 | private IHttpServer m_HttpServer = null; |
@@ -126,7 +97,7 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp | |||
126 | /// <summary> | 97 | /// <summary> |
127 | /// The default maximum number of urls | 98 | /// The default maximum number of urls |
128 | /// </summary> | 99 | /// </summary> |
129 | public const int DefaultTotalUrls = 100; | 100 | public const int DefaultTotalUrls = 15000; |
130 | 101 | ||
131 | /// <summary> | 102 | /// <summary> |
132 | /// Maximum number of external urls that can be set up by this module. | 103 | /// Maximum number of external urls that can be set up by this module. |
@@ -204,6 +175,17 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp | |||
204 | 175 | ||
205 | public void RemoveRegion(Scene scene) | 176 | public void RemoveRegion(Scene scene) |
206 | { | 177 | { |
178 | // Drop references to that scene | ||
179 | foreach (KeyValuePair<string, UrlData> kvp in m_UrlMap) | ||
180 | { | ||
181 | if (kvp.Value.scene == scene) | ||
182 | kvp.Value.scene = null; | ||
183 | } | ||
184 | foreach (KeyValuePair<UUID, UrlData> kvp in m_RequestMap) | ||
185 | { | ||
186 | if (kvp.Value.scene == scene) | ||
187 | kvp.Value.scene = null; | ||
188 | } | ||
207 | } | 189 | } |
208 | 190 | ||
209 | public void Close() | 191 | public void Close() |
@@ -221,7 +203,7 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp | |||
221 | engine.PostScriptEvent(itemID, "http_request", new Object[] { urlcode.ToString(), "URL_REQUEST_DENIED", "" }); | 203 | engine.PostScriptEvent(itemID, "http_request", new Object[] { urlcode.ToString(), "URL_REQUEST_DENIED", "" }); |
222 | return urlcode; | 204 | return urlcode; |
223 | } | 205 | } |
224 | string url = "http://" + ExternalHostNameForLSL + ":" + m_HttpServer.Port.ToString() + "/lslhttp/" + urlcode.ToString() + "/"; | 206 | string url = "http://" + ExternalHostNameForLSL + ":" + m_HttpServer.Port.ToString() + "/lslhttp/" + urlcode.ToString(); |
225 | 207 | ||
226 | UrlData urlData = new UrlData(); | 208 | UrlData urlData = new UrlData(); |
227 | urlData.hostID = host.UUID; | 209 | urlData.hostID = host.UUID; |
@@ -229,20 +211,22 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp | |||
229 | urlData.engine = engine; | 211 | urlData.engine = engine; |
230 | urlData.url = url; | 212 | urlData.url = url; |
231 | urlData.urlcode = urlcode; | 213 | urlData.urlcode = urlcode; |
214 | urlData.isSsl = false; | ||
232 | urlData.requests = new Dictionary<UUID, RequestData>(); | 215 | urlData.requests = new Dictionary<UUID, RequestData>(); |
233 | 216 | urlData.scene = host.ParentGroup.Scene; | |
217 | |||
234 | m_UrlMap[url] = urlData; | 218 | m_UrlMap[url] = urlData; |
235 | 219 | ||
236 | string uri = "/lslhttp/" + urlcode.ToString() + "/"; | 220 | string uri = "/lslhttp/" + urlcode.ToString(); |
237 | 221 | ||
238 | PollServiceEventArgs args | 222 | PollServiceEventArgs args |
239 | = new PollServiceEventArgs(HttpRequestHandler, uri, HasEvents, GetEvents, NoEvents, urlcode, 25000); | 223 | = new PollServiceEventArgs(HttpRequestHandler, uri, HasEvents, GetEvents, NoEvents, urlcode, 25000); |
240 | args.Type = PollServiceEventArgs.EventType.LslHttp; | 224 | args.Type = PollServiceEventArgs.EventType.LslHttp; |
241 | m_HttpServer.AddPollServiceHTTPHandler(uri, args); | 225 | m_HttpServer.AddPollServiceHTTPHandler(uri, args); |
242 | 226 | ||
243 | m_log.DebugFormat( | 227 | // m_log.DebugFormat( |
244 | "[URL MODULE]: Set up incoming request url {0} for {1} in {2} {3}", | 228 | // "[URL MODULE]: Set up incoming request url {0} for {1} in {2} {3}", |
245 | uri, itemID, host.Name, host.LocalId); | 229 | // uri, itemID, host.Name, host.LocalId); |
246 | 230 | ||
247 | engine.PostScriptEvent(itemID, "http_request", new Object[] { urlcode.ToString(), "URL_REQUEST_GRANTED", url }); | 231 | engine.PostScriptEvent(itemID, "http_request", new Object[] { urlcode.ToString(), "URL_REQUEST_GRANTED", url }); |
248 | } | 232 | } |
@@ -267,7 +251,7 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp | |||
267 | engine.PostScriptEvent(itemID, "http_request", new Object[] { urlcode.ToString(), "URL_REQUEST_DENIED", "" }); | 251 | engine.PostScriptEvent(itemID, "http_request", new Object[] { urlcode.ToString(), "URL_REQUEST_DENIED", "" }); |
268 | return urlcode; | 252 | return urlcode; |
269 | } | 253 | } |
270 | string url = "https://" + ExternalHostNameForLSL + ":" + m_HttpsServer.Port.ToString() + "/lslhttps/" + urlcode.ToString() + "/"; | 254 | string url = "https://" + ExternalHostNameForLSL + ":" + m_HttpsServer.Port.ToString() + "/lslhttps/" + urlcode.ToString(); |
271 | 255 | ||
272 | UrlData urlData = new UrlData(); | 256 | UrlData urlData = new UrlData(); |
273 | urlData.hostID = host.UUID; | 257 | urlData.hostID = host.UUID; |
@@ -275,20 +259,22 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp | |||
275 | urlData.engine = engine; | 259 | urlData.engine = engine; |
276 | urlData.url = url; | 260 | urlData.url = url; |
277 | urlData.urlcode = urlcode; | 261 | urlData.urlcode = urlcode; |
262 | urlData.isSsl = true; | ||
278 | urlData.requests = new Dictionary<UUID, RequestData>(); | 263 | urlData.requests = new Dictionary<UUID, RequestData>(); |
279 | 264 | ||
265 | |||
280 | m_UrlMap[url] = urlData; | 266 | m_UrlMap[url] = urlData; |
281 | 267 | ||
282 | string uri = "/lslhttps/" + urlcode.ToString() + "/"; | 268 | string uri = "/lslhttps/" + urlcode.ToString(); |
283 | 269 | ||
284 | PollServiceEventArgs args | 270 | PollServiceEventArgs args |
285 | = new PollServiceEventArgs(HttpRequestHandler, uri, HasEvents, GetEvents, NoEvents, urlcode, 25000); | 271 | = new PollServiceEventArgs(HttpRequestHandler, uri, HasEvents, GetEvents, NoEvents, urlcode, 25000); |
286 | args.Type = PollServiceEventArgs.EventType.LslHttp; | 272 | args.Type = PollServiceEventArgs.EventType.LslHttp; |
287 | m_HttpsServer.AddPollServiceHTTPHandler(uri, args); | 273 | m_HttpsServer.AddPollServiceHTTPHandler(uri, args); |
288 | 274 | ||
289 | m_log.DebugFormat( | 275 | // m_log.DebugFormat( |
290 | "[URL MODULE]: Set up incoming secure request url {0} for {1} in {2} {3}", | 276 | // "[URL MODULE]: Set up incoming secure request url {0} for {1} in {2} {3}", |
291 | uri, itemID, host.Name, host.LocalId); | 277 | // uri, itemID, host.Name, host.LocalId); |
292 | 278 | ||
293 | engine.PostScriptEvent(itemID, "http_request", new Object[] { urlcode.ToString(), "URL_REQUEST_GRANTED", url }); | 279 | engine.PostScriptEvent(itemID, "http_request", new Object[] { urlcode.ToString(), "URL_REQUEST_GRANTED", url }); |
294 | } | 280 | } |
@@ -307,12 +293,15 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp | |||
307 | return; | 293 | return; |
308 | } | 294 | } |
309 | 295 | ||
310 | foreach (UUID req in data.requests.Keys) | 296 | lock (m_RequestMap) |
311 | m_RequestMap.Remove(req); | 297 | { |
312 | 298 | foreach (UUID req in data.requests.Keys) | |
313 | m_log.DebugFormat( | 299 | m_RequestMap.Remove(req); |
314 | "[URL MODULE]: Releasing url {0} for {1} in {2}", | 300 | } |
315 | url, data.itemID, data.hostID); | 301 | |
302 | // m_log.DebugFormat( | ||
303 | // "[URL MODULE]: Releasing url {0} for {1} in {2}", | ||
304 | // url, data.itemID, data.hostID); | ||
316 | 305 | ||
317 | RemoveUrl(data); | 306 | RemoveUrl(data); |
318 | m_UrlMap.Remove(url); | 307 | m_UrlMap.Remove(url); |
@@ -337,29 +326,39 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp | |||
337 | 326 | ||
338 | public void HttpResponse(UUID request, int status, string body) | 327 | public void HttpResponse(UUID request, int status, string body) |
339 | { | 328 | { |
340 | lock (m_UrlMap) | 329 | lock (m_RequestMap) |
341 | { | 330 | { |
342 | if (m_RequestMap.ContainsKey(request)) | 331 | if (m_RequestMap.ContainsKey(request)) |
343 | { | 332 | { |
344 | UrlData urlData = m_RequestMap[request]; | 333 | UrlData urlData = m_RequestMap[request]; |
345 | string responseBody = body; | 334 | if (!urlData.requests[request].responseSent) |
346 | if (urlData.requests[request].responseType.Equals("text/plain")) | ||
347 | { | 335 | { |
348 | string value; | 336 | string responseBody = body; |
349 | if (urlData.requests[request].headers.TryGetValue("user-agent", out value)) | 337 | |
338 | // If we have no OpenID from built-in browser, disable this | ||
339 | if (!urlData.requests[request].allowResponseType) | ||
340 | urlData.requests[request].responseType = "text/plain"; | ||
341 | |||
342 | if (urlData.requests[request].responseType.Equals("text/plain")) | ||
350 | { | 343 | { |
351 | if (value != null && value.IndexOf("MSIE") >= 0) | 344 | string value; |
345 | if (urlData.requests[request].headers.TryGetValue("user-agent", out value)) | ||
352 | { | 346 | { |
353 | // wrap the html escaped response if the target client is IE | 347 | if (value != null && value.IndexOf("MSIE") >= 0) |
354 | // It ignores "text/plain" if the body is html | 348 | { |
355 | responseBody = "<html>" + System.Web.HttpUtility.HtmlEncode(body) + "</html>"; | 349 | // wrap the html escaped response if the target client is IE |
350 | // It ignores "text/plain" if the body is html | ||
351 | responseBody = "<html>" + System.Web.HttpUtility.HtmlEncode(body) + "</html>"; | ||
352 | } | ||
356 | } | 353 | } |
357 | } | 354 | } |
355 | |||
356 | urlData.requests[request].responseCode = status; | ||
357 | urlData.requests[request].responseBody = body; | ||
358 | //urlData.requests[request].ev.Set(); | ||
359 | urlData.requests[request].requestDone = true; | ||
360 | urlData.requests[request].responseSent = true; | ||
358 | } | 361 | } |
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 | } | 362 | } |
364 | else | 363 | else |
365 | { | 364 | { |
@@ -370,7 +369,7 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp | |||
370 | 369 | ||
371 | public string GetHttpHeader(UUID requestId, string header) | 370 | public string GetHttpHeader(UUID requestId, string header) |
372 | { | 371 | { |
373 | lock (m_UrlMap) | 372 | lock (m_RequestMap) |
374 | { | 373 | { |
375 | if (m_RequestMap.ContainsKey(requestId)) | 374 | if (m_RequestMap.ContainsKey(requestId)) |
376 | { | 375 | { |
@@ -384,7 +383,6 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp | |||
384 | m_log.Warn("[HttpRequestHandler] There was no http-in request with id " + requestId); | 383 | m_log.Warn("[HttpRequestHandler] There was no http-in request with id " + requestId); |
385 | } | 384 | } |
386 | } | 385 | } |
387 | |||
388 | return String.Empty; | 386 | return String.Empty; |
389 | } | 387 | } |
390 | 388 | ||
@@ -408,8 +406,11 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp | |||
408 | { | 406 | { |
409 | RemoveUrl(url.Value); | 407 | RemoveUrl(url.Value); |
410 | removeURLs.Add(url.Key); | 408 | removeURLs.Add(url.Key); |
411 | foreach (UUID req in url.Value.requests.Keys) | 409 | lock (m_RequestMap) |
412 | m_RequestMap.Remove(req); | 410 | { |
411 | foreach (UUID req in url.Value.requests.Keys) | ||
412 | m_RequestMap.Remove(req); | ||
413 | } | ||
413 | } | 414 | } |
414 | } | 415 | } |
415 | 416 | ||
@@ -430,9 +431,11 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp | |||
430 | { | 431 | { |
431 | RemoveUrl(url.Value); | 432 | RemoveUrl(url.Value); |
432 | removeURLs.Add(url.Key); | 433 | removeURLs.Add(url.Key); |
433 | 434 | lock (m_RequestMap) | |
434 | foreach (UUID req in url.Value.requests.Keys) | 435 | { |
435 | m_RequestMap.Remove(req); | 436 | foreach (UUID req in url.Value.requests.Keys) |
437 | m_RequestMap.Remove(req); | ||
438 | } | ||
436 | } | 439 | } |
437 | } | 440 | } |
438 | 441 | ||
@@ -441,123 +444,128 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp | |||
441 | } | 444 | } |
442 | } | 445 | } |
443 | 446 | ||
447 | |||
444 | private void RemoveUrl(UrlData data) | 448 | private void RemoveUrl(UrlData data) |
445 | { | 449 | { |
446 | m_HttpServer.RemoveHTTPHandler("", "/lslhttp/" + data.urlcode.ToString() + "/"); | 450 | if (data.isSsl) |
451 | m_HttpsServer.RemoveHTTPHandler("", "/lslhttps/"+data.urlcode.ToString()+"/"); | ||
452 | else | ||
453 | m_HttpServer.RemoveHTTPHandler("", "/lslhttp/"+data.urlcode.ToString()+"/"); | ||
447 | } | 454 | } |
448 | 455 | ||
449 | private Hashtable NoEvents(UUID requestID, UUID sessionID) | 456 | private Hashtable NoEvents(UUID requestID, UUID sessionID) |
450 | { | 457 | { |
451 | Hashtable response = new Hashtable(); | 458 | Hashtable response = new Hashtable(); |
452 | UrlData urlData; | 459 | UrlData url; |
453 | 460 | int startTime = 0; | |
454 | lock (m_UrlMap) | 461 | lock (m_RequestMap) |
455 | { | 462 | { |
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)) | 463 | 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; | 464 | return response; |
467 | } | 465 | url = m_RequestMap[requestID]; |
466 | startTime = url.requests[requestID].startTime; | ||
467 | } | ||
468 | 468 | ||
469 | urlData = m_RequestMap[requestID]; | 469 | if (System.Environment.TickCount - startTime > 25000) |
470 | { | ||
471 | response["int_response_code"] = 500; | ||
472 | response["str_response_string"] = "Script timeout"; | ||
473 | response["content_type"] = "text/plain"; | ||
474 | response["keepalive"] = false; | ||
475 | response["reusecontext"] = false; | ||
470 | 476 | ||
471 | if (System.Environment.TickCount - urlData.requests[requestID].startTime > 25000) | 477 | //remove from map |
478 | lock (url.requests) | ||
479 | { | ||
480 | url.requests.Remove(requestID); | ||
481 | } | ||
482 | lock (m_RequestMap) | ||
472 | { | 483 | { |
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); | 484 | m_RequestMap.Remove(requestID); |
482 | |||
483 | return response; | ||
484 | } | 485 | } |
486 | |||
487 | return response; | ||
485 | } | 488 | } |
486 | 489 | ||
490 | |||
487 | return response; | 491 | return response; |
488 | } | 492 | } |
489 | 493 | ||
490 | private bool HasEvents(UUID requestID, UUID sessionID) | 494 | private bool HasEvents(UUID requestID, UUID sessionID) |
491 | { | 495 | { |
492 | lock (m_UrlMap) | 496 | UrlData url=null; |
497 | |||
498 | lock (m_RequestMap) | ||
493 | { | 499 | { |
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)) | 500 | if (!m_RequestMap.ContainsKey(requestID)) |
500 | { | 501 | { |
501 | return true; | 502 | return false; |
502 | } | 503 | } |
503 | 504 | url = m_RequestMap[requestID]; | |
504 | UrlData urlData = m_RequestMap[requestID]; | 505 | } |
505 | 506 | lock (url.requests) | |
506 | if (!urlData.requests.ContainsKey(requestID)) | 507 | { |
508 | if (!url.requests.ContainsKey(requestID)) | ||
507 | { | 509 | { |
508 | return true; | 510 | return false; |
509 | } | 511 | } |
510 | 512 | else | |
511 | // Trigger return of timeout response. | ||
512 | if (System.Environment.TickCount - urlData.requests[requestID].startTime > 25000) | ||
513 | { | 513 | { |
514 | return true; | 514 | if (System.Environment.TickCount - url.requests[requestID].startTime > 25000) |
515 | { | ||
516 | return true; | ||
517 | } | ||
518 | if (url.requests[requestID].requestDone) | ||
519 | return true; | ||
520 | else | ||
521 | return false; | ||
515 | } | 522 | } |
516 | |||
517 | return urlData.requests[requestID].requestDone; | ||
518 | } | 523 | } |
519 | } | 524 | } |
520 | |||
521 | private Hashtable GetEvents(UUID requestID, UUID sessionID) | 525 | private Hashtable GetEvents(UUID requestID, UUID sessionID) |
522 | { | 526 | { |
523 | Hashtable response; | 527 | UrlData url = null; |
528 | RequestData requestData = null; | ||
524 | 529 | ||
525 | lock (m_UrlMap) | 530 | lock (m_RequestMap) |
526 | { | 531 | { |
527 | UrlData url = null; | ||
528 | RequestData requestData = null; | ||
529 | |||
530 | if (!m_RequestMap.ContainsKey(requestID)) | 532 | if (!m_RequestMap.ContainsKey(requestID)) |
531 | return NoEvents(requestID, sessionID); | 533 | return NoEvents(requestID,sessionID); |
532 | |||
533 | url = m_RequestMap[requestID]; | 534 | url = m_RequestMap[requestID]; |
535 | } | ||
536 | lock (url.requests) | ||
537 | { | ||
534 | requestData = url.requests[requestID]; | 538 | requestData = url.requests[requestID]; |
539 | } | ||
540 | |||
541 | if (!requestData.requestDone) | ||
542 | return NoEvents(requestID,sessionID); | ||
543 | |||
544 | Hashtable response = new Hashtable(); | ||
535 | 545 | ||
536 | if (!requestData.requestDone) | 546 | if (System.Environment.TickCount - requestData.startTime > 25000) |
537 | return NoEvents(requestID, sessionID); | 547 | { |
538 | 548 | response["int_response_code"] = 500; | |
539 | response = new Hashtable(); | 549 | response["str_response_string"] = "Script timeout"; |
540 | 550 | response["content_type"] = "text/plain"; | |
541 | if (System.Environment.TickCount - requestData.startTime > 25000) | ||
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 | |||
551 | //put response | ||
552 | response["int_response_code"] = requestData.responseCode; | ||
553 | response["str_response_string"] = requestData.responseBody; | ||
554 | response["content_type"] = requestData.responseType; | ||
555 | // response["content_type"] = "text/plain"; | ||
556 | response["keepalive"] = false; | 551 | response["keepalive"] = false; |
557 | response["reusecontext"] = false; | 552 | response["reusecontext"] = false; |
558 | 553 | return response; | |
559 | //remove from map | 554 | } |
555 | //put response | ||
556 | response["int_response_code"] = requestData.responseCode; | ||
557 | response["str_response_string"] = requestData.responseBody; | ||
558 | response["content_type"] = requestData.responseType; | ||
559 | response["keepalive"] = false; | ||
560 | response["reusecontext"] = false; | ||
561 | |||
562 | //remove from map | ||
563 | lock (url.requests) | ||
564 | { | ||
560 | url.requests.Remove(requestID); | 565 | url.requests.Remove(requestID); |
566 | } | ||
567 | lock (m_RequestMap) | ||
568 | { | ||
561 | m_RequestMap.Remove(requestID); | 569 | m_RequestMap.Remove(requestID); |
562 | } | 570 | } |
563 | 571 | ||
@@ -566,41 +574,45 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp | |||
566 | 574 | ||
567 | public void HttpRequestHandler(UUID requestID, Hashtable request) | 575 | public void HttpRequestHandler(UUID requestID, Hashtable request) |
568 | { | 576 | { |
569 | string uri = request["uri"].ToString(); | 577 | lock (request) |
570 | bool is_ssl = uri.Contains("lslhttps"); | ||
571 | |||
572 | try | ||
573 | { | 578 | { |
574 | Hashtable headers = (Hashtable)request["headers"]; | 579 | string uri = request["uri"].ToString(); |
580 | bool is_ssl = uri.Contains("lslhttps"); | ||
575 | 581 | ||
576 | // string uri_full = "http://" + m_ExternalHostNameForLSL + ":" + m_HttpServer.Port.ToString() + uri;// "/lslhttp/" + urlcode.ToString() + "/"; | 582 | try |
577 | |||
578 | int pos1 = uri.IndexOf("/");// /lslhttp | ||
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 | |||
587 | pathInfo = uri.Substring(pos3); | ||
588 | |||
589 | UrlData urlData = null; | ||
590 | |||
591 | lock (m_UrlMap) | ||
592 | { | 583 | { |
593 | string url; | 584 | Hashtable headers = (Hashtable)request["headers"]; |
594 | 585 | ||
595 | if (is_ssl) | 586 | // string uri_full = "http://" + ExternalHostNameForLSL + ":" + m_HttpServer.Port.ToString() + uri;// "/lslhttp/" + urlcode.ToString() + "/"; |
596 | url = "https://" + ExternalHostNameForLSL + ":" + m_HttpsServer.Port.ToString() + uri_tmp; | 587 | |
588 | int pos1 = uri.IndexOf("/");// /lslhttp | ||
589 | int pos2 = uri.IndexOf("/", pos1 + 1);// /lslhttp/ | ||
590 | int pos3 = pos2 + 37; // /lslhttp/urlcode | ||
591 | string uri_tmp = uri.Substring(0, pos3); | ||
592 | //HTTP server code doesn't provide us with QueryStrings | ||
593 | string pathInfo; | ||
594 | string queryString; | ||
595 | queryString = ""; | ||
596 | |||
597 | pathInfo = uri.Substring(pos3); | ||
598 | |||
599 | UrlData url = null; | ||
600 | string urlkey; | ||
601 | if (!is_ssl) | ||
602 | urlkey = "http://" + ExternalHostNameForLSL + ":" + m_HttpServer.Port.ToString() + uri_tmp; | ||
603 | //m_UrlMap[]; | ||
597 | else | 604 | else |
598 | url = "http://" + ExternalHostNameForLSL + ":" + m_HttpServer.Port.ToString() + uri_tmp; | 605 | urlkey = "https://" + ExternalHostNameForLSL + ":" + m_HttpsServer.Port.ToString() + uri_tmp; |
599 | 606 | ||
600 | // Avoid a race - the request URL may have been released via llRequestUrl() whilst this | 607 | if (m_UrlMap.ContainsKey(urlkey)) |
601 | // request was being processed. | 608 | { |
602 | if (!m_UrlMap.TryGetValue(url, out urlData)) | 609 | url = m_UrlMap[urlkey]; |
610 | } | ||
611 | else | ||
612 | { | ||
613 | //m_log.Warn("[HttpRequestHandler]: http-in request failed; no such url: "+urlkey.ToString()); | ||
603 | return; | 614 | return; |
615 | } | ||
604 | 616 | ||
605 | //for llGetHttpHeader support we need to store original URI here | 617 | //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 | 618 | //to make x-path-info / x-query-string / x-script-url / x-remote-ip headers |
@@ -611,6 +623,8 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp | |||
611 | requestData.requestDone = false; | 623 | requestData.requestDone = false; |
612 | requestData.startTime = System.Environment.TickCount; | 624 | requestData.startTime = System.Environment.TickCount; |
613 | requestData.uri = uri; | 625 | requestData.uri = uri; |
626 | requestData.hostID = url.hostID; | ||
627 | requestData.scene = url.scene; | ||
614 | if (requestData.headers == null) | 628 | if (requestData.headers == null) |
615 | requestData.headers = new Dictionary<string, string>(); | 629 | requestData.headers = new Dictionary<string, string>(); |
616 | 630 | ||
@@ -619,8 +633,33 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp | |||
619 | string key = (string)header.Key; | 633 | string key = (string)header.Key; |
620 | string value = (string)header.Value; | 634 | string value = (string)header.Value; |
621 | requestData.headers.Add(key, value); | 635 | requestData.headers.Add(key, value); |
636 | if (key == "cookie") | ||
637 | { | ||
638 | string[] parts = value.Split(new char[] {'='}); | ||
639 | if (parts[0] == "agni_sl_session_id" && parts.Length > 1) | ||
640 | { | ||
641 | string cookie = Uri.UnescapeDataString(parts[1]); | ||
642 | string[] crumbs = cookie.Split(new char[] {':'}); | ||
643 | UUID owner; | ||
644 | if (crumbs.Length == 2 && UUID.TryParse(crumbs[0], out owner)) | ||
645 | { | ||
646 | if (crumbs[1].Length == 32) | ||
647 | { | ||
648 | Scene scene = requestData.scene; | ||
649 | if (scene != null) | ||
650 | { | ||
651 | SceneObjectPart host = scene.GetSceneObjectPart(requestData.hostID); | ||
652 | if (host != null) | ||
653 | { | ||
654 | if (host.OwnerID == owner) | ||
655 | requestData.allowResponseType = true; | ||
656 | } | ||
657 | } | ||
658 | } | ||
659 | } | ||
660 | } | ||
661 | } | ||
622 | } | 662 | } |
623 | |||
624 | foreach (DictionaryEntry de in request) | 663 | foreach (DictionaryEntry de in request) |
625 | { | 664 | { |
626 | if (de.Key.ToString() == "querystringkeys") | 665 | if (de.Key.ToString() == "querystringkeys") |
@@ -631,13 +670,21 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp | |||
631 | if (request.ContainsKey(key)) | 670 | if (request.ContainsKey(key)) |
632 | { | 671 | { |
633 | string val = (String)request[key]; | 672 | string val = (String)request[key]; |
634 | queryString = queryString + key + "=" + val + "&"; | 673 | if (key != "") |
674 | { | ||
675 | queryString = queryString + key + "=" + val + "&"; | ||
676 | } | ||
677 | else | ||
678 | { | ||
679 | queryString = queryString + val + "&"; | ||
680 | } | ||
635 | } | 681 | } |
636 | } | 682 | } |
637 | |||
638 | if (queryString.Length > 1) | 683 | if (queryString.Length > 1) |
639 | queryString = queryString.Substring(0, queryString.Length - 1); | 684 | queryString = queryString.Substring(0, queryString.Length - 1); |
685 | |||
640 | } | 686 | } |
687 | |||
641 | } | 688 | } |
642 | 689 | ||
643 | //if this machine is behind DNAT/port forwarding, currently this is being | 690 | //if this machine is behind DNAT/port forwarding, currently this is being |
@@ -645,23 +692,34 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp | |||
645 | requestData.headers["x-remote-ip"] = requestData.headers["remote_addr"]; | 692 | requestData.headers["x-remote-ip"] = requestData.headers["remote_addr"]; |
646 | requestData.headers["x-path-info"] = pathInfo; | 693 | requestData.headers["x-path-info"] = pathInfo; |
647 | requestData.headers["x-query-string"] = queryString; | 694 | requestData.headers["x-query-string"] = queryString; |
648 | requestData.headers["x-script-url"] = urlData.url; | 695 | requestData.headers["x-script-url"] = url.url; |
649 | 696 | ||
650 | urlData.requests.Add(requestID, requestData); | 697 | //requestData.ev = new ManualResetEvent(false); |
651 | m_RequestMap.Add(requestID, urlData); | 698 | lock (url.requests) |
652 | } | 699 | { |
700 | url.requests.Add(requestID, requestData); | ||
701 | } | ||
702 | lock (m_RequestMap) | ||
703 | { | ||
704 | //add to request map | ||
705 | m_RequestMap.Add(requestID, url); | ||
706 | } | ||
653 | 707 | ||
654 | urlData.engine.PostScriptEvent( | 708 | url.engine.PostScriptEvent(url.itemID, "http_request", new Object[] { requestID.ToString(), request["http-method"].ToString(), request["body"].ToString() }); |
655 | urlData.itemID, | 709 | |
656 | "http_request", | 710 | //send initial response? |
657 | new Object[] { requestID.ToString(), request["http-method"].ToString(), request["body"].ToString() }); | 711 | // Hashtable response = new Hashtable(); |
658 | } | 712 | |
659 | catch (Exception we) | 713 | return; |
660 | { | 714 | |
661 | //Hashtable response = new Hashtable(); | 715 | } |
662 | m_log.Warn("[HttpRequestHandler]: http-in request failed"); | 716 | catch (Exception we) |
663 | m_log.Warn(we.Message); | 717 | { |
664 | m_log.Warn(we.StackTrace); | 718 | //Hashtable response = new Hashtable(); |
719 | m_log.Warn("[HttpRequestHandler]: http-in request failed"); | ||
720 | m_log.Warn(we.Message); | ||
721 | m_log.Warn(we.StackTrace); | ||
722 | } | ||
665 | } | 723 | } |
666 | } | 724 | } |
667 | 725 | ||
diff --git a/OpenSim/Region/CoreModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs b/OpenSim/Region/CoreModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs index 6da2222..ad33f23 100644 --- a/OpenSim/Region/CoreModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs | |||
@@ -271,6 +271,8 @@ namespace OpenSim.Region.CoreModules.Scripting.ScriptModuleComms | |||
271 | return "modInvokeR"; | 271 | return "modInvokeR"; |
272 | else if (sid.ReturnType == typeof(object[])) | 272 | else if (sid.ReturnType == typeof(object[])) |
273 | return "modInvokeL"; | 273 | return "modInvokeL"; |
274 | else if (sid.ReturnType == typeof(void)) | ||
275 | return "modInvokeN"; | ||
274 | 276 | ||
275 | m_log.WarnFormat("[MODULE COMMANDS] failed to find match for {0} with return type {1}",fname,sid.ReturnType.Name); | 277 | m_log.WarnFormat("[MODULE COMMANDS] failed to find match for {0} with return type {1}",fname,sid.ReturnType.Name); |
276 | } | 278 | } |
diff --git a/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs b/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs index 4cecd85..2fc89fc 100644 --- a/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs | |||
@@ -861,4 +861,4 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender | |||
861 | return null; | 861 | return null; |
862 | } | 862 | } |
863 | } | 863 | } |
864 | } \ No newline at end of file | 864 | } |
diff --git a/OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs b/OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs index 2c2c99c..87a0537 100644 --- a/OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs | |||
@@ -96,6 +96,8 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm | |||
96 | // private static readonly ILog m_log = | 96 | // private static readonly ILog m_log = |
97 | // LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 97 | // LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
98 | 98 | ||
99 | private const int DEBUG_CHANNEL = 2147483647; | ||
100 | |||
99 | private ListenerManager m_listenerManager; | 101 | private ListenerManager m_listenerManager; |
100 | private Queue m_pending; | 102 | private Queue m_pending; |
101 | private Queue m_pendingQ; | 103 | private Queue m_pendingQ; |
@@ -366,67 +368,60 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm | |||
366 | /// <param name='msg'> | 368 | /// <param name='msg'> |
367 | /// Message. | 369 | /// Message. |
368 | /// </param> | 370 | /// </param> |
369 | public void DeliverMessageTo(UUID target, int channel, Vector3 pos, | 371 | public bool DeliverMessageTo(UUID target, int channel, Vector3 pos, string name, UUID id, string msg, out string error) |
370 | string name, UUID id, string msg) | ||
371 | { | 372 | { |
373 | error = null; | ||
374 | |||
375 | if (channel == DEBUG_CHANNEL) | ||
376 | return true; | ||
377 | |||
372 | // Is id an avatar? | 378 | // Is id an avatar? |
373 | ScenePresence sp = m_scene.GetScenePresence(target); | 379 | ScenePresence sp = m_scene.GetScenePresence(target); |
374 | 380 | ||
375 | if (sp != null) | 381 | if (sp != null) |
376 | { | 382 | { |
377 | // ignore if a child agent this is restricted to inside one | 383 | // Send message to avatar |
378 | // region | ||
379 | if (sp.IsChildAgent) | ||
380 | return; | ||
381 | |||
382 | // Send message to the avatar. | ||
383 | // Channel zero only goes to the avatar | ||
384 | // non zero channel messages only go to the attachments | ||
385 | if (channel == 0) | 384 | if (channel == 0) |
386 | { | 385 | { |
387 | m_scene.SimChatToAgent(target, Utils.StringToBytes(msg), | 386 | // Channel 0 goes to viewer ONLY |
388 | pos, name, id, false); | 387 | m_scene.SimChat(Utils.StringToBytes(msg), ChatTypeEnum.Broadcast, 0, pos, name, id, target, false, false); |
388 | return true; | ||
389 | } | 389 | } |
390 | else | ||
391 | { | ||
392 | List<SceneObjectGroup> attachments = sp.GetAttachments(); | ||
393 | if (attachments.Count == 0) | ||
394 | return; | ||
395 | 390 | ||
396 | // Get uuid of attachments | 391 | List<SceneObjectGroup> attachments = sp.GetAttachments(); |
397 | List<UUID> targets = new List<UUID>(); | ||
398 | foreach (SceneObjectGroup sog in attachments) | ||
399 | { | ||
400 | if (!sog.IsDeleted) | ||
401 | targets.Add(sog.UUID); | ||
402 | } | ||
403 | 392 | ||
404 | // Need to check each attachment | 393 | if (attachments.Count == 0) |
405 | foreach (ListenerInfo li | 394 | return true; |
406 | in m_listenerManager.GetListeners(UUID.Zero, | ||
407 | channel, name, id, msg)) | ||
408 | { | ||
409 | if (li.GetHostID().Equals(id)) | ||
410 | continue; | ||
411 | 395 | ||
412 | if (m_scene.GetSceneObjectPart( | 396 | // Get uuid of attachments |
413 | li.GetHostID()) == null) | 397 | List<UUID> targets = new List<UUID>(); |
414 | { | 398 | foreach (SceneObjectGroup sog in attachments) |
415 | continue; | 399 | { |
416 | } | 400 | if (!sog.IsDeleted) |
401 | targets.Add(sog.UUID); | ||
402 | } | ||
417 | 403 | ||
418 | if (targets.Contains(li.GetHostID())) | 404 | // Need to check each attachment |
419 | QueueMessage(new ListenerInfo(li, name, id, msg)); | 405 | foreach (ListenerInfo li in m_listenerManager.GetListeners(UUID.Zero, channel, name, id, msg)) |
420 | } | 406 | { |
407 | if (li.GetHostID().Equals(id)) | ||
408 | continue; | ||
409 | |||
410 | if (m_scene.GetSceneObjectPart(li.GetHostID()) == null) | ||
411 | continue; | ||
412 | |||
413 | if (targets.Contains(li.GetHostID())) | ||
414 | QueueMessage(new ListenerInfo(li, name, id, msg)); | ||
421 | } | 415 | } |
422 | 416 | ||
423 | return; | 417 | return true; |
424 | } | 418 | } |
425 | 419 | ||
426 | // No avatar found so look for an object | 420 | SceneObjectPart part = m_scene.GetSceneObjectPart(target); |
427 | foreach (ListenerInfo li | 421 | if (part == null) // Not even an object |
428 | in m_listenerManager.GetListeners(UUID.Zero, channel, | 422 | return true; // No error |
429 | name, id, msg)) | 423 | |
424 | foreach (ListenerInfo li in m_listenerManager.GetListeners(UUID.Zero, channel, name, id, msg)) | ||
430 | { | 425 | { |
431 | // Dont process if this message is from yourself! | 426 | // Dont process if this message is from yourself! |
432 | if (li.GetHostID().Equals(id)) | 427 | if (li.GetHostID().Equals(id)) |
@@ -444,7 +439,7 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm | |||
444 | } | 439 | } |
445 | } | 440 | } |
446 | 441 | ||
447 | return; | 442 | return true; |
448 | } | 443 | } |
449 | 444 | ||
450 | protected void QueueMessage(ListenerInfo li) | 445 | protected void QueueMessage(ListenerInfo li) |