aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim
diff options
context:
space:
mode:
authorUbitUmarov2019-02-24 07:25:50 +0000
committerUbitUmarov2019-02-24 07:25:50 +0000
commit800f6d6529516be22d4ee79cd8e9161479f4df34 (patch)
treea489698150d5f0f80731fa9a29f50e14b9945965 /OpenSim
parentupdate script sintaxe (diff)
downloadopensim-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')
-rw-r--r--OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs165
-rw-r--r--OpenSim/Region/Framework/Interfaces/IHttpRequests.cs1
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs19
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/HttpRequest.cs13
4 files changed, 117 insertions, 81 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
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Collections.Concurrent;
30using System.IO; 31using System.IO;
31using System.Net; 32using System.Net;
32using System.Net.Mail; 33using 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 {
diff --git a/OpenSim/Region/Framework/Interfaces/IHttpRequests.cs b/OpenSim/Region/Framework/Interfaces/IHttpRequests.cs
index 978c248..3ab1f6c 100644
--- a/OpenSim/Region/Framework/Interfaces/IHttpRequests.cs
+++ b/OpenSim/Region/Framework/Interfaces/IHttpRequests.cs
@@ -87,5 +87,6 @@ namespace OpenSim.Region.Framework.Interfaces
87 void StopHttpRequest(uint m_localID, UUID m_itemID); 87 void StopHttpRequest(uint m_localID, UUID m_itemID);
88 IServiceRequest GetNextCompletedRequest(); 88 IServiceRequest GetNextCompletedRequest();
89 void RemoveCompletedRequest(UUID id); 89 void RemoveCompletedRequest(UUID id);
90 bool CheckThrottle(uint localID);
90 } 91 }
91} 92}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
index 943141c..6cea821 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
@@ -13945,14 +13945,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
13945 13945
13946 public LSL_Key llHTTPRequest(string url, LSL_List parameters, string body) 13946 public LSL_Key llHTTPRequest(string url, LSL_List parameters, string body)
13947 { 13947 {
13948 // Partial implementation: support for parameter flags needed
13949 // see http://wiki.secondlife.com/wiki/LlHTTPRequest
13950 // parameter flags support are implemented in ScriptsHttpRequests.cs
13951 // in StartHttpRequest
13952
13953 m_host.AddScriptLPS(1); 13948 m_host.AddScriptLPS(1);
13954 IHttpRequestModule httpScriptMod = 13949 IHttpRequestModule httpScriptMod = m_ScriptEngine.World.RequestModuleInterface<IHttpRequestModule>();
13955 m_ScriptEngine.World.RequestModuleInterface<IHttpRequestModule>(); 13950 if(httpScriptMod == null)
13951 return "";
13952
13953 if(!httpScriptMod.CheckThrottle(m_host.LocalId))
13954 return UUID.Zero.ToString();
13955
13956 List<string> param = new List<string>(); 13956 List<string> param = new List<string>();
13957 bool ok; 13957 bool ok;
13958 Int32 flag; 13958 Int32 flag;
@@ -14123,8 +14123,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
14123 } 14123 }
14124 14124
14125 HttpInitialRequestStatus status; 14125 HttpInitialRequestStatus status;
14126 UUID reqID 14126 UUID reqID = httpScriptMod.StartHttpRequest(m_host.LocalId, m_item.ItemID, url, param, httpHeaders, body, out status);
14127 = httpScriptMod.StartHttpRequest(m_host.LocalId, m_item.ItemID, url, param, httpHeaders, body, out status);
14128 14127
14129 if (status == HttpInitialRequestStatus.DISALLOWED_BY_FILTER) 14128 if (status == HttpInitialRequestStatus.DISALLOWED_BY_FILTER)
14130 Error("llHttpRequest", string.Format("Request to {0} disallowed by filter", url)); 14129 Error("llHttpRequest", string.Format("Request to {0} disallowed by filter", url));
@@ -14132,7 +14131,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
14132 if (reqID != UUID.Zero) 14131 if (reqID != UUID.Zero)
14133 return reqID.ToString(); 14132 return reqID.ToString();
14134 else 14133 else
14135 return null; 14134 return "";
14136 } 14135 }
14137 14136
14138 14137
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/HttpRequest.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/HttpRequest.cs
index 629b14b..166f2d9 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/HttpRequest.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/HttpRequest.cs
@@ -48,14 +48,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
48 if (m_CmdManager.m_ScriptEngine.World == null) 48 if (m_CmdManager.m_ScriptEngine.World == null)
49 return; 49 return;
50 50
51 IHttpRequestModule iHttpReq = 51 IHttpRequestModule iHttpReq = m_CmdManager.m_ScriptEngine.World.RequestModuleInterface<IHttpRequestModule>();
52 m_CmdManager.m_ScriptEngine.World.RequestModuleInterface<IHttpRequestModule>(); 52 if(iHttpReq == null)
53 53 return;
54 HttpRequestClass httpInfo = null;
55
56 if (iHttpReq != null)
57 httpInfo = (HttpRequestClass)iHttpReq.GetNextCompletedRequest();
58 54
55 HttpRequestClass httpInfo = (HttpRequestClass)iHttpReq.GetNextCompletedRequest();
59 while (httpInfo != null) 56 while (httpInfo != null)
60 { 57 {
61 //m_log.Debug("[AsyncLSL]:" + httpInfo.response_body + httpInfo.status); 58 //m_log.Debug("[AsyncLSL]:" + httpInfo.response_body + httpInfo.status);
@@ -67,8 +64,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
67 // implemented here yet anyway. Should be fixed if/when maxsize 64 // implemented here yet anyway. Should be fixed if/when maxsize
68 // is supported 65 // is supported
69 66
70 iHttpReq.RemoveCompletedRequest(httpInfo.ReqID);
71
72 object[] resobj = new object[] 67 object[] resobj = new object[]
73 { 68 {
74 new LSL_Types.LSLString(httpInfo.ReqID.ToString()), 69 new LSL_Types.LSLString(httpInfo.ReqID.ToString()),