diff options
Diffstat (limited to 'OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs')
-rw-r--r-- | OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs | 180 |
1 files changed, 111 insertions, 69 deletions
diff --git a/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs b/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs index 6793fc8..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; |
@@ -428,7 +445,16 @@ 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 | ||
434 | /* | 460 | /* |
@@ -439,10 +465,18 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest | |||
439 | public void SendRequest() | 465 | public void SendRequest() |
440 | { | 466 | { |
441 | HttpWebResponse response = null; | 467 | HttpWebResponse response = null; |
468 | StringBuilder sb = new StringBuilder(); | ||
469 | byte[] buf = new byte[8192]; | ||
470 | string tempString = null; | ||
471 | int count = 0; | ||
442 | 472 | ||
443 | try | 473 | try |
444 | { | 474 | { |
445 | Request = (HttpWebRequest) 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 | |||
446 | Request.Method = HttpMethod; | 480 | Request.Method = HttpMethod; |
447 | Request.ContentType = HttpMIMEType; | 481 | Request.ContentType = HttpMIMEType; |
448 | 482 | ||
@@ -450,7 +484,6 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest | |||
450 | { | 484 | { |
451 | // We could hijack Connection Group Name to identify | 485 | // We could hijack Connection Group Name to identify |
452 | // 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. |
453 | // Request.ConnectionGroupName = "NoVerify"; | ||
454 | Request.Headers.Add("NoVerifyCert", "true"); | 487 | Request.Headers.Add("NoVerifyCert", "true"); |
455 | } | 488 | } |
456 | // else | 489 | // else |
@@ -497,12 +530,11 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest | |||
497 | bstream.Close(); | 530 | bstream.Close(); |
498 | } | 531 | } |
499 | 532 | ||
533 | Request.Timeout = HttpTimeout; | ||
500 | try | 534 | try |
501 | { | 535 | { |
502 | IAsyncResult result = (IAsyncResult)Request.BeginGetResponse(ResponseCallback, null); | 536 | // execute the request |
503 | 537 | response = (HttpWebResponse) Request.GetResponse(); | |
504 | ThreadPool.RegisterWaitForSingleObject( | ||
505 | result.AsyncWaitHandle, new WaitOrTimerCallback(TimeoutCallback), null, HttpTimeout, true); | ||
506 | } | 538 | } |
507 | catch (WebException e) | 539 | catch (WebException e) |
508 | { | 540 | { |
@@ -511,31 +543,11 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest | |||
511 | throw; | 543 | throw; |
512 | } | 544 | } |
513 | response = (HttpWebResponse)e.Response; | 545 | response = (HttpWebResponse)e.Response; |
514 | _finished = true; | ||
515 | } | 546 | } |
516 | } | ||
517 | catch (Exception e) | ||
518 | { | ||
519 | Status = (int)OSHttpStatusCode.ClientErrorJoker; | ||
520 | ResponseBody = e.Message; | ||
521 | _finished = true; | ||
522 | } | ||
523 | } | ||
524 | 547 | ||
525 | private void ResponseCallback(IAsyncResult ar) | ||
526 | { | ||
527 | HttpWebResponse response = null; | ||
528 | |||
529 | try | ||
530 | { | ||
531 | response = (HttpWebResponse)Request.EndGetResponse(ar); | ||
532 | Status = (int)response.StatusCode; | 548 | Status = (int)response.StatusCode; |
533 | 549 | ||
534 | Stream resStream = response.GetResponseStream(); | 550 | Stream resStream = response.GetResponseStream(); |
535 | StringBuilder sb = new StringBuilder(); | ||
536 | byte[] buf = new byte[8192]; | ||
537 | string tempString = null; | ||
538 | int count = 0; | ||
539 | 551 | ||
540 | do | 552 | do |
541 | { | 553 | { |
@@ -550,41 +562,71 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest | |||
550 | 562 | ||
551 | // continue building the string | 563 | // continue building the string |
552 | sb.Append(tempString); | 564 | sb.Append(tempString); |
565 | if (sb.Length > 2048) | ||
566 | break; | ||
553 | } | 567 | } |
554 | } | 568 | } while (count > 0); // any more data to read? |
555 | while (count > 0); // any more data to read? | ||
556 | 569 | ||
557 | ResponseBody = sb.ToString(); | 570 | ResponseBody = sb.ToString().Replace("\r", ""); |
558 | } | 571 | } |
559 | catch (Exception e) | 572 | catch (WebException e) |
560 | { | 573 | { |
561 | Status = (int)OSHttpStatusCode.ClientErrorJoker; | 574 | if (e.Status == WebExceptionStatus.ProtocolError) |
562 | ResponseBody = e.Message; | 575 | { |
576 | HttpWebResponse webRsp = (HttpWebResponse)((WebException)e).Response; | ||
577 | Status = (int)webRsp.StatusCode; | ||
578 | try | ||
579 | { | ||
580 | using (Stream responseStream = webRsp.GetResponseStream()) | ||
581 | { | ||
582 | ResponseBody = responseStream.GetStreamString(); | ||
583 | } | ||
584 | } | ||
585 | catch | ||
586 | { | ||
587 | ResponseBody = webRsp.StatusDescription; | ||
588 | } | ||
589 | } | ||
590 | else | ||
591 | { | ||
592 | Status = (int)OSHttpStatusCode.ClientErrorJoker; | ||
593 | ResponseBody = e.Message; | ||
594 | } | ||
563 | 595 | ||
564 | // m_log.Debug( | 596 | if (ResponseBody == null) |
565 | // string.Format("[SCRIPTS HTTP REQUESTS]: Exception on response to {0} for {1} ", Url, ItemID), e); | 597 | ResponseBody = String.Empty; |
598 | |||
599 | _finished = true; | ||
600 | return; | ||
601 | } | ||
602 | catch (Exception e) | ||
603 | { | ||
604 | // Don't crash on anything else | ||
566 | } | 605 | } |
567 | finally | 606 | finally |
568 | { | 607 | { |
569 | if (response != null) | 608 | if (response != null) |
570 | response.Close(); | 609 | response.Close(); |
571 | |||
572 | _finished = true; | ||
573 | } | 610 | } |
574 | } | ||
575 | 611 | ||
576 | private void TimeoutCallback(object state, bool timedOut) | 612 | if (ResponseBody == null) |
577 | { | 613 | ResponseBody = String.Empty; |
578 | if (timedOut) | 614 | |
579 | Request.Abort(); | 615 | _finished = true; |
580 | } | 616 | } |
581 | 617 | ||
582 | public void Stop() | 618 | public void Stop() |
583 | { | 619 | { |
584 | // m_log.DebugFormat("[SCRIPTS HTTP REQUESTS]: Stopping request to {0} for {1} ", Url, ItemID); | 620 | try |
585 | 621 | { | |
586 | if (Request != null) | 622 | if (!WorkItem.Cancel()) |
587 | Request.Abort(); | 623 | { |
624 | WorkItem.Cancel(true); | ||
625 | } | ||
626 | } | ||
627 | catch (Exception) | ||
628 | { | ||
629 | } | ||
588 | } | 630 | } |
589 | } | 631 | } |
590 | } | 632 | } |