diff options
Diffstat (limited to 'OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs')
-rw-r--r-- | OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs | 233 |
1 files changed, 146 insertions, 87 deletions
diff --git a/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs b/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs index b1f3f9b..235fbbb 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; |
@@ -46,6 +43,7 @@ using OpenSim.Framework.Servers.HttpServer; | |||
46 | using OpenSim.Region.Framework.Interfaces; | 43 | using OpenSim.Region.Framework.Interfaces; |
47 | using OpenSim.Region.Framework.Scenes; | 44 | using OpenSim.Region.Framework.Scenes; |
48 | using Mono.Addins; | 45 | using Mono.Addins; |
46 | using Amib.Threading; | ||
49 | 47 | ||
50 | /***************************************************** | 48 | /***************************************************** |
51 | * | 49 | * |
@@ -109,6 +107,7 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest | |||
109 | private Dictionary<UUID, HttpRequestClass> m_pendingRequests; | 107 | private Dictionary<UUID, HttpRequestClass> m_pendingRequests; |
110 | private Scene m_scene; | 108 | private Scene m_scene; |
111 | // private Queue<HttpRequestClass> rpcQueue = new Queue<HttpRequestClass>(); | 109 | // private Queue<HttpRequestClass> rpcQueue = new Queue<HttpRequestClass>(); |
110 | public static SmartThreadPool ThreadPool = null; | ||
112 | 111 | ||
113 | public HttpRequestModule() | 112 | public HttpRequestModule() |
114 | { | 113 | { |
@@ -291,29 +290,18 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest | |||
291 | return true; | 290 | return true; |
292 | } | 291 | } |
293 | 292 | ||
294 | public void StopHttpRequestsForScript(UUID id) | 293 | public void StopHttpRequest(uint m_localID, UUID m_itemID) |
295 | { | 294 | { |
296 | if (m_pendingRequests != null) | 295 | if (m_pendingRequests != null) |
297 | { | 296 | { |
298 | List<UUID> keysToRemove = null; | ||
299 | |||
300 | lock (HttpListLock) | 297 | lock (HttpListLock) |
301 | { | 298 | { |
302 | foreach (HttpRequestClass req in m_pendingRequests.Values) | 299 | HttpRequestClass tmpReq; |
300 | if (m_pendingRequests.TryGetValue(m_itemID, out tmpReq)) | ||
303 | { | 301 | { |
304 | if (req.ItemID == id) | 302 | tmpReq.Stop(); |
305 | { | 303 | m_pendingRequests.Remove(m_itemID); |
306 | req.Stop(); | ||
307 | |||
308 | if (keysToRemove == null) | ||
309 | keysToRemove = new List<UUID>(); | ||
310 | |||
311 | keysToRemove.Add(req.ReqID); | ||
312 | } | ||
313 | } | 304 | } |
314 | |||
315 | if (keysToRemove != null) | ||
316 | keysToRemove.ForEach(keyToRemove => m_pendingRequests.Remove(keyToRemove)); | ||
317 | } | 305 | } |
318 | } | 306 | } |
319 | } | 307 | } |
@@ -331,13 +319,19 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest | |||
331 | { | 319 | { |
332 | lock (HttpListLock) | 320 | lock (HttpListLock) |
333 | { | 321 | { |
334 | foreach (HttpRequestClass req in m_pendingRequests.Values) | 322 | foreach (UUID luid in m_pendingRequests.Keys) |
335 | { | 323 | { |
336 | if (req.Finished) | 324 | HttpRequestClass tmpReq; |
337 | return req; | 325 | |
326 | if (m_pendingRequests.TryGetValue(luid, out tmpReq)) | ||
327 | { | ||
328 | if (tmpReq.Finished) | ||
329 | { | ||
330 | return tmpReq; | ||
331 | } | ||
332 | } | ||
338 | } | 333 | } |
339 | } | 334 | } |
340 | |||
341 | return null; | 335 | return null; |
342 | } | 336 | } |
343 | 337 | ||
@@ -364,9 +358,34 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest | |||
364 | m_proxyurl = config.Configs["Startup"].GetString("HttpProxy"); | 358 | m_proxyurl = config.Configs["Startup"].GetString("HttpProxy"); |
365 | m_proxyexcepts = config.Configs["Startup"].GetString("HttpProxyExceptions"); | 359 | m_proxyexcepts = config.Configs["Startup"].GetString("HttpProxyExceptions"); |
366 | 360 | ||
361 | <<<<<<< HEAD | ||
367 | m_outboundUrlFilter = new OutboundUrlFilter("Script HTTP request module", config); | 362 | m_outboundUrlFilter = new OutboundUrlFilter("Script HTTP request module", config); |
363 | ======= | ||
364 | int maxThreads = 15; | ||
365 | |||
366 | IConfig httpConfig = config.Configs["HttpRequestModule"]; | ||
367 | if (httpConfig != null) | ||
368 | { | ||
369 | maxThreads = httpConfig.GetInt("MaxPoolThreads", maxThreads); | ||
370 | } | ||
371 | >>>>>>> avn/ubitvar | ||
368 | 372 | ||
369 | m_pendingRequests = new Dictionary<UUID, HttpRequestClass>(); | 373 | m_pendingRequests = new Dictionary<UUID, HttpRequestClass>(); |
374 | |||
375 | // First instance sets this up for all sims | ||
376 | if (ThreadPool == null) | ||
377 | { | ||
378 | STPStartInfo startInfo = new STPStartInfo(); | ||
379 | startInfo.IdleTimeout = 20000; | ||
380 | startInfo.MaxWorkerThreads = maxThreads; | ||
381 | startInfo.MinWorkerThreads = 1; | ||
382 | startInfo.ThreadPriority = ThreadPriority.BelowNormal; | ||
383 | startInfo.StartSuspended = true; | ||
384 | startInfo.ThreadPoolName = "ScriptsHttpReq"; | ||
385 | |||
386 | ThreadPool = new SmartThreadPool(startInfo); | ||
387 | ThreadPool.Start(); | ||
388 | } | ||
370 | } | 389 | } |
371 | 390 | ||
372 | public void AddRegion(Scene scene) | 391 | public void AddRegion(Scene scene) |
@@ -410,8 +429,6 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest | |||
410 | 429 | ||
411 | public class HttpRequestClass : IServiceRequest | 430 | public class HttpRequestClass : IServiceRequest |
412 | { | 431 | { |
413 | // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | ||
414 | |||
415 | // Constants for parameters | 432 | // Constants for parameters |
416 | // public const int HTTP_BODY_MAXLENGTH = 2; | 433 | // public const int HTTP_BODY_MAXLENGTH = 2; |
417 | // public const int HTTP_METHOD = 0; | 434 | // public const int HTTP_METHOD = 0; |
@@ -438,6 +455,8 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest | |||
438 | public string HttpMIMEType = "text/plain;charset=utf-8"; | 455 | public string HttpMIMEType = "text/plain;charset=utf-8"; |
439 | public int HttpTimeout; | 456 | public int HttpTimeout; |
440 | public bool HttpVerifyCert = true; | 457 | public bool HttpVerifyCert = true; |
458 | public IWorkItemResult WorkItem = null; | ||
459 | |||
441 | //public bool HttpVerboseThrottle = true; // not implemented | 460 | //public bool HttpVerboseThrottle = true; // not implemented |
442 | public List<string> HttpCustomHeaders = null; | 461 | public List<string> HttpCustomHeaders = null; |
443 | public bool HttpPragmaNoCache = true; | 462 | public bool HttpPragmaNoCache = true; |
@@ -485,15 +504,44 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest | |||
485 | 504 | ||
486 | public void Process() | 505 | public void Process() |
487 | { | 506 | { |
507 | _finished = false; | ||
508 | |||
509 | lock (HttpRequestModule.ThreadPool) | ||
510 | WorkItem = HttpRequestModule.ThreadPool.QueueWorkItem(new WorkItemCallback(StpSendWrapper), null); | ||
511 | } | ||
512 | |||
513 | private object StpSendWrapper(object o) | ||
514 | { | ||
488 | SendRequest(); | 515 | SendRequest(); |
516 | return null; | ||
489 | } | 517 | } |
490 | 518 | ||
519 | /* | ||
520 | * TODO: More work on the response codes. Right now | ||
521 | * returning 200 for success or 499 for exception | ||
522 | */ | ||
523 | |||
491 | public void SendRequest() | 524 | public void SendRequest() |
492 | { | 525 | { |
526 | HttpWebResponse response = null; | ||
527 | Stream resStream = null; | ||
528 | StringBuilder sb = new StringBuilder(); | ||
529 | byte[] buf = new byte[8192]; | ||
530 | string tempString = null; | ||
531 | int count = 0; | ||
532 | |||
493 | try | 533 | try |
494 | { | 534 | { |
535 | <<<<<<< HEAD | ||
495 | Request = (HttpWebRequest)WebRequest.Create(Url); | 536 | Request = (HttpWebRequest)WebRequest.Create(Url); |
496 | Request.AllowAutoRedirect = false; | 537 | Request.AllowAutoRedirect = false; |
538 | ======= | ||
539 | Request = (HttpWebRequest) WebRequest.Create(Url); | ||
540 | |||
541 | //This works around some buggy HTTP Servers like Lighttpd | ||
542 | Request.ServicePoint.Expect100Continue = false; | ||
543 | |||
544 | >>>>>>> avn/ubitvar | ||
497 | Request.Method = HttpMethod; | 545 | Request.Method = HttpMethod; |
498 | Request.ContentType = HttpMIMEType; | 546 | Request.ContentType = HttpMIMEType; |
499 | 547 | ||
@@ -501,7 +549,6 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest | |||
501 | { | 549 | { |
502 | // We could hijack Connection Group Name to identify | 550 | // We could hijack Connection Group Name to identify |
503 | // a desired security exception. But at the moment we'll use a dummy header instead. | 551 | // a desired security exception. But at the moment we'll use a dummy header instead. |
504 | // Request.ConnectionGroupName = "NoVerify"; | ||
505 | Request.Headers.Add("NoVerifyCert", "true"); | 552 | Request.Headers.Add("NoVerifyCert", "true"); |
506 | } | 553 | } |
507 | // else | 554 | // else |
@@ -534,14 +581,11 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest | |||
534 | } | 581 | } |
535 | } | 582 | } |
536 | 583 | ||
537 | if (ResponseHeaders != null) | 584 | foreach (KeyValuePair<string, string> entry in ResponseHeaders) |
538 | { | 585 | if (entry.Key.ToLower().Equals("user-agent")) |
539 | foreach (KeyValuePair<string, string> entry in ResponseHeaders) | 586 | Request.UserAgent = entry.Value; |
540 | if (entry.Key.ToLower().Equals("user-agent") && Request is HttpWebRequest) | 587 | else |
541 | ((HttpWebRequest)Request).UserAgent = entry.Value; | 588 | Request.Headers[entry.Key] = entry.Value; |
542 | else | ||
543 | Request.Headers[entry.Key] = entry.Value; | ||
544 | } | ||
545 | 589 | ||
546 | // Encode outbound data | 590 | // Encode outbound data |
547 | if (!string.IsNullOrEmpty(OutboundBody)) | 591 | if (!string.IsNullOrEmpty(OutboundBody)) |
@@ -553,12 +597,11 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest | |||
553 | bstream.Write(data, 0, data.Length); | 597 | bstream.Write(data, 0, data.Length); |
554 | } | 598 | } |
555 | 599 | ||
600 | Request.Timeout = HttpTimeout; | ||
556 | try | 601 | try |
557 | { | 602 | { |
558 | IAsyncResult result = (IAsyncResult)Request.BeginGetResponse(ResponseCallback, null); | 603 | // execute the request |
559 | 604 | response = (HttpWebResponse) Request.GetResponse(); | |
560 | ThreadPool.RegisterWaitForSingleObject( | ||
561 | result.AsyncWaitHandle, new WaitOrTimerCallback(TimeoutCallback), null, HttpTimeout, true); | ||
562 | } | 605 | } |
563 | catch (WebException e) | 606 | catch (WebException e) |
564 | { | 607 | { |
@@ -566,65 +609,74 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest | |||
566 | { | 609 | { |
567 | throw; | 610 | throw; |
568 | } | 611 | } |
612 | response = (HttpWebResponse)e.Response; | ||
613 | } | ||
569 | 614 | ||
570 | HttpWebResponse response = (HttpWebResponse)e.Response; | 615 | Status = (int)response.StatusCode; |
571 | 616 | ||
572 | Status = (int)response.StatusCode; | 617 | resStream = response.GetResponseStream(); |
573 | ResponseBody = response.StatusDescription; | ||
574 | _finished = true; | ||
575 | } | ||
576 | } | ||
577 | catch (Exception e) | ||
578 | { | ||
579 | // m_log.Debug( | ||
580 | // string.Format("[SCRIPTS HTTP REQUESTS]: Exception on request to {0} for {1} ", Url, ItemID), e); | ||
581 | 618 | ||
582 | Status = (int)OSHttpStatusCode.ClientErrorJoker; | 619 | do |
583 | ResponseBody = e.Message; | 620 | { |
584 | _finished = true; | 621 | // fill the buffer with data |
585 | } | 622 | count = resStream.Read(buf, 0, buf.Length); |
586 | } | ||
587 | 623 | ||
588 | private void ResponseCallback(IAsyncResult ar) | 624 | // make sure we read some data |
589 | { | 625 | if (count != 0) |
590 | HttpWebResponse response = null; | 626 | { |
627 | // translate from bytes to ASCII text | ||
628 | tempString = Util.UTF8.GetString(buf, 0, count); | ||
591 | 629 | ||
592 | try | 630 | // continue building the string |
631 | sb.Append(tempString); | ||
632 | if (sb.Length > 2048) | ||
633 | break; | ||
634 | } | ||
635 | } while (count > 0); // any more data to read? | ||
636 | |||
637 | ResponseBody = sb.ToString().Replace("\r", ""); | ||
638 | } | ||
639 | catch (WebException e) | ||
593 | { | 640 | { |
594 | try | 641 | if (e.Status == WebExceptionStatus.ProtocolError) |
595 | { | ||
596 | response = (HttpWebResponse)Request.EndGetResponse(ar); | ||
597 | } | ||
598 | catch (WebException e) | ||
599 | { | 642 | { |
600 | if (e.Status != WebExceptionStatus.ProtocolError) | 643 | HttpWebResponse webRsp = (HttpWebResponse)((WebException)e).Response; |
644 | Status = (int)webRsp.StatusCode; | ||
645 | try | ||
601 | { | 646 | { |
602 | throw; | 647 | using (Stream responseStream = webRsp.GetResponseStream()) |
648 | { | ||
649 | ResponseBody = responseStream.GetStreamString(); | ||
650 | } | ||
603 | } | 651 | } |
604 | 652 | catch | |
605 | response = (HttpWebResponse)e.Response; | 653 | { |
654 | ResponseBody = webRsp.StatusDescription; | ||
655 | } | ||
656 | } | ||
657 | else | ||
658 | { | ||
659 | Status = (int)OSHttpStatusCode.ClientErrorJoker; | ||
660 | ResponseBody = e.Message; | ||
606 | } | 661 | } |
607 | 662 | ||
608 | Status = (int)response.StatusCode; | 663 | if (ResponseBody == null) |
664 | ResponseBody = String.Empty; | ||
609 | 665 | ||
610 | using (Stream stream = response.GetResponseStream()) | 666 | _finished = true; |
611 | { | 667 | return; |
612 | StreamReader reader = new StreamReader(stream, Encoding.UTF8); | ||
613 | ResponseBody = reader.ReadToEnd(); | ||
614 | } | ||
615 | } | 668 | } |
616 | catch (Exception e) | 669 | catch (Exception e) |
617 | { | 670 | { |
618 | Status = (int)OSHttpStatusCode.ClientErrorJoker; | 671 | // Don't crash on anything else |
619 | ResponseBody = e.Message; | ||
620 | |||
621 | // m_log.Debug( | ||
622 | // string.Format("[SCRIPTS HTTP REQUESTS]: Exception on response to {0} for {1} ", Url, ItemID), e); | ||
623 | } | 672 | } |
624 | finally | 673 | finally |
625 | { | 674 | { |
675 | if (resStream != null) | ||
676 | resStream.Close(); | ||
626 | if (response != null) | 677 | if (response != null) |
627 | response.Close(); | 678 | response.Close(); |
679 | <<<<<<< HEAD | ||
628 | 680 | ||
629 | // We need to resubmit | 681 | // We need to resubmit |
630 | if ( | 682 | if ( |
@@ -672,21 +724,28 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest | |||
672 | { | 724 | { |
673 | _finished = true; | 725 | _finished = true; |
674 | } | 726 | } |
727 | ======= | ||
728 | >>>>>>> avn/ubitvar | ||
675 | } | 729 | } |
676 | } | ||
677 | 730 | ||
678 | private void TimeoutCallback(object state, bool timedOut) | 731 | if (ResponseBody == null) |
679 | { | 732 | ResponseBody = String.Empty; |
680 | if (timedOut) | 733 | |
681 | Request.Abort(); | 734 | _finished = true; |
682 | } | 735 | } |
683 | 736 | ||
684 | public void Stop() | 737 | public void Stop() |
685 | { | 738 | { |
686 | // m_log.DebugFormat("[SCRIPTS HTTP REQUESTS]: Stopping request to {0} for {1} ", Url, ItemID); | 739 | try |
687 | 740 | { | |
688 | if (Request != null) | 741 | if (!WorkItem.Cancel()) |
689 | Request.Abort(); | 742 | { |
743 | WorkItem.Cancel(true); | ||
744 | } | ||
745 | } | ||
746 | catch (Exception) | ||
747 | { | ||
748 | } | ||
690 | } | 749 | } |
691 | } | 750 | } |
692 | } \ No newline at end of file | 751 | } |