Merge branch 'master' of opensimulator.org:/var/git/opensim

This commit is contained in:
Melanie
2018-09-12 13:22:17 +01:00
555 changed files with 112848 additions and 117437 deletions

View File

@@ -32,6 +32,7 @@ using System.Collections.Specialized;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using System.Reflection;
using System.Globalization;
@@ -43,10 +44,11 @@ using log4net;
using Nwc.XmlRpc;
using OpenMetaverse.StructuredData;
using CoolHTTPListener = HttpServer.HttpListener;
using HttpListener=System.Net.HttpListener;
using LogPrio=HttpServer.LogPrio;
using HttpListener = System.Net.HttpListener;
using LogPrio = HttpServer.LogPrio;
using OpenSim.Framework.Monitoring;
using System.IO.Compression;
using System.Security.Cryptography;
namespace OpenSim.Framework.Servers.HttpServer
{
@@ -107,19 +109,26 @@ namespace OpenSim.Framework.Servers.HttpServer
new Dictionary<string, WebSocketRequestDelegate>();
protected uint m_port;
protected uint m_sslport;
protected bool m_ssl;
private X509Certificate2 m_cert;
protected bool m_firstcaps = true;
protected string m_SSLCommonName = "";
protected List<string> m_certNames = new List<string>();
protected List<string> m_certIPs = new List<string>();
protected string m_certCN= "";
protected RemoteCertificateValidationCallback m_certificateValidationCallback = null;
protected IPAddress m_listenIPAddress = IPAddress.Any;
public PollServiceRequestManager PollServiceRequestManager { get; private set; }
public string Protocol
{
get { return m_ssl ? "https://" : "http://"; }
}
public uint SSLPort
{
get { return m_sslport; }
get { return m_port; }
}
public string SSLCommonName
@@ -148,27 +157,166 @@ namespace OpenSim.Framework.Servers.HttpServer
m_port = port;
}
public BaseHttpServer(uint port, bool ssl) : this (port)
private void load_cert(string CPath, string CPass)
{
m_ssl = ssl;
}
public BaseHttpServer(uint port, bool ssl, uint sslport, string CN) : this (port, ssl)
{
if (m_ssl)
try
{
m_sslport = sslport;
m_cert = new X509Certificate2(CPath, CPass);
X509Extension ext = m_cert.Extensions["2.5.29.17"];
if(ext != null)
{
AsnEncodedData asndata = new AsnEncodedData(ext.Oid, ext.RawData);
string datastr = asndata.Format(true);
string[] lines = datastr.Split(new char[] {'\n','\r'});
foreach(string s in lines)
{
if(String.IsNullOrEmpty(s))
continue;
string[] parts = s.Split(new char[] {'='});
if(String.IsNullOrEmpty(parts[0]))
continue;
string entryName = parts[0].Replace(" ","");
if(entryName == "DNSName")
m_certNames.Add(parts[1]);
else if(entryName == "IPAddress")
m_certIPs.Add(parts[1]);
else if(entryName == "Unknown(135)") // stupid mono
{
try
{
if(parts[1].Length == 8)
{
long tmp = long.Parse(parts[1], NumberStyles.AllowHexSpecifier);
tmp = IPAddress.HostToNetworkOrder(tmp);
tmp = (long)((ulong) tmp >> 32);
IPAddress ia = new IPAddress(tmp);
m_certIPs.Add(ia.ToString());
}
}
catch {}
}
}
}
m_certCN = m_cert.GetNameInfo(X509NameType.SimpleName, false);
}
catch
{
throw new Exception("SSL cert load error");
}
}
public BaseHttpServer(uint port, bool ssl, string CPath, string CPass) : this (port, ssl)
public BaseHttpServer(uint port, bool ssl, string CN, string CPath, string CPass)
{
if (m_ssl)
m_port = port;
if (ssl)
{
m_cert = new X509Certificate2(CPath, CPass);
if(string.IsNullOrEmpty(CPath))
throw new Exception("invalid main http server cert path");
if(Uri.CheckHostName(CN) == UriHostNameType.Unknown)
throw new Exception("invalid main http server CN (ExternalHostName)");
m_certNames.Clear();
m_certIPs.Clear();
m_certCN= "";
m_ssl = true;
load_cert(CPath, CPass);
if(!CheckSSLCertHost(CN))
throw new Exception("invalid main http server CN (ExternalHostName)");
m_SSLCommonName = CN;
if(m_cert.Issuer == m_cert.Subject )
m_log.Warn("Self signed certificate. Clients need to allow this (some viewers debug option NoVerifySSLcert must be set to true");
}
else
m_ssl = false;
}
public BaseHttpServer(uint port, bool ssl, string CPath, string CPass)
{
m_port = port;
if (ssl)
{
load_cert(CPath, CPass);
if(m_cert.Issuer == m_cert.Subject )
m_log.Warn("Self signed certificate. Http clients need to allow this");
m_ssl = true;
}
else
m_ssl = false;
}
static bool MatchDNS (string hostname, string dns)
{
int indx = dns.IndexOf ('*');
if (indx == -1)
return (String.Compare(hostname, dns, true, CultureInfo.InvariantCulture) == 0);
int dnslen = dns.Length;
dnslen--;
if(indx == dnslen)
return true; // just * ?
if(indx > dnslen - 2)
return false; // 2 short ?
if (dns[indx + 1] != '.')
return false;
int indx2 = dns.IndexOf ('*', indx + 1);
if (indx2 != -1)
return false; // there can only be one;
string end = dns.Substring(indx + 1);
int hostlen = hostname.Length;
int endlen = end.Length;
int length = hostlen - endlen;
if (length <= 0)
return false;
if (String.Compare(hostname, length, end, 0, endlen, true, CultureInfo.InvariantCulture) != 0)
return false;
if (indx == 0)
{
indx2 = hostname.IndexOf ('.');
return ((indx2 == -1) || (indx2 >= length));
}
string start = dns.Substring (0, indx);
return (String.Compare (hostname, 0, start, 0, start.Length, true, CultureInfo.InvariantCulture) == 0);
}
public bool CheckSSLCertHost(string hostname)
{
UriHostNameType htype = Uri.CheckHostName(hostname);
if(htype == UriHostNameType.Unknown || htype == UriHostNameType.Basic)
return false;
if(htype == UriHostNameType.Dns)
{
foreach(string name in m_certNames)
{
if(MatchDNS(hostname, name))
return true;
}
if(MatchDNS(hostname, m_certCN))
return true;
}
else
{
foreach(string ip in m_certIPs)
{
if (String.Compare(hostname, ip, true, CultureInfo.InvariantCulture) == 0)
return true;
}
}
return false;
}
/// <summary>
/// Add a stream handler to the http server. If the handler already exists, then nothing happens.
/// </summary>
@@ -396,14 +544,10 @@ namespace OpenSim.Framework.Servers.HttpServer
if (psEvArgs.Request != null)
{
OSHttpRequest req = new OSHttpRequest(context, request);
Stream requestStream = req.InputStream;
string requestBody;
Encoding encoding = Encoding.UTF8;
StreamReader reader = new StreamReader(requestStream, encoding);
string requestBody = reader.ReadToEnd();
reader.Close();
using(StreamReader reader = new StreamReader(req.InputStream, encoding))
requestBody = reader.ReadToEnd();
Hashtable keysvals = new Hashtable();
Hashtable headervals = new Hashtable();
@@ -461,8 +605,7 @@ namespace OpenSim.Framework.Servers.HttpServer
}
OSHttpResponse resp = new OSHttpResponse(new HttpResponse(context, request),context);
resp.ReuseContext = true;
// resp.ReuseContext = false;
HandleRequest(req, resp);
// !!!HACK ALERT!!!
@@ -494,6 +637,8 @@ namespace OpenSim.Framework.Servers.HttpServer
{
try
{
if(request.InputStream != null && request.InputStream.CanRead)
request.InputStream.Close();
byte[] buffer500 = SendHTML500(response);
response.OutputStream.Write(buffer500, 0, buffer500.Length);
response.Send();
@@ -541,7 +686,6 @@ namespace OpenSim.Framework.Servers.HttpServer
// }
// }
//response.KeepAlive = true;
response.SendChunked = false;
string path = request.RawUrl;
@@ -565,15 +709,11 @@ namespace OpenSim.Framework.Servers.HttpServer
{
//m_log.Debug("[BASE HTTP SERVER]: Found Caps based HTTP Handler");
IGenericHTTPHandler HTTPRequestHandler = requestHandler as IGenericHTTPHandler;
Stream requestStream = request.InputStream;
string requestBody;
Encoding encoding = Encoding.UTF8;
StreamReader reader = new StreamReader(requestStream, encoding);
string requestBody = reader.ReadToEnd();
reader.Close();
//requestStream.Close();
using(StreamReader reader = new StreamReader(request.InputStream, encoding))
requestBody = reader.ReadToEnd();
Hashtable keysvals = new Hashtable();
Hashtable headervals = new Hashtable();
@@ -613,7 +753,6 @@ namespace OpenSim.Framework.Servers.HttpServer
else
{
IStreamHandler streamHandler = (IStreamHandler)requestHandler;
using (MemoryStream memoryStream = new MemoryStream())
{
streamHandler.Handle(path, request.InputStream, memoryStream, request, response);
@@ -690,7 +829,8 @@ namespace OpenSim.Framework.Servers.HttpServer
}
}
request.InputStream.Close();
if(request.InputStream != null && request.InputStream.CanRead)
request.InputStream.Dispose();
if (buffer != null)
{
@@ -723,10 +863,6 @@ namespace OpenSim.Framework.Servers.HttpServer
requestEndTick = Environment.TickCount;
response.Send();
//response.OutputStream.Close();
//response.FreeContext();
}
catch (SocketException e)
{
@@ -758,6 +894,9 @@ namespace OpenSim.Framework.Servers.HttpServer
}
finally
{
if(request.InputStream != null && request.InputStream.CanRead)
request.InputStream.Close();
// Every month or so this will wrap and give bad numbers, not really a problem
// since its just for reporting
int tickdiff = requestEndTick - requestStartTick;
@@ -998,7 +1137,7 @@ namespace OpenSim.Framework.Servers.HttpServer
{
String requestBody;
Stream requestStream = request.InputStream;
Stream requestStream = Util.Copy(request.InputStream);
Stream innerStream = null;
try
{
@@ -1009,15 +1148,15 @@ namespace OpenSim.Framework.Servers.HttpServer
}
using (StreamReader reader = new StreamReader(requestStream, Encoding.UTF8))
{
requestBody = reader.ReadToEnd();
}
}
finally
{
if (innerStream != null)
if (innerStream != null && innerStream.CanRead)
innerStream.Dispose();
requestStream.Dispose();
if (requestStream.CanRead)
requestStream.Dispose();
}
//m_log.Debug(requestBody);
@@ -1098,6 +1237,17 @@ namespace OpenSim.Framework.Servers.HttpServer
if (gridproxy)
xmlRprcRequest.Params.Add("gridproxy"); // Param[4]
// reserve this for
// ... by Fumi.Iseki for DTLNSLMoneyServer
// BUT make its presence possible to detect/parse
string rcn = request.IHttpClientContext.SSLCommonName;
if(!string.IsNullOrWhiteSpace(rcn))
{
rcn = "SSLCN:" + rcn;
xmlRprcRequest.Params.Add(rcn); // Param[4] or Param[5]
}
try
{
xmlRpcResponse = method(xmlRprcRequest, request.RemoteIPEndPoint);
@@ -1263,15 +1413,12 @@ namespace OpenSim.Framework.Servers.HttpServer
//m_log.Warn("[BASE HTTP SERVER]: We've figured out it's a LLSD Request");
Stream requestStream = request.InputStream;
string requestBody;
Encoding encoding = Encoding.UTF8;
StreamReader reader = new StreamReader(requestStream, encoding);
string requestBody = reader.ReadToEnd();
reader.Close();
requestStream.Close();
using(StreamReader reader = new StreamReader(requestStream, encoding))
requestBody= reader.ReadToEnd();
//m_log.DebugFormat("[OGP]: {0}:{1}", request.RawUrl, requestBody);
response.KeepAlive = true;
OSD llsdRequest = null;
OSD llsdResponse = null;
@@ -1592,15 +1739,10 @@ namespace OpenSim.Framework.Servers.HttpServer
byte[] buffer;
Stream requestStream = request.InputStream;
string requestBody;
Encoding encoding = Encoding.UTF8;
StreamReader reader = new StreamReader(requestStream, encoding);
string requestBody = reader.ReadToEnd();
// avoid warning for now
reader.ReadToEnd();
reader.Close();
requestStream.Close();
using(StreamReader reader = new StreamReader(requestStream, encoding))
requestBody = reader.ReadToEnd();
Hashtable keysvals = new Hashtable();
Hashtable headervals = new Hashtable();
@@ -1792,20 +1934,13 @@ namespace OpenSim.Framework.Servers.HttpServer
{
response.ProtocolVersion = (string)responsedata["http_protocol_version"];
}
/*
if (responsedata.ContainsKey("keepalive"))
{
bool keepalive = (bool)responsedata["keepalive"];
response.KeepAlive = keepalive;
}
if (responsedata.ContainsKey("reusecontext"))
response.ReuseContext = (bool) responsedata["reusecontext"];
*/
// disable this things
response.KeepAlive = false;
response.ReuseContext = false;
// Cross-Origin Resource Sharing with simple requests
if (responsedata.ContainsKey("access_control_allow_origin"))
response.AddHeader("Access-Control-Allow-Origin", (string)responsedata["access_control_allow_origin"]);
@@ -1818,11 +1953,8 @@ namespace OpenSim.Framework.Servers.HttpServer
contentType = "text/html";
}
// The client ignores anything but 200 here for web login, so ensure that this is 200 for that
response.StatusCode = responsecode;
if (responsecode == (int)OSHttpStatusCode.RedirectMovedPermanently)
@@ -1832,13 +1964,12 @@ namespace OpenSim.Framework.Servers.HttpServer
}
response.AddHeader("Content-Type", contentType);
if (responsedata.ContainsKey("headers"))
{
Hashtable headerdata = (Hashtable)responsedata["headers"];
foreach (string header in headerdata.Keys)
response.AddHeader(header, (string)headerdata[header]);
response.AddHeader(header, headerdata[header].ToString());
}
byte[] buffer;
@@ -1906,7 +2037,7 @@ namespace OpenSim.Framework.Servers.HttpServer
public void Start()
{
Start(true);
Start(true,true);
}
/// <summary>
@@ -1916,7 +2047,7 @@ namespace OpenSim.Framework.Servers.HttpServer
/// If true then poll responses are performed asynchronsly.
/// Option exists to allow regression tests to perform processing synchronously.
/// </param>
public void Start(bool performPollResponsesAsync)
public void Start(bool performPollResponsesAsync, bool runPool)
{
m_log.InfoFormat(
"[BASE HTTP SERVER]: Starting {0} server on port {1}", UseSSL ? "HTTPS" : "HTTP", Port);
@@ -1945,6 +2076,8 @@ namespace OpenSim.Framework.Servers.HttpServer
//m_httpListener.Prefixes.Add("https://+:" + (m_sslport) + "/");
//m_httpListener.Prefixes.Add("http://+:" + m_port + "/");
m_httpListener2 = CoolHTTPListener.Create(IPAddress.Any, (int)m_port, m_cert);
if(m_certificateValidationCallback != null)
m_httpListener2.CertificateValidationCallback = m_certificateValidationCallback;
m_httpListener2.ExceptionThrown += httpServerException;
m_httpListener2.LogWriter = httpserverlog;
}
@@ -1954,9 +2087,11 @@ namespace OpenSim.Framework.Servers.HttpServer
m_httpListener2.Start(64);
// Long Poll Service Manager with 3 worker threads a 25 second timeout for no events
PollServiceRequestManager = new PollServiceRequestManager(this, performPollResponsesAsync, 2, 25000);
PollServiceRequestManager.Start();
if(runPool)
{
PollServiceRequestManager = new PollServiceRequestManager(this, performPollResponsesAsync, 2, 25000);
PollServiceRequestManager.Start();
}
HTTPDRunning = true;
@@ -1970,7 +2105,7 @@ namespace OpenSim.Framework.Servers.HttpServer
catch (Exception e)
{
m_log.Error("[BASE HTTP SERVER]: Error - " + e.Message);
m_log.Error("[BASE HTTP SERVER]: Tip: Do you have permission to listen on port " + m_port + ", " + m_sslport + "?");
m_log.Error("[BASE HTTP SERVER]: Tip: Do you have permission to listen on port " + m_port + "?");
// We want this exception to halt the entire server since in current configurations we aren't too
// useful without inbound HTTP.
@@ -2028,7 +2163,8 @@ namespace OpenSim.Framework.Servers.HttpServer
try
{
PollServiceRequestManager.Stop();
if(PollServiceRequestManager != null)
PollServiceRequestManager.Stop();
m_httpListener2.ExceptionThrown -= httpServerException;
//m_httpListener2.DisconnectHandler = null;
@@ -2135,10 +2271,9 @@ namespace OpenSim.Framework.Servers.HttpServer
string file = Path.Combine(".", "http_500.html");
if (!File.Exists(file))
return getDefaultHTTP500();
StreamReader sr = File.OpenText(file);
string result = sr.ReadToEnd();
sr.Close();
string result;
using(StreamReader sr = File.OpenText(file))
result = sr.ReadToEnd();
return result;
}

View File

@@ -118,7 +118,7 @@ namespace OpenSim.Framework.Servers.HttpServer
/// </summary>
string StatusDescription { get; set; }
bool ReuseContext { get; set; }
// bool ReuseContext { get; set; }
/// <summary>
/// Add a header field and content to the response.

View File

@@ -257,25 +257,6 @@ namespace OpenSim.Framework.Servers.HttpServer
}
}
public bool ReuseContext
{
get
{
if (_httpClientContext != null)
{
return !_httpClientContext.EndWhenDone;
}
return true;
}
set
{
if (_httpClientContext != null)
{
_httpClientContext.EndWhenDone = !value;
}
}
}
protected IHttpResponse _httpResponse;
private IHttpClientContext _httpClientContext;

View File

@@ -37,6 +37,7 @@ namespace OpenSim.Framework.Servers.HttpServer
public delegate Hashtable GetEventsMethod(UUID requestID, UUID pId);
public delegate Hashtable NoEventsMethod(UUID requestID, UUID pId);
public delegate void DropMethod(UUID requestID, UUID pId);
public class PollServiceEventArgs : EventArgs
{
@@ -44,13 +45,14 @@ namespace OpenSim.Framework.Servers.HttpServer
public GetEventsMethod GetEvents;
public NoEventsMethod NoEvents;
public RequestMethod Request;
public DropMethod Drop;
public UUID Id;
public int TimeOutms;
public EventType Type;
public enum EventType : int
{
LongPoll = 0,
Poll = 0,
LslHttp = 1,
Inventory = 2,
Texture = 3,
@@ -73,16 +75,17 @@ namespace OpenSim.Framework.Servers.HttpServer
RequestMethod pRequest,
string pUrl,
HasEventsMethod pHasEvents, GetEventsMethod pGetEvents, NoEventsMethod pNoEvents,
UUID pId, int pTimeOutms)
DropMethod pDrop, UUID pId, int pTimeOutms)
{
Request = pRequest;
Url = pUrl;
HasEvents = pHasEvents;
GetEvents = pGetEvents;
NoEvents = pNoEvents;
Drop = pDrop;
Id = pId;
TimeOutms = pTimeOutms;
Type = EventType.LongPoll;
Type = EventType.Poll;
}
}
}

View File

@@ -47,8 +47,10 @@ namespace OpenSim.Framework.Servers.HttpServer
public readonly UUID RequestID;
public int contextHash;
/*
private void GenContextHash()
{
Random rnd = new Random();
contextHash = 0;
if (Request.Headers["remote_addr"] != null)
@@ -62,8 +64,9 @@ namespace OpenSim.Framework.Servers.HttpServer
}
else
contextHash += rnd.Next() & 0xffff;
}
}
*/
public PollServiceHttpRequest(
PollServiceEventArgs pPollServiceArgs, IHttpClientContext pHttpContext, IHttpRequest pRequest)
{
@@ -72,7 +75,8 @@ namespace OpenSim.Framework.Servers.HttpServer
Request = pRequest;
RequestTime = System.Environment.TickCount;
RequestID = UUID.Random();
GenContextHash();
// GenContextHash();
contextHash = HttpContext.contextID;
}
internal void DoHTTPGruntWork(BaseHttpServer server, Hashtable responsedata)
@@ -82,10 +86,12 @@ namespace OpenSim.Framework.Servers.HttpServer
byte[] buffer = server.DoHTTPGruntWork(responsedata, response);
if(Request.Body.CanRead)
Request.Body.Dispose();
response.SendChunked = false;
response.ContentLength64 = buffer.Length;
response.ContentEncoding = Encoding.UTF8;
response.ReuseContext = false;
try
{
@@ -114,10 +120,12 @@ namespace OpenSim.Framework.Servers.HttpServer
OSHttpResponse response
= new OSHttpResponse(new HttpResponse(HttpContext, Request), HttpContext);
if(Request.Body.CanRead)
Request.Body.Dispose();
response.SendChunked = false;
response.ContentLength64 = 0;
response.ContentEncoding = Encoding.UTF8;
response.ReuseContext = false;
response.KeepAlive = false;
response.SendChunked = false;
response.StatusCode = 503;
@@ -127,7 +135,7 @@ namespace OpenSim.Framework.Servers.HttpServer
response.OutputStream.Flush();
response.Send();
}
catch (Exception e)
catch
{
}
}

View File

@@ -30,13 +30,10 @@ using System.Collections;
using System.Threading;
using System.Reflection;
using log4net;
using HttpServer;
using OpenSim.Framework;
using OpenSim.Framework.Monitoring;
using Amib.Threading;
using System.IO;
using System.Text;
using System.Collections.Generic;
using System.Collections.Concurrent;
namespace OpenSim.Framework.Servers.HttpServer
{
@@ -46,21 +43,18 @@ namespace OpenSim.Framework.Servers.HttpServer
private readonly BaseHttpServer m_server;
private Dictionary<PollServiceHttpRequest, Queue<PollServiceHttpRequest>> m_bycontext;
private BlockingQueue<PollServiceHttpRequest> m_requests = new BlockingQueue<PollServiceHttpRequest>();
private static Queue<PollServiceHttpRequest> m_slowRequests = new Queue<PollServiceHttpRequest>();
private static Queue<PollServiceHttpRequest> m_retryRequests = new Queue<PollServiceHttpRequest>();
private Dictionary<int, Queue<PollServiceHttpRequest>> m_bycontext;
private BlockingCollection<PollServiceHttpRequest> m_requests = new BlockingCollection<PollServiceHttpRequest>();
private static ConcurrentQueue<PollServiceHttpRequest> m_retryRequests = new ConcurrentQueue<PollServiceHttpRequest>();
private uint m_WorkerThreadCount = 0;
private Thread[] m_workerThreads;
private Thread m_retrysThread;
private bool m_running = false;
private int slowCount = 0;
private SmartThreadPool m_threadPool;
public PollServiceRequestManager(
BaseHttpServer pSrv, bool performResponsesAsync, uint pWorkerThreadCount, int pTimeout)
{
@@ -68,8 +62,7 @@ namespace OpenSim.Framework.Servers.HttpServer
m_WorkerThreadCount = pWorkerThreadCount;
m_workerThreads = new Thread[m_WorkerThreadCount];
PollServiceHttpRequestComparer preqCp = new PollServiceHttpRequestComparer();
m_bycontext = new Dictionary<PollServiceHttpRequest, Queue<PollServiceHttpRequest>>(preqCp);
m_bycontext = new Dictionary<int, Queue<PollServiceHttpRequest>>(256);
STPStartInfo startInfo = new STPStartInfo();
startInfo.IdleTimeout = 30000;
@@ -80,7 +73,6 @@ namespace OpenSim.Framework.Servers.HttpServer
startInfo.ThreadPoolName = "PoolService";
m_threadPool = new SmartThreadPool(startInfo);
}
public void Start()
@@ -95,7 +87,7 @@ namespace OpenSim.Framework.Servers.HttpServer
PoolWorkerJob,
string.Format("PollServiceWorkerThread {0}:{1}", i, m_server.Port),
ThreadPriority.Normal,
false,
true,
false,
null,
int.MaxValue);
@@ -105,36 +97,32 @@ namespace OpenSim.Framework.Servers.HttpServer
this.CheckRetries,
string.Format("PollServiceWatcherThread:{0}", m_server.Port),
ThreadPriority.Normal,
false,
true,
true,
null,
1000 * 60 * 10);
}
private void ReQueueEvent(PollServiceHttpRequest req)
{
if (m_running)
{
lock (m_retryRequests)
m_retryRequests.Enqueue(req);
}
m_retryRequests.Enqueue(req);
}
public void Enqueue(PollServiceHttpRequest req)
{
Queue<PollServiceHttpRequest> ctxQeueue;
int rhash = req.contextHash;
lock (m_bycontext)
{
Queue<PollServiceHttpRequest> ctxQeueue;
if (m_bycontext.TryGetValue(req, out ctxQeueue))
if (m_bycontext.TryGetValue(rhash, out ctxQeueue))
{
ctxQeueue.Enqueue(req);
}
else
{
ctxQeueue = new Queue<PollServiceHttpRequest>();
m_bycontext[req] = ctxQeueue;
m_bycontext[rhash] = ctxQeueue;
EnqueueInt(req);
}
}
@@ -143,9 +131,10 @@ namespace OpenSim.Framework.Servers.HttpServer
public void byContextDequeue(PollServiceHttpRequest req)
{
Queue<PollServiceHttpRequest> ctxQeueue;
int rhash = req.contextHash;
lock (m_bycontext)
{
if (m_bycontext.TryGetValue(req, out ctxQeueue))
if (m_bycontext.TryGetValue(rhash, out ctxQeueue))
{
if (ctxQeueue.Count > 0)
{
@@ -154,51 +143,41 @@ namespace OpenSim.Framework.Servers.HttpServer
}
else
{
m_bycontext.Remove(req);
m_bycontext.Remove(rhash);
}
}
}
}
public void DropByContext(PollServiceHttpRequest req)
{
Queue<PollServiceHttpRequest> ctxQeueue;
int rhash = req.contextHash;
lock (m_bycontext)
{
if (m_bycontext.TryGetValue(rhash, out ctxQeueue))
{
ctxQeueue.Clear();
m_bycontext.Remove(rhash);
}
}
}
public void EnqueueInt(PollServiceHttpRequest req)
{
if (m_running)
{
if (req.PollServiceArgs.Type != PollServiceEventArgs.EventType.LongPoll)
{
m_requests.Enqueue(req);
}
else
{
lock (m_slowRequests)
m_slowRequests.Enqueue(req);
}
}
m_requests.Add(req);
}
private void CheckRetries()
{
PollServiceHttpRequest preq;
while (m_running)
{
Thread.Sleep(100); // let the world move .. back to faster rate
Thread.Sleep(100);
Watchdog.UpdateThread();
lock (m_retryRequests)
{
while (m_retryRequests.Count > 0 && m_running)
m_requests.Enqueue(m_retryRequests.Dequeue());
}
slowCount++;
if (slowCount >= 10)
{
slowCount = 0;
lock (m_slowRequests)
{
while (m_slowRequests.Count > 0 && m_running)
m_requests.Enqueue(m_slowRequests.Dequeue());
}
}
while (m_running && m_retryRequests.TryDequeue(out preq))
m_requests.Add(preq);
}
}
@@ -206,117 +185,130 @@ namespace OpenSim.Framework.Servers.HttpServer
{
m_running = false;
Thread.Sleep(1000); // let the world move
Thread.Sleep(100); // let the world move
foreach (Thread t in m_workerThreads)
Watchdog.AbortThread(t.ManagedThreadId);
m_threadPool.Shutdown();
// any entry in m_bycontext should have a active request on the other queues
// so just delete contents to easy GC
foreach (Queue<PollServiceHttpRequest> qu in m_bycontext.Values)
qu.Clear();
m_bycontext.Clear();
PollServiceHttpRequest req;
try
{
foreach (PollServiceHttpRequest req in m_retryRequests)
{
while(m_retryRequests.TryDequeue(out req))
req.DoHTTPstop(m_server);
}
}
catch
{
}
PollServiceHttpRequest wreq;
m_retryRequests.Clear();
lock (m_slowRequests)
try
{
while(m_requests.TryTake(out req, 0))
req.DoHTTPstop(m_server);
}
catch
{
while (m_slowRequests.Count > 0)
m_requests.Enqueue(m_slowRequests.Dequeue());
}
while (m_requests.Count() > 0)
{
try
{
wreq = m_requests.Dequeue(0);
wreq.DoHTTPstop(m_server);
m_requests.Dispose();
}
catch
{
}
}
m_requests.Clear();
}
// work threads
private void PoolWorkerJob()
{
PollServiceHttpRequest req;
while (m_running)
{
PollServiceHttpRequest req = m_requests.Dequeue(5000);
Watchdog.UpdateThread();
if (req != null)
req = null;
if(!m_requests.TryTake(out req, 4500) || req == null)
{
try
{
if (req.PollServiceArgs.HasEvents(req.RequestID, req.PollServiceArgs.Id))
{
Hashtable responsedata = req.PollServiceArgs.GetEvents(req.RequestID, req.PollServiceArgs.Id);
Watchdog.UpdateThread();
continue;
}
Watchdog.UpdateThread();
try
{
if(!req.HttpContext.CanSend())
{
req.PollServiceArgs.Drop(req.RequestID, req.PollServiceArgs.Id);
byContextDequeue(req);
continue;
}
if(req.HttpContext.IsSending())
{
if ((Environment.TickCount - req.RequestTime) > req.PollServiceArgs.TimeOutms)
{
req.PollServiceArgs.Drop(req.RequestID, req.PollServiceArgs.Id);
byContextDequeue(req);
}
else
ReQueueEvent(req);
continue;
}
if (req.PollServiceArgs.HasEvents(req.RequestID, req.PollServiceArgs.Id))
{
PollServiceHttpRequest nreq = req;
m_threadPool.QueueWorkItem(x =>
{
try
{
Hashtable responsedata = nreq.PollServiceArgs.GetEvents(nreq.RequestID, nreq.PollServiceArgs.Id);
nreq.DoHTTPGruntWork(m_server, responsedata);
}
catch (ObjectDisposedException) { }
finally
{
byContextDequeue(nreq);
nreq = null;
}
return null;
}, null);
}
else
{
if ((Environment.TickCount - req.RequestTime) > req.PollServiceArgs.TimeOutms)
{
PollServiceHttpRequest nreq = req;
m_threadPool.QueueWorkItem(x =>
{
try
{
req.DoHTTPGruntWork(m_server, responsedata);
byContextDequeue(req);
nreq.DoHTTPGruntWork(m_server,
nreq.PollServiceArgs.NoEvents(nreq.RequestID, nreq.PollServiceArgs.Id));
}
catch (ObjectDisposedException) // Browser aborted before we could read body, server closed the stream
catch (ObjectDisposedException) {}
finally
{
// Ignore it, no need to reply
byContextDequeue(nreq);
nreq = null;
}
return null;
}, null);
}
else
{
if ((Environment.TickCount - req.RequestTime) > req.PollServiceArgs.TimeOutms)
{
m_threadPool.QueueWorkItem(x =>
{
try
{
req.DoHTTPGruntWork(m_server,
req.PollServiceArgs.NoEvents(req.RequestID, req.PollServiceArgs.Id));
byContextDequeue(req);
}
catch (ObjectDisposedException)
{
// Ignore it, no need to reply
}
return null;
}, null);
}
else
{
ReQueueEvent(req);
}
ReQueueEvent(req);
}
}
catch (Exception e)
{
m_log.ErrorFormat("Exception in poll service thread: " + e.ToString());
}
}
catch (Exception e)
{
m_log.ErrorFormat("Exception in poll service thread: " + e.ToString());
}
}
}
}
}

View File

@@ -50,11 +50,10 @@ namespace OpenSim.Framework.Servers.HttpServer
protected override byte[] ProcessRequest(string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
{
string requestBody;
Encoding encoding = Encoding.UTF8;
StreamReader streamReader = new StreamReader(request, encoding);
string requestBody = streamReader.ReadToEnd();
streamReader.Close();
using(StreamReader streamReader = new StreamReader(request,encoding))
requestBody = streamReader.ReadToEnd();
string param = GetParam(path);
string responseString = m_restMethod(requestBody, path, param, httpRequest, httpResponse);