aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs
diff options
context:
space:
mode:
authorDavid Walter Seikel2016-11-03 21:44:39 +1000
committerDavid Walter Seikel2016-11-03 21:44:39 +1000
commit134f86e8d5c414409631b25b8c6f0ee45fbd8631 (patch)
tree216b89d3fb89acfb81be1e440c25c41ab09fa96d /OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs
parentMore changing to production grid. Double oops. (diff)
downloadopensim-SC_OLD-134f86e8d5c414409631b25b8c6f0ee45fbd8631.zip
opensim-SC_OLD-134f86e8d5c414409631b25b8c6f0ee45fbd8631.tar.gz
opensim-SC_OLD-134f86e8d5c414409631b25b8c6f0ee45fbd8631.tar.bz2
opensim-SC_OLD-134f86e8d5c414409631b25b8c6f0ee45fbd8631.tar.xz
Initial update to OpenSim 0.8.2.1 source code.
Diffstat (limited to '')
-rw-r--r--OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs355
1 files changed, 268 insertions, 87 deletions
diff --git a/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs b/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs
index a676971..9dfeb96 100644
--- a/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs
+++ b/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs
@@ -28,12 +28,15 @@
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.IO; 30using System.IO;
31using System.Linq;
31using System.Net; 32using System.Net;
32using System.Net.Mail; 33using System.Net.Mail;
33using System.Net.Security; 34using System.Net.Security;
35using System.Reflection;
34using System.Text; 36using System.Text;
35using System.Threading; 37using System.Threading;
36using System.Security.Cryptography.X509Certificates; 38using System.Security.Cryptography.X509Certificates;
39using log4net;
37using Nini.Config; 40using Nini.Config;
38using OpenMetaverse; 41using OpenMetaverse;
39using OpenSim.Framework; 42using OpenSim.Framework;
@@ -91,10 +94,13 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
91 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "HttpRequestModule")] 94 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "HttpRequestModule")]
92 public class HttpRequestModule : ISharedRegionModule, IHttpRequestModule 95 public class HttpRequestModule : ISharedRegionModule, IHttpRequestModule
93 { 96 {
97// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
98
94 private object HttpListLock = new object(); 99 private object HttpListLock = new object();
95 private int httpTimeout = 30000; 100 private int httpTimeout = 30000;
96 private string m_name = "HttpScriptRequests"; 101 private string m_name = "HttpScriptRequests";
97 102
103 private OutboundUrlFilter m_outboundUrlFilter;
98 private string m_proxyurl = ""; 104 private string m_proxyurl = "";
99 private string m_proxyexcepts = ""; 105 private string m_proxyexcepts = "";
100 106
@@ -132,10 +138,12 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
132 return false; 138 return false;
133 139
134 // Check for policy and execute it if defined 140 // Check for policy and execute it if defined
141#pragma warning disable 0618
135 if (ServicePointManager.CertificatePolicy != null) 142 if (ServicePointManager.CertificatePolicy != null)
136 { 143 {
137 return ServicePointManager.CertificatePolicy.CheckValidationResult (sp, certificate, Request, 0); 144 return ServicePointManager.CertificatePolicy.CheckValidationResult (sp, certificate, Request, 0);
138 } 145 }
146#pragma warning restore 0618
139 147
140 return true; 148 return true;
141 } 149 }
@@ -153,7 +161,9 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
153 return UUID.Zero; 161 return UUID.Zero;
154 } 162 }
155 163
156 public UUID StartHttpRequest(uint localID, UUID itemID, string url, List<string> parameters, Dictionary<string, string> headers, string body) 164 public UUID StartHttpRequest(
165 uint localID, UUID itemID, string url, List<string> parameters, Dictionary<string, string> headers, string body,
166 out HttpInitialRequestStatus status)
157 { 167 {
158 UUID reqID = UUID.Random(); 168 UUID reqID = UUID.Random();
159 HttpRequestClass htc = new HttpRequestClass(); 169 HttpRequestClass htc = new HttpRequestClass();
@@ -187,10 +197,50 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
187 case (int)HttpRequestConstants.HTTP_VERIFY_CERT: 197 case (int)HttpRequestConstants.HTTP_VERIFY_CERT:
188 htc.HttpVerifyCert = (int.Parse(parms[i + 1]) != 0); 198 htc.HttpVerifyCert = (int.Parse(parms[i + 1]) != 0);
189 break; 199 break;
200
201 case (int)HttpRequestConstants.HTTP_VERBOSE_THROTTLE:
202
203 // TODO implement me
204 break;
205
206 case (int)HttpRequestConstants.HTTP_CUSTOM_HEADER:
207 //Parameters are in pairs and custom header takes
208 //arguments in pairs so adjust for header marker.
209 ++i;
210
211 //Maximum of 8 headers are allowed based on the
212 //Second Life documentation for llHTTPRequest.
213 for (int count = 1; count <= 8; ++count)
214 {
215 //Not enough parameters remaining for a header?
216 if (parms.Length - i < 2)
217 break;
218
219 //Have we reached the end of the list of headers?
220 //End is marked by a string with a single digit.
221 //We already know we have at least one parameter
222 //so it is safe to do this check at top of loop.
223 if (Char.IsDigit(parms[i][0]))
224 break;
225
226 if (htc.HttpCustomHeaders == null)
227 htc.HttpCustomHeaders = new List<string>();
228
229 htc.HttpCustomHeaders.Add(parms[i]);
230 htc.HttpCustomHeaders.Add(parms[i+1]);
231
232 i += 2;
233 }
234 break;
235
236 case (int)HttpRequestConstants.HTTP_PRAGMA_NO_CACHE:
237 htc.HttpPragmaNoCache = (int.Parse(parms[i + 1]) != 0);
238 break;
190 } 239 }
191 } 240 }
192 } 241 }
193 242
243 htc.RequestModule = this;
194 htc.LocalID = localID; 244 htc.LocalID = localID;
195 htc.ItemID = itemID; 245 htc.ItemID = itemID;
196 htc.Url = url; 246 htc.Url = url;
@@ -201,28 +251,68 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
201 htc.proxyurl = m_proxyurl; 251 htc.proxyurl = m_proxyurl;
202 htc.proxyexcepts = m_proxyexcepts; 252 htc.proxyexcepts = m_proxyexcepts;
203 253
254 // Same number as default HttpWebRequest.MaximumAutomaticRedirections
255 htc.MaxRedirects = 50;
256
257 if (StartHttpRequest(htc))
258 {
259 status = HttpInitialRequestStatus.OK;
260 return htc.ReqID;
261 }
262 else
263 {
264 status = HttpInitialRequestStatus.DISALLOWED_BY_FILTER;
265 return UUID.Zero;
266 }
267 }
268
269 /// <summary>
270 /// Would a caller to this module be allowed to make a request to the given URL?
271 /// </summary>
272 /// <returns></returns>
273 public bool CheckAllowed(Uri url)
274 {
275 return m_outboundUrlFilter.CheckAllowed(url);
276 }
277
278 public bool StartHttpRequest(HttpRequestClass req)
279 {
280 if (!CheckAllowed(new Uri(req.Url)))
281 return false;
282
204 lock (HttpListLock) 283 lock (HttpListLock)
205 { 284 {
206 m_pendingRequests.Add(reqID, htc); 285 m_pendingRequests.Add(req.ReqID, req);
207 } 286 }
208 287
209 htc.Process(); 288 req.Process();
210 289
211 return reqID; 290 return true;
212 } 291 }
213 292
214 public void StopHttpRequest(uint m_localID, UUID m_itemID) 293 public void StopHttpRequestsForScript(UUID id)
215 { 294 {
216 if (m_pendingRequests != null) 295 if (m_pendingRequests != null)
217 { 296 {
297 List<UUID> keysToRemove = null;
298
218 lock (HttpListLock) 299 lock (HttpListLock)
219 { 300 {
220 HttpRequestClass tmpReq; 301 foreach (HttpRequestClass req in m_pendingRequests.Values)
221 if (m_pendingRequests.TryGetValue(m_itemID, out tmpReq))
222 { 302 {
223 tmpReq.Stop(); 303 if (req.ItemID == id)
224 m_pendingRequests.Remove(m_itemID); 304 {
305 req.Stop();
306
307 if (keysToRemove == null)
308 keysToRemove = new List<UUID>();
309
310 keysToRemove.Add(req.ReqID);
311 }
225 } 312 }
313
314 if (keysToRemove != null)
315 keysToRemove.ForEach(keyToRemove => m_pendingRequests.Remove(keyToRemove));
226 } 316 }
227 } 317 }
228 } 318 }
@@ -240,19 +330,13 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
240 { 330 {
241 lock (HttpListLock) 331 lock (HttpListLock)
242 { 332 {
243 foreach (UUID luid in m_pendingRequests.Keys) 333 foreach (HttpRequestClass req in m_pendingRequests.Values)
244 { 334 {
245 HttpRequestClass tmpReq; 335 if (req.Finished)
246 336 return req;
247 if (m_pendingRequests.TryGetValue(luid, out tmpReq))
248 {
249 if (tmpReq.Finished)
250 {
251 return tmpReq;
252 }
253 }
254 } 337 }
255 } 338 }
339
256 return null; 340 return null;
257 } 341 }
258 342
@@ -279,6 +363,8 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
279 m_proxyurl = config.Configs["Startup"].GetString("HttpProxy"); 363 m_proxyurl = config.Configs["Startup"].GetString("HttpProxy");
280 m_proxyexcepts = config.Configs["Startup"].GetString("HttpProxyExceptions"); 364 m_proxyexcepts = config.Configs["Startup"].GetString("HttpProxyExceptions");
281 365
366 m_outboundUrlFilter = new OutboundUrlFilter("Script HTTP request module", config);
367
282 m_pendingRequests = new Dictionary<UUID, HttpRequestClass>(); 368 m_pendingRequests = new Dictionary<UUID, HttpRequestClass>();
283 } 369 }
284 370
@@ -321,16 +407,27 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
321 #endregion 407 #endregion
322 } 408 }
323 409
324 public class HttpRequestClass: IServiceRequest 410 public class HttpRequestClass : IServiceRequest
325 { 411 {
412// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
413
326 // Constants for parameters 414 // Constants for parameters
327 // public const int HTTP_BODY_MAXLENGTH = 2; 415 // public const int HTTP_BODY_MAXLENGTH = 2;
328 // public const int HTTP_METHOD = 0; 416 // public const int HTTP_METHOD = 0;
329 // public const int HTTP_MIMETYPE = 1; 417 // public const int HTTP_MIMETYPE = 1;
330 // public const int HTTP_VERIFY_CERT = 3; 418 // public const int HTTP_VERIFY_CERT = 3;
419 // public const int HTTP_VERBOSE_THROTTLE = 4;
420 // public const int HTTP_CUSTOM_HEADER = 5;
421 // public const int HTTP_PRAGMA_NO_CACHE = 6;
422
423 /// <summary>
424 /// Module that made this request.
425 /// </summary>
426 public HttpRequestModule RequestModule { get; set; }
427
331 private bool _finished; 428 private bool _finished;
332 public bool Finished 429 public bool Finished
333 { 430 {
334 get { return _finished; } 431 get { return _finished; }
335 } 432 }
336 // public int HttpBodyMaxLen = 2048; // not implemented 433 // public int HttpBodyMaxLen = 2048; // not implemented
@@ -340,11 +437,13 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
340 public string HttpMIMEType = "text/plain;charset=utf-8"; 437 public string HttpMIMEType = "text/plain;charset=utf-8";
341 public int HttpTimeout; 438 public int HttpTimeout;
342 public bool HttpVerifyCert = true; 439 public bool HttpVerifyCert = true;
343 private Thread httpThread; 440 //public bool HttpVerboseThrottle = true; // not implemented
441 public List<string> HttpCustomHeaders = null;
442 public bool HttpPragmaNoCache = true;
344 443
345 // Request info 444 // Request info
346 private UUID _itemID; 445 private UUID _itemID;
347 public UUID ItemID 446 public UUID ItemID
348 { 447 {
349 get { return _itemID; } 448 get { return _itemID; }
350 set { _itemID = value; } 449 set { _itemID = value; }
@@ -358,9 +457,20 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
358 public DateTime Next; 457 public DateTime Next;
359 public string proxyurl; 458 public string proxyurl;
360 public string proxyexcepts; 459 public string proxyexcepts;
460
461 /// <summary>
462 /// Number of HTTP redirects that this request has been through.
463 /// </summary>
464 public int Redirects { get; private set; }
465
466 /// <summary>
467 /// Maximum number of HTTP redirects allowed for this request.
468 /// </summary>
469 public int MaxRedirects { get; set; }
470
361 public string OutboundBody; 471 public string OutboundBody;
362 private UUID _reqID; 472 private UUID _reqID;
363 public UUID ReqID 473 public UUID ReqID
364 { 474 {
365 get { return _reqID; } 475 get { return _reqID; }
366 set { _reqID = value; } 476 set { _reqID = value; }
@@ -374,34 +484,19 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
374 484
375 public void Process() 485 public void Process()
376 { 486 {
377 httpThread = new Thread(SendRequest); 487 SendRequest();
378 httpThread.Name = "HttpRequestThread";
379 httpThread.Priority = ThreadPriority.BelowNormal;
380 httpThread.IsBackground = true;
381 _finished = false;
382 httpThread.Start();
383 } 488 }
384 489
385 /*
386 * TODO: More work on the response codes. Right now
387 * returning 200 for success or 499 for exception
388 */
389
390 public void SendRequest() 490 public void SendRequest()
391 { 491 {
392 HttpWebResponse response = null;
393 StringBuilder sb = new StringBuilder();
394 byte[] buf = new byte[8192];
395 string tempString = null;
396 int count = 0;
397
398 try 492 try
399 { 493 {
400 Request = (HttpWebRequest) WebRequest.Create(Url); 494 Request = (HttpWebRequest)WebRequest.Create(Url);
495 Request.AllowAutoRedirect = false;
401 Request.Method = HttpMethod; 496 Request.Method = HttpMethod;
402 Request.ContentType = HttpMIMEType; 497 Request.ContentType = HttpMIMEType;
403 498
404 if(!HttpVerifyCert) 499 if (!HttpVerifyCert)
405 { 500 {
406 // We could hijack Connection Group Name to identify 501 // We could hijack Connection Group Name to identify
407 // a desired security exception. But at the moment we'll use a dummy header instead. 502 // a desired security exception. But at the moment we'll use a dummy header instead.
@@ -412,41 +507,57 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
412// { 507// {
413// Request.ConnectionGroupName="Verify"; 508// Request.ConnectionGroupName="Verify";
414// } 509// }
415 if (proxyurl != null && proxyurl.Length > 0) 510
511 if (!HttpPragmaNoCache)
512 {
513 Request.Headers.Add("Pragma", "no-cache");
514 }
515
516 if (HttpCustomHeaders != null)
517 {
518 for (int i = 0; i < HttpCustomHeaders.Count; i += 2)
519 Request.Headers.Add(HttpCustomHeaders[i],
520 HttpCustomHeaders[i+1]);
521 }
522
523 if (!string.IsNullOrEmpty(proxyurl))
416 { 524 {
417 if (proxyexcepts != null && proxyexcepts.Length > 0) 525 if (!string.IsNullOrEmpty(proxyexcepts))
418 { 526 {
419 string[] elist = proxyexcepts.Split(';'); 527 string[] elist = proxyexcepts.Split(';');
420 Request.Proxy = new WebProxy(proxyurl, true, elist); 528 Request.Proxy = new WebProxy(proxyurl, true, elist);
421 } 529 }
422 else 530 else
423 { 531 {
424 Request.Proxy = new WebProxy(proxyurl, true); 532 Request.Proxy = new WebProxy(proxyurl, true);
425 } 533 }
426 } 534 }
427 535
428 foreach (KeyValuePair<string, string> entry in ResponseHeaders) 536 if (ResponseHeaders != null)
429 if (entry.Key.ToLower().Equals("user-agent")) 537 {
430 Request.UserAgent = entry.Value; 538 foreach (KeyValuePair<string, string> entry in ResponseHeaders)
431 else 539 if (entry.Key.ToLower().Equals("user-agent") && Request is HttpWebRequest)
432 Request.Headers[entry.Key] = entry.Value; 540 ((HttpWebRequest)Request).UserAgent = entry.Value;
541 else
542 Request.Headers[entry.Key] = entry.Value;
543 }
433 544
434 // Encode outbound data 545 // Encode outbound data
435 if (OutboundBody.Length > 0) 546 if (!string.IsNullOrEmpty(OutboundBody))
436 { 547 {
437 byte[] data = Util.UTF8.GetBytes(OutboundBody); 548 byte[] data = Util.UTF8.GetBytes(OutboundBody);
438 549
439 Request.ContentLength = data.Length; 550 Request.ContentLength = data.Length;
440 Stream bstream = Request.GetRequestStream(); 551 using (Stream bstream = Request.GetRequestStream())
441 bstream.Write(data, 0, data.Length); 552 bstream.Write(data, 0, data.Length);
442 bstream.Close();
443 } 553 }
444 554
445 Request.Timeout = HttpTimeout;
446 try 555 try
447 { 556 {
448 // execute the request 557 IAsyncResult result = (IAsyncResult)Request.BeginGetResponse(ResponseCallback, null);
449 response = (HttpWebResponse) Request.GetResponse(); 558
559 ThreadPool.RegisterWaitForSingleObject(
560 result.AsyncWaitHandle, new WaitOrTimerCallback(TimeoutCallback), null, HttpTimeout, true);
450 } 561 }
451 catch (WebException e) 562 catch (WebException e)
452 { 563 {
@@ -454,57 +565,127 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
454 { 565 {
455 throw; 566 throw;
456 } 567 }
457 response = (HttpWebResponse)e.Response; 568
569 HttpWebResponse response = (HttpWebResponse)e.Response;
570
571 Status = (int)response.StatusCode;
572 ResponseBody = response.StatusDescription;
573 _finished = true;
458 } 574 }
575 }
576 catch (Exception e)
577 {
578// m_log.Debug(
579// string.Format("[SCRIPTS HTTP REQUESTS]: Exception on request to {0} for {1} ", Url, ItemID), e);
459 580
460 Status = (int)response.StatusCode; 581 Status = (int)OSHttpStatusCode.ClientErrorJoker;
582 ResponseBody = e.Message;
583 _finished = true;
584 }
585 }
461 586
462 Stream resStream = response.GetResponseStream(); 587 private void ResponseCallback(IAsyncResult ar)
588 {
589 HttpWebResponse response = null;
463 590
464 do 591 try
592 {
593 try
465 { 594 {
466 // fill the buffer with data 595 response = (HttpWebResponse)Request.EndGetResponse(ar);
467 count = resStream.Read(buf, 0, buf.Length); 596 }
468 597 catch (WebException e)
469 // make sure we read some data 598 {
470 if (count != 0) 599 if (e.Status != WebExceptionStatus.ProtocolError)
471 { 600 {
472 // translate from bytes to ASCII text 601 throw;
473 tempString = Util.UTF8.GetString(buf, 0, count);
474
475 // continue building the string
476 sb.Append(tempString);
477 } 602 }
478 } while (count > 0); // any more data to read?
479 603
480 ResponseBody = sb.ToString(); 604 response = (HttpWebResponse)e.Response;
605 }
606
607 Status = (int)response.StatusCode;
608
609 using (Stream stream = response.GetResponseStream())
610 {
611 StreamReader reader = new StreamReader(stream, Encoding.UTF8);
612 ResponseBody = reader.ReadToEnd();
613 }
481 } 614 }
482 catch (Exception e) 615 catch (Exception e)
483 { 616 {
484 Status = (int)OSHttpStatusCode.ClientErrorJoker; 617 Status = (int)OSHttpStatusCode.ClientErrorJoker;
485 ResponseBody = e.Message; 618 ResponseBody = e.Message;
486 619
487 _finished = true; 620// m_log.Debug(
488 return; 621// string.Format("[SCRIPTS HTTP REQUESTS]: Exception on response to {0} for {1} ", Url, ItemID), e);
489 } 622 }
490 finally 623 finally
491 { 624 {
492 if (response != null) 625 if (response != null)
493 response.Close(); 626 response.Close();
627
628 // We need to resubmit
629 if (
630 (Status == (int)HttpStatusCode.MovedPermanently
631 || Status == (int)HttpStatusCode.Found
632 || Status == (int)HttpStatusCode.SeeOther
633 || Status == (int)HttpStatusCode.TemporaryRedirect))
634 {
635 if (Redirects >= MaxRedirects)
636 {
637 Status = (int)OSHttpStatusCode.ClientErrorJoker;
638 ResponseBody = "Number of redirects exceeded max redirects";
639 _finished = true;
640 }
641 else
642 {
643 string location = response.Headers["Location"];
644
645 if (location == null)
646 {
647 Status = (int)OSHttpStatusCode.ClientErrorJoker;
648 ResponseBody = "HTTP redirect code but no location header";
649 _finished = true;
650 }
651 else if (!RequestModule.CheckAllowed(new Uri(location)))
652 {
653 Status = (int)OSHttpStatusCode.ClientErrorJoker;
654 ResponseBody = "URL from HTTP redirect blocked: " + location;
655 _finished = true;
656 }
657 else
658 {
659 Status = 0;
660 Url = response.Headers["Location"];
661 Redirects++;
662 ResponseBody = null;
663
664// m_log.DebugFormat("Redirecting to [{0}]", Url);
665
666 Process();
667 }
668 }
669 }
670 else
671 {
672 _finished = true;
673 }
494 } 674 }
675 }
495 676
496 _finished = true; 677 private void TimeoutCallback(object state, bool timedOut)
678 {
679 if (timedOut)
680 Request.Abort();
497 } 681 }
498 682
499 public void Stop() 683 public void Stop()
500 { 684 {
501 try 685// m_log.DebugFormat("[SCRIPTS HTTP REQUESTS]: Stopping request to {0} for {1} ", Url, ItemID);
502 { 686
503 httpThread.Abort(); 687 if (Request != null)
504 } 688 Request.Abort();
505 catch (Exception)
506 {
507 }
508 } 689 }
509 } 690 }
510} 691} \ No newline at end of file