diff options
author | UbitUmarov | 2019-02-24 07:25:50 +0000 |
---|---|---|
committer | UbitUmarov | 2019-02-24 07:25:50 +0000 |
commit | 800f6d6529516be22d4ee79cd8e9161479f4df34 (patch) | |
tree | a489698150d5f0f80731fa9a29f50e14b9945965 /OpenSim/Region/CoreModules | |
parent | update script sintaxe (diff) | |
download | opensim-SC-800f6d6529516be22d4ee79cd8e9161479f4df34.zip opensim-SC-800f6d6529516be22d4ee79cd8e9161479f4df34.tar.gz opensim-SC-800f6d6529516be22d4ee79cd8e9161479f4df34.tar.bz2 opensim-SC-800f6d6529516be22d4ee79cd8e9161479f4df34.tar.xz |
several changes to llHttpRequest processing: options section renamed ScriptsHttpRequestModule; throttle by prim (PrimRequestsBurst = 3, PrimRequestsPerSec = 1) and max concurrent connections per instance (MaxPoolThreads = 5), llhttprequest returns if error, nullkey if throttled, reqid otherwise
Diffstat (limited to 'OpenSim/Region/CoreModules')
-rw-r--r-- | OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs | 165 |
1 files changed, 103 insertions, 62 deletions
diff --git a/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs b/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs index c3f6d6b..54936a3 100644 --- a/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs +++ b/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs | |||
@@ -27,6 +27,7 @@ | |||
27 | 27 | ||
28 | using System; | 28 | using System; |
29 | using System.Collections.Generic; | 29 | using System.Collections.Generic; |
30 | using System.Collections.Concurrent; | ||
30 | using System.IO; | 31 | using System.IO; |
31 | using System.Net; | 32 | using System.Net; |
32 | using System.Net.Mail; | 33 | using System.Net.Mail; |
@@ -101,11 +102,22 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest | |||
101 | private OutboundUrlFilter m_outboundUrlFilter; | 102 | private OutboundUrlFilter m_outboundUrlFilter; |
102 | private string m_proxyurl = ""; | 103 | private string m_proxyurl = ""; |
103 | private string m_proxyexcepts = ""; | 104 | private string m_proxyexcepts = ""; |
105 | |||
106 | private float m_primpersec = 1.0f; | ||
107 | private float m_primburst = 3f; | ||
108 | |||
109 | private struct ThrottleData | ||
110 | { | ||
111 | public double lastTime; | ||
112 | public float count; | ||
113 | } | ||
104 | 114 | ||
105 | // <request id, HttpRequestClass> | 115 | // <request id, HttpRequestClass> |
106 | private Dictionary<UUID, HttpRequestClass> m_pendingRequests; | 116 | private Dictionary<UUID, HttpRequestClass> m_pendingRequests; |
117 | private ConcurrentQueue<HttpRequestClass> m_CompletedRequests; | ||
118 | private ConcurrentDictionary<uint, ThrottleData> m_RequestsThrottle; | ||
119 | |||
107 | private Scene m_scene; | 120 | private Scene m_scene; |
108 | // private Queue<HttpRequestClass> rpcQueue = new Queue<HttpRequestClass>(); | ||
109 | public static SmartThreadPool ThreadPool = null; | 121 | public static SmartThreadPool ThreadPool = null; |
110 | 122 | ||
111 | public HttpRequestModule() | 123 | public HttpRequestModule() |
@@ -119,6 +131,41 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest | |||
119 | return UUID.Zero; | 131 | return UUID.Zero; |
120 | } | 132 | } |
121 | 133 | ||
134 | public bool CheckThrottle(uint localID) | ||
135 | { | ||
136 | ThrottleData th; | ||
137 | double now = Util.GetTimeStamp(); | ||
138 | bool ret = false; | ||
139 | |||
140 | if (m_RequestsThrottle.TryGetValue(localID, out th)) | ||
141 | { | ||
142 | double delta = now - th.lastTime; | ||
143 | th.lastTime = now; | ||
144 | |||
145 | float add = (float)(m_primpersec * delta); | ||
146 | th.count += add; | ||
147 | if (th.count > m_primburst) | ||
148 | th.count = m_primburst; | ||
149 | |||
150 | ret = th.count > 0; | ||
151 | } | ||
152 | else | ||
153 | { | ||
154 | th = new ThrottleData() | ||
155 | { | ||
156 | lastTime = now, | ||
157 | count = m_primburst | ||
158 | }; | ||
159 | ret = true; | ||
160 | } | ||
161 | |||
162 | if (ret) | ||
163 | th.count--; | ||
164 | |||
165 | m_RequestsThrottle[localID] = th; | ||
166 | return ret; | ||
167 | } | ||
168 | |||
122 | public UUID StartHttpRequest( | 169 | public UUID StartHttpRequest( |
123 | uint localID, UUID itemID, string url, List<string> parameters, Dictionary<string, string> headers, string body, | 170 | uint localID, UUID itemID, string url, List<string> parameters, Dictionary<string, string> headers, string body, |
124 | out HttpInitialRequestStatus status) | 171 | out HttpInitialRequestStatus status) |
@@ -243,9 +290,7 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest | |||
243 | return false; | 290 | return false; |
244 | 291 | ||
245 | lock (HttpListLock) | 292 | lock (HttpListLock) |
246 | { | ||
247 | m_pendingRequests.Add(req.ReqID, req); | 293 | m_pendingRequests.Add(req.ReqID, req); |
248 | } | ||
249 | 294 | ||
250 | req.Process(); | 295 | req.Process(); |
251 | 296 | ||
@@ -256,14 +301,19 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest | |||
256 | { | 301 | { |
257 | if (m_pendingRequests != null) | 302 | if (m_pendingRequests != null) |
258 | { | 303 | { |
304 | List<UUID> toremove = new List<UUID>(); | ||
259 | lock (HttpListLock) | 305 | lock (HttpListLock) |
260 | { | 306 | { |
261 | HttpRequestClass tmpReq; | 307 | foreach (HttpRequestClass tmpReq in m_pendingRequests.Values) |
262 | if (m_pendingRequests.TryGetValue(m_itemID, out tmpReq)) | ||
263 | { | 308 | { |
264 | tmpReq.Stop(); | 309 | if(tmpReq.ItemID == m_itemID) |
265 | m_pendingRequests.Remove(m_itemID); | 310 | { |
311 | tmpReq.Stop(); | ||
312 | toremove.Add(tmpReq.ReqID); | ||
313 | } | ||
266 | } | 314 | } |
315 | foreach(UUID id in toremove) | ||
316 | m_pendingRequests.Remove(id); | ||
267 | } | 317 | } |
268 | } | 318 | } |
269 | } | 319 | } |
@@ -276,37 +326,37 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest | |||
276 | * finished. I thought about setting up a queue for this, but | 326 | * finished. I thought about setting up a queue for this, but |
277 | * it will need some refactoring and this works 'enough' right now | 327 | * it will need some refactoring and this works 'enough' right now |
278 | */ | 328 | */ |
279 | 329 | public void GotCompletedRequest(HttpRequestClass req) | |
280 | public IServiceRequest GetNextCompletedRequest() | ||
281 | { | 330 | { |
331 | if(req.Removed) | ||
332 | return; | ||
282 | lock (HttpListLock) | 333 | lock (HttpListLock) |
283 | { | 334 | { |
284 | foreach (UUID luid in m_pendingRequests.Keys) | 335 | m_pendingRequests.Remove(req.ReqID); |
285 | { | 336 | m_CompletedRequests.Enqueue(req); |
286 | HttpRequestClass tmpReq; | 337 | } |
338 | } | ||
287 | 339 | ||
288 | if (m_pendingRequests.TryGetValue(luid, out tmpReq)) | 340 | public IServiceRequest GetNextCompletedRequest() |
289 | { | 341 | { |
290 | if (tmpReq.Finished) | 342 | HttpRequestClass req; |
291 | { | 343 | while(m_CompletedRequests.TryDequeue(out req)) |
292 | return tmpReq; | 344 | { |
293 | } | 345 | if(!req.Removed) |
294 | } | 346 | return req; |
295 | } | ||
296 | } | 347 | } |
297 | return null; | 348 | return null; |
298 | } | 349 | } |
299 | 350 | ||
300 | public void RemoveCompletedRequest(UUID id) | 351 | public void RemoveCompletedRequest(UUID reqId) |
301 | { | 352 | { |
302 | lock (HttpListLock) | 353 | lock (HttpListLock) |
303 | { | 354 | { |
304 | HttpRequestClass tmpReq; | 355 | HttpRequestClass tmpReq; |
305 | if (m_pendingRequests.TryGetValue(id, out tmpReq)) | 356 | if (m_pendingRequests.TryGetValue(reqId, out tmpReq)) |
306 | { | 357 | { |
307 | tmpReq.Stop(); | 358 | tmpReq.Stop(); |
308 | tmpReq = null; | 359 | m_pendingRequests.Remove(reqId); |
309 | m_pendingRequests.Remove(id); | ||
310 | } | 360 | } |
311 | } | 361 | } |
312 | } | 362 | } |
@@ -322,17 +372,20 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest | |||
322 | 372 | ||
323 | HttpRequestClass.HttpBodyMaxLenMAX = config.Configs["Network"].GetInt("HttpBodyMaxLenMAX", 16384); | 373 | HttpRequestClass.HttpBodyMaxLenMAX = config.Configs["Network"].GetInt("HttpBodyMaxLenMAX", 16384); |
324 | 374 | ||
325 | |||
326 | m_outboundUrlFilter = new OutboundUrlFilter("Script HTTP request module", config); | 375 | m_outboundUrlFilter = new OutboundUrlFilter("Script HTTP request module", config); |
327 | int maxThreads = 15; | ||
328 | 376 | ||
329 | IConfig httpConfig = config.Configs["HttpRequestModule"]; | 377 | int maxThreads = 5; |
378 | IConfig httpConfig = config.Configs["ScriptsHttpRequestModule"]; | ||
330 | if (httpConfig != null) | 379 | if (httpConfig != null) |
331 | { | 380 | { |
332 | maxThreads = httpConfig.GetInt("MaxPoolThreads", maxThreads); | 381 | maxThreads = httpConfig.GetInt("MaxPoolThreads", maxThreads); |
382 | m_primburst = httpConfig.GetFloat("PrimRequestsBurst", m_primburst); | ||
383 | m_primpersec = httpConfig.GetFloat("PrimRequestsPerSec", m_primpersec); | ||
333 | } | 384 | } |
334 | 385 | ||
335 | m_pendingRequests = new Dictionary<UUID, HttpRequestClass>(); | 386 | m_pendingRequests = new Dictionary<UUID, HttpRequestClass>(); |
387 | m_CompletedRequests = new ConcurrentQueue<HttpRequestClass>(); | ||
388 | m_RequestsThrottle = new ConcurrentDictionary<uint, ThrottleData>(); | ||
336 | 389 | ||
337 | // First instance sets this up for all sims | 390 | // First instance sets this up for all sims |
338 | if (ThreadPool == null) | 391 | if (ThreadPool == null) |
@@ -406,11 +459,8 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest | |||
406 | /// </summary> | 459 | /// </summary> |
407 | public HttpRequestModule RequestModule { get; set; } | 460 | public HttpRequestModule RequestModule { get; set; } |
408 | 461 | ||
409 | private bool _finished; | 462 | public bool Finished { get; private set;} |
410 | public bool Finished | 463 | public bool Removed{ get; set;} |
411 | { | ||
412 | get { return _finished; } | ||
413 | } | ||
414 | 464 | ||
415 | public static int HttpBodyMaxLenMAX = 16384; | 465 | public static int HttpBodyMaxLenMAX = 16384; |
416 | 466 | ||
@@ -427,19 +477,10 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest | |||
427 | public bool HttpPragmaNoCache = true; | 477 | public bool HttpPragmaNoCache = true; |
428 | 478 | ||
429 | // Request info | 479 | // Request info |
430 | private UUID _itemID; | 480 | public UUID ReqID { get; set; } |
431 | public UUID ItemID | 481 | public UUID ItemID { get; set;} |
432 | { | 482 | public uint LocalID { get; set;} |
433 | get { return _itemID; } | 483 | |
434 | set { _itemID = value; } | ||
435 | } | ||
436 | private uint _localID; | ||
437 | public uint LocalID | ||
438 | { | ||
439 | get { return _localID; } | ||
440 | set { _localID = value; } | ||
441 | } | ||
442 | public DateTime Next; | ||
443 | public string proxyurl; | 484 | public string proxyurl; |
444 | public string proxyexcepts; | 485 | public string proxyexcepts; |
445 | 486 | ||
@@ -454,12 +495,7 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest | |||
454 | public int MaxRedirects { get; set; } | 495 | public int MaxRedirects { get; set; } |
455 | 496 | ||
456 | public string OutboundBody; | 497 | public string OutboundBody; |
457 | private UUID _reqID; | 498 | |
458 | public UUID ReqID | ||
459 | { | ||
460 | get { return _reqID; } | ||
461 | set { _reqID = value; } | ||
462 | } | ||
463 | public HttpWebRequest Request; | 499 | public HttpWebRequest Request; |
464 | public string ResponseBody; | 500 | public string ResponseBody; |
465 | public List<string> ResponseMetadata; | 501 | public List<string> ResponseMetadata; |
@@ -469,10 +505,7 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest | |||
469 | 505 | ||
470 | public void Process() | 506 | public void Process() |
471 | { | 507 | { |
472 | _finished = false; | 508 | WorkItem = HttpRequestModule.ThreadPool.QueueWorkItem(new WorkItemCallback(StpSendWrapper), null); |
473 | |||
474 | lock (HttpRequestModule.ThreadPool) | ||
475 | WorkItem = HttpRequestModule.ThreadPool.QueueWorkItem(new WorkItemCallback(StpSendWrapper), null); | ||
476 | } | 509 | } |
477 | 510 | ||
478 | private object StpSendWrapper(object o) | 511 | private object StpSendWrapper(object o) |
@@ -521,6 +554,9 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest | |||
521 | 554 | ||
522 | public void SendRequest() | 555 | public void SendRequest() |
523 | { | 556 | { |
557 | if(Removed) | ||
558 | return; | ||
559 | |||
524 | HttpWebResponse response = null; | 560 | HttpWebResponse response = null; |
525 | Stream resStream = null; | 561 | Stream resStream = null; |
526 | byte[] buf = new byte[HttpBodyMaxLenMAX + 16]; | 562 | byte[] buf = new byte[HttpBodyMaxLenMAX + 16]; |
@@ -672,7 +708,6 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest | |||
672 | if (response != null) | 708 | if (response != null) |
673 | response.Close(); | 709 | response.Close(); |
674 | 710 | ||
675 | |||
676 | // We need to resubmit | 711 | // We need to resubmit |
677 | if ( | 712 | if ( |
678 | (Status == (int)HttpStatusCode.MovedPermanently | 713 | (Status == (int)HttpStatusCode.MovedPermanently |
@@ -684,7 +719,8 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest | |||
684 | { | 719 | { |
685 | Status = (int)OSHttpStatusCode.ClientErrorJoker; | 720 | Status = (int)OSHttpStatusCode.ClientErrorJoker; |
686 | ResponseBody = "Number of redirects exceeded max redirects"; | 721 | ResponseBody = "Number of redirects exceeded max redirects"; |
687 | _finished = true; | 722 | WorkItem = null; |
723 | RequestModule.GotCompletedRequest(this); | ||
688 | } | 724 | } |
689 | else | 725 | else |
690 | { | 726 | { |
@@ -694,13 +730,15 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest | |||
694 | { | 730 | { |
695 | Status = (int)OSHttpStatusCode.ClientErrorJoker; | 731 | Status = (int)OSHttpStatusCode.ClientErrorJoker; |
696 | ResponseBody = "HTTP redirect code but no location header"; | 732 | ResponseBody = "HTTP redirect code but no location header"; |
697 | _finished = true; | 733 | WorkItem = null; |
734 | RequestModule.GotCompletedRequest(this); | ||
698 | } | 735 | } |
699 | else if (!RequestModule.CheckAllowed(new Uri(location))) | 736 | else if (!RequestModule.CheckAllowed(new Uri(location))) |
700 | { | 737 | { |
701 | Status = (int)OSHttpStatusCode.ClientErrorJoker; | 738 | Status = (int)OSHttpStatusCode.ClientErrorJoker; |
702 | ResponseBody = "URL from HTTP redirect blocked: " + location; | 739 | ResponseBody = "URL from HTTP redirect blocked: " + location; |
703 | _finished = true; | 740 | WorkItem = null; |
741 | RequestModule.GotCompletedRequest(this); | ||
704 | } | 742 | } |
705 | else | 743 | else |
706 | { | 744 | { |
@@ -717,9 +755,10 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest | |||
717 | } | 755 | } |
718 | else | 756 | else |
719 | { | 757 | { |
720 | _finished = true; | 758 | WorkItem = null; |
721 | if (ResponseBody == null) | 759 | if (ResponseBody == null) |
722 | ResponseBody = String.Empty; | 760 | ResponseBody = String.Empty; |
761 | RequestModule.GotCompletedRequest(this); | ||
723 | } | 762 | } |
724 | } | 763 | } |
725 | } | 764 | } |
@@ -728,10 +767,12 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest | |||
728 | { | 767 | { |
729 | try | 768 | try |
730 | { | 769 | { |
770 | Removed = true; | ||
771 | if(WorkItem == null) | ||
772 | return; | ||
773 | |||
731 | if (!WorkItem.Cancel()) | 774 | if (!WorkItem.Cancel()) |
732 | { | ||
733 | WorkItem.Cancel(true); | 775 | WorkItem.Cancel(true); |
734 | } | ||
735 | } | 776 | } |
736 | catch (Exception) | 777 | catch (Exception) |
737 | { | 778 | { |