we should only have one http poll service manager per instance

0.9.1.0-post-fixes
UbitUmarov 2018-11-03 11:43:47 +00:00
parent 3e6342eb61
commit 5b5e53aa1d
4 changed files with 182 additions and 80 deletions

View File

@ -44,11 +44,11 @@ using log4net;
using Nwc.XmlRpc; using Nwc.XmlRpc;
using OpenMetaverse.StructuredData; using OpenMetaverse.StructuredData;
using CoolHTTPListener = HttpServer.HttpListener; using CoolHTTPListener = HttpServer.HttpListener;
using HttpListener = System.Net.HttpListener;
using LogPrio = HttpServer.LogPrio; using LogPrio = HttpServer.LogPrio;
using OpenSim.Framework.Monitoring; using OpenSim.Framework.Monitoring;
using System.IO.Compression; using System.IO.Compression;
using System.Security.Cryptography; using System.Security.Cryptography;
using OpenSim.Framework.Servers;
namespace OpenSim.Framework.Servers.HttpServer namespace OpenSim.Framework.Servers.HttpServer
{ {
@ -57,6 +57,8 @@ namespace OpenSim.Framework.Servers.HttpServer
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private HttpServerLogWriter httpserverlog = new HttpServerLogWriter(); private HttpServerLogWriter httpserverlog = new HttpServerLogWriter();
private static Encoding UTF8NoBOM = new System.Text.UTF8Encoding(false); private static Encoding UTF8NoBOM = new System.Text.UTF8Encoding(false);
public static PollServiceRequestManager m_pollServiceManager;
private static object m_generalLock = new object();
/// <summary> /// <summary>
/// This is a pending websocket request before it got an sucessful upgrade response. /// This is a pending websocket request before it got an sucessful upgrade response.
@ -119,7 +121,6 @@ namespace OpenSim.Framework.Servers.HttpServer
protected IPAddress m_listenIPAddress = IPAddress.Any; protected IPAddress m_listenIPAddress = IPAddress.Any;
public PollServiceRequestManager PollServiceRequestManager { get; private set; }
public string Protocol public string Protocol
{ {
@ -249,24 +250,24 @@ namespace OpenSim.Framework.Servers.HttpServer
m_ssl = false; m_ssl = false;
} }
static bool MatchDNS (string hostname, string dns) static bool MatchDNS(string hostname, string dns)
{ {
int indx = dns.IndexOf ('*'); int indx = dns.IndexOf('*');
if (indx == -1) if (indx == -1)
return (String.Compare(hostname, dns, true, CultureInfo.InvariantCulture) == 0); return (String.Compare(hostname, dns, true, CultureInfo.InvariantCulture) == 0);
int dnslen = dns.Length; int dnslen = dns.Length;
dnslen--; dnslen--;
if(indx == dnslen) if (indx == dnslen)
return true; // just * ? return true; // just * ?
if(indx > dnslen - 2) if (indx > dnslen - 2)
return false; // 2 short ? return false; // 2 short ?
if (dns[indx + 1] != '.') if (dns[indx + 1] != '.')
return false; return false;
int indx2 = dns.IndexOf ('*', indx + 1); int indx2 = dns.IndexOf('*', indx + 1);
if (indx2 != -1) if (indx2 != -1)
return false; // there can only be one; return false; // there can only be one;
@ -282,12 +283,12 @@ namespace OpenSim.Framework.Servers.HttpServer
if (indx == 0) if (indx == 0)
{ {
indx2 = hostname.IndexOf ('.'); indx2 = hostname.IndexOf('.');
return ((indx2 == -1) || (indx2 >= length)); return ((indx2 == -1) || (indx2 >= length));
} }
string start = dns.Substring (0, indx); string start = dns.Substring(0, indx);
return (String.Compare (hostname, 0, start, 0, start.Length, true, CultureInfo.InvariantCulture) == 0); return (String.Compare(hostname, 0, start, 0, start.Length, true, CultureInfo.InvariantCulture) == 0);
} }
public bool CheckSSLCertHost(string hostname) public bool CheckSSLCertHost(string hostname)
@ -527,7 +528,6 @@ namespace OpenSim.Framework.Servers.HttpServer
public void OnRequest(object source, RequestEventArgs args) public void OnRequest(object source, RequestEventArgs args)
{ {
RequestNumber++; RequestNumber++;
try try
{ {
IHttpClientContext context = (IHttpClientContext)source; IHttpClientContext context = (IHttpClientContext)source;
@ -576,7 +576,7 @@ namespace OpenSim.Framework.Servers.HttpServer
psEvArgs.Request(psreq.RequestID, keysvals); psEvArgs.Request(psreq.RequestID, keysvals);
} }
PollServiceRequestManager.Enqueue(psreq); m_pollServiceManager.Enqueue(psreq);
} }
else else
{ {
@ -616,16 +616,6 @@ namespace OpenSim.Framework.Servers.HttpServer
request.AcceptTypes[i] = string.Empty; request.AcceptTypes[i] = string.Empty;
} }
// public void ConvertIHttpClientContextToOSHttp(object stateinfo)
// {
// HttpServerContextObj objstate = (HttpServerContextObj)stateinfo;
// OSHttpRequest request = objstate.oreq;
// OSHttpResponse resp = objstate.oresp;
// HandleRequest(request,resp);
// }
/// <summary> /// <summary>
/// This methods is the start of incoming HTTP request handling. /// This methods is the start of incoming HTTP request handling.
/// </summary> /// </summary>
@ -2036,7 +2026,7 @@ namespace OpenSim.Framework.Servers.HttpServer
public void Start() public void Start()
{ {
Start(true,true); Start(true, true);
} }
/// <summary> /// <summary>
@ -2085,11 +2075,14 @@ namespace OpenSim.Framework.Servers.HttpServer
//m_httpListener.Start(); //m_httpListener.Start();
m_httpListener2.Start(64); m_httpListener2.Start(64);
// Long Poll Service Manager with 3 worker threads a 25 second timeout for no events lock(m_generalLock)
if(runPool)
{ {
PollServiceRequestManager = new PollServiceRequestManager(this, performPollResponsesAsync, 2, 25000); if (runPool)
PollServiceRequestManager.Start(); {
if(m_pollServiceManager == null)
m_pollServiceManager = new PollServiceRequestManager(performPollResponsesAsync, 2, 25000);
m_pollServiceManager.Start();
}
} }
HTTPDRunning = true; HTTPDRunning = true;
@ -2143,27 +2136,22 @@ namespace OpenSim.Framework.Servers.HttpServer
if (source.ToString() == "HttpServer.HttpListener" && exception.ToString().StartsWith("Mono.Security.Protocol.Tls.TlsException")) if (source.ToString() == "HttpServer.HttpListener" && exception.ToString().StartsWith("Mono.Security.Protocol.Tls.TlsException"))
return; return;
m_log.ErrorFormat("[BASE HTTP SERVER]: {0} had an exception {1}", source.ToString(), exception.ToString()); m_log.ErrorFormat("[BASE HTTP SERVER]: {0} had an exception {1}", source.ToString(), exception.ToString());
/*
if (HTTPDRunning)// && NotSocketErrors > 5)
{
Stop();
Thread.Sleep(200);
StartHTTP();
m_log.Warn("[HTTPSERVER]: Died. Trying to kick.....");
}
*/
} }
public void Stop() public void Stop(bool stopPool = false)
{ {
HTTPDRunning = false; HTTPDRunning = false;
StatsManager.DeregisterStat(m_requestsProcessedStat); StatsManager.DeregisterStat(m_requestsProcessedStat);
try try
{ {
if(PollServiceRequestManager != null) lock(m_generalLock)
PollServiceRequestManager.Stop(); {
if (stopPool && m_pollServiceManager != null)
m_pollServiceManager.Stop();
}
m_httpListener2.ExceptionThrown -= httpServerException; m_httpListener2.ExceptionThrown -= httpServerException;
//m_httpListener2.DisconnectHandler = null; //m_httpListener2.DisconnectHandler = null;

View File

@ -79,12 +79,12 @@ namespace OpenSim.Framework.Servers.HttpServer
contextHash = HttpContext.contextID; contextHash = HttpContext.contextID;
} }
internal void DoHTTPGruntWork(BaseHttpServer server, Hashtable responsedata) internal void DoHTTPGruntWork(Hashtable responsedata)
{ {
OSHttpResponse response OSHttpResponse response
= new OSHttpResponse(new HttpResponse(HttpContext, Request), HttpContext); = new OSHttpResponse(new HttpResponse(HttpContext, Request), HttpContext);
byte[] buffer = server.DoHTTPGruntWork(responsedata, response); byte[] buffer = srvDoHTTPGruntWork(responsedata, response);
if(Request.Body.CanRead) if(Request.Body.CanRead)
Request.Body.Dispose(); Request.Body.Dispose();
@ -114,7 +114,119 @@ namespace OpenSim.Framework.Servers.HttpServer
PollServiceArgs.RequestsHandled++; PollServiceArgs.RequestsHandled++;
} }
internal void DoHTTPstop(BaseHttpServer server) internal byte[] srvDoHTTPGruntWork(Hashtable responsedata, OSHttpResponse response)
{
int responsecode;
string responseString = String.Empty;
byte[] responseData = null;
string contentType;
if (responsedata == null)
{
responsecode = 500;
responseString = "No response could be obtained";
contentType = "text/plain";
responsedata = new Hashtable();
}
else
{
try
{
//m_log.Info("[BASE HTTP SERVER]: Doing HTTP Grunt work with response");
responsecode = (int)responsedata["int_response_code"];
if (responsedata["bin_response_data"] != null)
responseData = (byte[])responsedata["bin_response_data"];
else
responseString = (string)responsedata["str_response_string"];
contentType = (string)responsedata["content_type"];
if (responseString == null)
responseString = String.Empty;
}
catch
{
responsecode = 500;
responseString = "No response could be obtained";
contentType = "text/plain";
responsedata = new Hashtable();
}
}
if (responsedata.ContainsKey("error_status_text"))
{
response.StatusDescription = (string)responsedata["error_status_text"];
}
if (responsedata.ContainsKey("http_protocol_version"))
{
response.ProtocolVersion = (string)responsedata["http_protocol_version"];
}
if (responsedata.ContainsKey("keepalive"))
{
bool keepalive = (bool)responsedata["keepalive"];
response.KeepAlive = keepalive;
}
// 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"]);
//Even though only one other part of the entire code uses HTTPHandlers, we shouldn't expect this
//and should check for NullReferenceExceptions
if (string.IsNullOrEmpty(contentType))
{
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)
{
response.RedirectLocation = (string)responsedata["str_redirect_location"];
response.StatusCode = responsecode;
}
response.AddHeader("Content-Type", contentType);
if (responsedata.ContainsKey("headers"))
{
Hashtable headerdata = (Hashtable)responsedata["headers"];
foreach (string header in headerdata.Keys)
response.AddHeader(header, headerdata[header].ToString());
}
byte[] buffer;
if (responseData != null)
{
buffer = responseData;
}
else
{
if (!(contentType.Contains("image")
|| contentType.Contains("x-shockwave-flash")
|| contentType.Contains("application/x-oar")
|| contentType.Contains("application/vnd.ll.mesh")))
{
// Text
buffer = Encoding.UTF8.GetBytes(responseString);
}
else
{
// Binary!
buffer = Convert.FromBase64String(responseString);
}
response.SendChunked = false;
response.ContentLength64 = buffer.Length;
response.ContentEncoding = Encoding.UTF8;
}
return buffer;
}
internal void DoHTTPstop()
{ {
OSHttpResponse response OSHttpResponse response
= new OSHttpResponse(new HttpResponse(HttpContext, Request), HttpContext); = new OSHttpResponse(new HttpResponse(HttpContext, Request), HttpContext);

View File

@ -41,8 +41,6 @@ namespace OpenSim.Framework.Servers.HttpServer
{ {
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private readonly BaseHttpServer m_server;
private Dictionary<int, Queue<PollServiceHttpRequest>> m_bycontext; private Dictionary<int, Queue<PollServiceHttpRequest>> m_bycontext;
private BlockingCollection<PollServiceHttpRequest> m_requests = new BlockingCollection<PollServiceHttpRequest>(); private BlockingCollection<PollServiceHttpRequest> m_requests = new BlockingCollection<PollServiceHttpRequest>();
private ConcurrentQueue<PollServiceHttpRequest> m_retryRequests = new ConcurrentQueue<PollServiceHttpRequest>(); private ConcurrentQueue<PollServiceHttpRequest> m_retryRequests = new ConcurrentQueue<PollServiceHttpRequest>();
@ -56,9 +54,8 @@ namespace OpenSim.Framework.Servers.HttpServer
private SmartThreadPool m_threadPool; private SmartThreadPool m_threadPool;
public PollServiceRequestManager( public PollServiceRequestManager(
BaseHttpServer pSrv, bool performResponsesAsync, uint pWorkerThreadCount, int pTimeout) bool performResponsesAsync, uint pWorkerThreadCount, int pTimeout)
{ {
m_server = pSrv;
m_WorkerThreadCount = pWorkerThreadCount; m_WorkerThreadCount = pWorkerThreadCount;
m_workerThreads = new Thread[m_WorkerThreadCount]; m_workerThreads = new Thread[m_WorkerThreadCount];
@ -77,6 +74,8 @@ namespace OpenSim.Framework.Servers.HttpServer
public void Start() public void Start()
{ {
if(m_running)
return;
m_running = true; m_running = true;
m_threadPool.Start(); m_threadPool.Start();
//startup worker threads //startup worker threads
@ -85,7 +84,7 @@ namespace OpenSim.Framework.Servers.HttpServer
m_workerThreads[i] m_workerThreads[i]
= WorkManager.StartThread( = WorkManager.StartThread(
PoolWorkerJob, PoolWorkerJob,
string.Format("PollServiceWorkerThread {0}:{1}", i, m_server.Port), string.Format("PollServiceWorkerThread {0}", i),
ThreadPriority.Normal, ThreadPriority.Normal,
true, true,
false, false,
@ -95,7 +94,7 @@ namespace OpenSim.Framework.Servers.HttpServer
m_retrysThread = WorkManager.StartThread( m_retrysThread = WorkManager.StartThread(
this.CheckRetries, this.CheckRetries,
string.Format("PollServiceWatcherThread:{0}", m_server.Port), string.Format("PollServiceWatcherThread"),
ThreadPriority.Normal, ThreadPriority.Normal,
true, true,
true, true,
@ -183,6 +182,9 @@ namespace OpenSim.Framework.Servers.HttpServer
public void Stop() public void Stop()
{ {
if(!m_running)
return;
m_running = false; m_running = false;
Thread.Sleep(100); // let the world move Thread.Sleep(100); // let the world move
@ -202,7 +204,7 @@ namespace OpenSim.Framework.Servers.HttpServer
try try
{ {
while(m_retryRequests.TryDequeue(out req)) while(m_retryRequests.TryDequeue(out req))
req.DoHTTPstop(m_server); req.DoHTTPstop();
} }
catch catch
{ {
@ -211,7 +213,7 @@ namespace OpenSim.Framework.Servers.HttpServer
try try
{ {
while(m_requests.TryTake(out req, 0)) while(m_requests.TryTake(out req, 0))
req.DoHTTPstop(m_server); req.DoHTTPstop();
} }
catch catch
{ {
@ -266,7 +268,7 @@ namespace OpenSim.Framework.Servers.HttpServer
try try
{ {
Hashtable responsedata = nreq.PollServiceArgs.GetEvents(nreq.RequestID, nreq.PollServiceArgs.Id); Hashtable responsedata = nreq.PollServiceArgs.GetEvents(nreq.RequestID, nreq.PollServiceArgs.Id);
nreq.DoHTTPGruntWork(m_server, responsedata); nreq.DoHTTPGruntWork(responsedata);
} }
catch (ObjectDisposedException) { } catch (ObjectDisposedException) { }
finally finally
@ -286,8 +288,7 @@ namespace OpenSim.Framework.Servers.HttpServer
{ {
try try
{ {
nreq.DoHTTPGruntWork(m_server, nreq.DoHTTPGruntWork(nreq.PollServiceArgs.NoEvents(nreq.RequestID, nreq.PollServiceArgs.Id));
nreq.PollServiceArgs.NoEvents(nreq.RequestID, nreq.PollServiceArgs.Id));
} }
catch (ObjectDisposedException) {} catch (ObjectDisposedException) {}
finally finally

View File

@ -87,13 +87,14 @@ namespace OpenSim.Framework.Servers
set set
{ {
lock (m_Servers) lock (m_Servers)
{
if (!m_Servers.ContainsValue(value)) if (!m_Servers.ContainsValue(value))
throw new Exception("HTTP server must already have been registered to be set as the main instance"); throw new Exception("HTTP server must already have been registered to be set as the main instance");
instance = value; instance = value;
} }
} }
}
public static BaseHttpServer UnSecureInstance public static BaseHttpServer UnSecureInstance
{ {
@ -372,14 +373,14 @@ namespace OpenSim.Framework.Servers
public static void Stop() public static void Stop()
{ {
PollServiceRequestManager pool = null;
lock (m_Servers) lock (m_Servers)
{ {
foreach (BaseHttpServer httpServer in m_Servers.Values) foreach (BaseHttpServer httpServer in m_Servers.Values)
{ {
httpServer.Stop(); httpServer.Stop(true);
} }
} }
} }
} }
} }