aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs')
-rw-r--r--OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs227
1 files changed, 136 insertions, 91 deletions
diff --git a/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs b/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs
index c3a8afd..5541063 100644
--- a/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs
+++ b/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs
@@ -28,15 +28,12 @@
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.IO; 30using System.IO;
31using System.Linq;
32using System.Net; 31using System.Net;
33using System.Net.Mail; 32using System.Net.Mail;
34using System.Net.Security; 33using System.Net.Security;
35using System.Reflection;
36using System.Text; 34using System.Text;
37using System.Threading; 35using System.Threading;
38using System.Security.Cryptography.X509Certificates; 36using System.Security.Cryptography.X509Certificates;
39using log4net;
40using Nini.Config; 37using Nini.Config;
41using OpenMetaverse; 38using OpenMetaverse;
42using OpenSim.Framework; 39using OpenSim.Framework;
@@ -45,6 +42,7 @@ using OpenSim.Framework.Servers.HttpServer;
45using OpenSim.Region.Framework.Interfaces; 42using OpenSim.Region.Framework.Interfaces;
46using OpenSim.Region.Framework.Scenes; 43using OpenSim.Region.Framework.Scenes;
47using Mono.Addins; 44using Mono.Addins;
45using 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,14 +513,11 @@ 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 (!string.IsNullOrEmpty(OutboundBody)) 523 if (!string.IsNullOrEmpty(OutboundBody))
@@ -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}