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 OpenMetaverse.StructuredData;
using CoolHTTPListener = HttpServer.HttpListener;
using HttpListener = System.Net.HttpListener;
using LogPrio = HttpServer.LogPrio;
using OpenSim.Framework.Monitoring;
using System.IO.Compression;
using System.Security.Cryptography;
using OpenSim.Framework.Servers;
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 HttpServerLogWriter httpserverlog = new HttpServerLogWriter();
private static Encoding UTF8NoBOM = new System.Text.UTF8Encoding(false);
public static PollServiceRequestManager m_pollServiceManager;
private static object m_generalLock = new object();
/// <summary>
/// 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;
public PollServiceRequestManager PollServiceRequestManager { get; private set; }
public string Protocol
{
@ -249,46 +250,46 @@ namespace OpenSim.Framework.Servers.HttpServer
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);
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)
if (indx == dnslen)
return true; // just * ?
if(indx > dnslen - 2)
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);
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;
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);
}
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)
{
@ -527,7 +528,6 @@ namespace OpenSim.Framework.Servers.HttpServer
public void OnRequest(object source, RequestEventArgs args)
{
RequestNumber++;
try
{
IHttpClientContext context = (IHttpClientContext)source;
@ -576,7 +576,7 @@ namespace OpenSim.Framework.Servers.HttpServer
psEvArgs.Request(psreq.RequestID, keysvals);
}
PollServiceRequestManager.Enqueue(psreq);
m_pollServiceManager.Enqueue(psreq);
}
else
{
@ -616,16 +616,6 @@ namespace OpenSim.Framework.Servers.HttpServer
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>
/// This methods is the start of incoming HTTP request handling.
/// </summary>
@ -2036,7 +2026,7 @@ namespace OpenSim.Framework.Servers.HttpServer
public void Start()
{
Start(true,true);
Start(true, true);
}
/// <summary>
@ -2085,11 +2075,14 @@ namespace OpenSim.Framework.Servers.HttpServer
//m_httpListener.Start();
m_httpListener2.Start(64);
// Long Poll Service Manager with 3 worker threads a 25 second timeout for no events
if(runPool)
lock(m_generalLock)
{
PollServiceRequestManager = new PollServiceRequestManager(this, performPollResponsesAsync, 2, 25000);
PollServiceRequestManager.Start();
if (runPool)
{
if(m_pollServiceManager == null)
m_pollServiceManager = new PollServiceRequestManager(performPollResponsesAsync, 2, 25000);
m_pollServiceManager.Start();
}
}
HTTPDRunning = true;
@ -2143,27 +2136,22 @@ namespace OpenSim.Framework.Servers.HttpServer
if (source.ToString() == "HttpServer.HttpListener" && exception.ToString().StartsWith("Mono.Security.Protocol.Tls.TlsException"))
return;
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;
StatsManager.DeregisterStat(m_requestsProcessedStat);
try
{
if(PollServiceRequestManager != null)
PollServiceRequestManager.Stop();
lock(m_generalLock)
{
if (stopPool && m_pollServiceManager != null)
m_pollServiceManager.Stop();
}
m_httpListener2.ExceptionThrown -= httpServerException;
//m_httpListener2.DisconnectHandler = null;

View File

@ -79,12 +79,12 @@ namespace OpenSim.Framework.Servers.HttpServer
contextHash = HttpContext.contextID;
}
internal void DoHTTPGruntWork(BaseHttpServer server, Hashtable responsedata)
internal void DoHTTPGruntWork(Hashtable responsedata)
{
OSHttpResponse response
= new OSHttpResponse(new HttpResponse(HttpContext, Request), HttpContext);
byte[] buffer = server.DoHTTPGruntWork(responsedata, response);
byte[] buffer = srvDoHTTPGruntWork(responsedata, response);
if(Request.Body.CanRead)
Request.Body.Dispose();
@ -114,7 +114,119 @@ namespace OpenSim.Framework.Servers.HttpServer
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
= 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 readonly BaseHttpServer m_server;
private Dictionary<int, Queue<PollServiceHttpRequest>> m_bycontext;
private BlockingCollection<PollServiceHttpRequest> m_requests = new BlockingCollection<PollServiceHttpRequest>();
private ConcurrentQueue<PollServiceHttpRequest> m_retryRequests = new ConcurrentQueue<PollServiceHttpRequest>();
@ -56,9 +54,8 @@ namespace OpenSim.Framework.Servers.HttpServer
private SmartThreadPool m_threadPool;
public PollServiceRequestManager(
BaseHttpServer pSrv, bool performResponsesAsync, uint pWorkerThreadCount, int pTimeout)
bool performResponsesAsync, uint pWorkerThreadCount, int pTimeout)
{
m_server = pSrv;
m_WorkerThreadCount = pWorkerThreadCount;
m_workerThreads = new Thread[m_WorkerThreadCount];
@ -77,6 +74,8 @@ namespace OpenSim.Framework.Servers.HttpServer
public void Start()
{
if(m_running)
return;
m_running = true;
m_threadPool.Start();
//startup worker threads
@ -85,7 +84,7 @@ namespace OpenSim.Framework.Servers.HttpServer
m_workerThreads[i]
= WorkManager.StartThread(
PoolWorkerJob,
string.Format("PollServiceWorkerThread {0}:{1}", i, m_server.Port),
string.Format("PollServiceWorkerThread {0}", i),
ThreadPriority.Normal,
true,
false,
@ -95,7 +94,7 @@ namespace OpenSim.Framework.Servers.HttpServer
m_retrysThread = WorkManager.StartThread(
this.CheckRetries,
string.Format("PollServiceWatcherThread:{0}", m_server.Port),
string.Format("PollServiceWatcherThread"),
ThreadPriority.Normal,
true,
true,
@ -183,6 +182,9 @@ namespace OpenSim.Framework.Servers.HttpServer
public void Stop()
{
if(!m_running)
return;
m_running = false;
Thread.Sleep(100); // let the world move
@ -202,7 +204,7 @@ namespace OpenSim.Framework.Servers.HttpServer
try
{
while(m_retryRequests.TryDequeue(out req))
req.DoHTTPstop(m_server);
req.DoHTTPstop();
}
catch
{
@ -211,7 +213,7 @@ namespace OpenSim.Framework.Servers.HttpServer
try
{
while(m_requests.TryTake(out req, 0))
req.DoHTTPstop(m_server);
req.DoHTTPstop();
}
catch
{
@ -266,7 +268,7 @@ namespace OpenSim.Framework.Servers.HttpServer
try
{
Hashtable responsedata = nreq.PollServiceArgs.GetEvents(nreq.RequestID, nreq.PollServiceArgs.Id);
nreq.DoHTTPGruntWork(m_server, responsedata);
nreq.DoHTTPGruntWork(responsedata);
}
catch (ObjectDisposedException) { }
finally
@ -286,8 +288,7 @@ namespace OpenSim.Framework.Servers.HttpServer
{
try
{
nreq.DoHTTPGruntWork(m_server,
nreq.PollServiceArgs.NoEvents(nreq.RequestID, nreq.PollServiceArgs.Id));
nreq.DoHTTPGruntWork(nreq.PollServiceArgs.NoEvents(nreq.RequestID, nreq.PollServiceArgs.Id));
}
catch (ObjectDisposedException) {}
finally

View File

@ -87,14 +87,15 @@ namespace OpenSim.Framework.Servers
set
{
lock (m_Servers)
{
if (!m_Servers.ContainsValue(value))
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
{
get { return unsecureinstance; }
@ -372,14 +373,14 @@ namespace OpenSim.Framework.Servers
public static void Stop()
{
PollServiceRequestManager pool = null;
lock (m_Servers)
{
foreach (BaseHttpServer httpServer in m_Servers.Values)
{
httpServer.Stop();
httpServer.Stop(true);
}
}
}
}
}