status: work-in-progress, non-functional

fleshing out OSHttpRequestPump code.
0.6.0-stable
Dr Scofield 2008-06-27 15:57:33 +00:00
parent 6175021300
commit 92e04ea587
3 changed files with 165 additions and 0 deletions

View File

@ -144,6 +144,11 @@ namespace OpenSim.Framework.Servers
get { return _queryString; } get { return _queryString; }
} }
public HttpRequest HttpRequest
{
get { return _request; }
}
public OSHttpRequest() public OSHttpRequest()
{ {
} }

View File

@ -26,6 +26,13 @@
*/ */
using System; using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Net;
using System.Reflection;
using System.Text.RegularExpressions;
using System.Threading;
using log4net;
using HttpServer; using HttpServer;
namespace OpenSim.Framework.Servers namespace OpenSim.Framework.Servers
@ -39,11 +46,29 @@ namespace OpenSim.Framework.Servers
/// </summary> /// </summary>
public class OSHttpRequestPump public class OSHttpRequestPump
{ {
private static readonly ILog _log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
protected OSHttpServer _server; protected OSHttpServer _server;
protected OSHttpRequestQueue _queue; protected OSHttpRequestQueue _queue;
protected Thread _engine;
private int _id;
public string EngineID
{
get { return String.Format("{0}-{1}", _server.EngineID, _id); }
}
public OSHttpRequestPump() public OSHttpRequestPump()
{ {
_engine = new Thread(new ThreadStart(Engine));
_engine.Name = EngineID;
_engine.IsBackground = true;
_engine.Start();
ThreadTracker.Add(_engine);
} }
public static OSHttpRequestPump[] Pumps(OSHttpServer server, OSHttpRequestQueue queue, int poolSize) public static OSHttpRequestPump[] Pumps(OSHttpServer server, OSHttpRequestQueue queue, int poolSize)
@ -53,9 +78,140 @@ namespace OpenSim.Framework.Servers
{ {
pumps[i]._server = server; pumps[i]._server = server;
pumps[i]._queue = queue; pumps[i]._queue = queue;
pumps[i]._id = i;
} }
return pumps; return pumps;
} }
public void Start()
{
_engine = new Thread(new ThreadStart(Engine));
_engine.Name = EngineID;
_engine.IsBackground = true;
_engine.Start();
ThreadTracker.Add(_engine);
}
public void Engine()
{
OSHttpRequest req = null;
try {
while (true)
{
// get job to do
req = _queue.Dequeue();
// get list of registered handlers
List<OSHttpHandler> handlers = _server.OSHttpHandlers;
// prune list and sort from most specific to least
// specific
handlers = MatchHandlers(req, handlers);
// process req
foreach(OSHttpHandler h in handlers)
{
OSHttpHandlerResult rc = h.Process(req);
// handler did not process the request, try
// next handler
if (OSHttpHandlerResult.Pass == rc) continue;
// handler is taking over processing of
// request, we are done
if (OSHttpHandlerResult.Detached == rc) break;
// request was handled, we need to clean up
// TODO: cleanup :-)
break;
}
}
}
catch (Exception e)
{
_log.DebugFormat("[{0}] something went wrong: {1}", EngineID, e.ToString());
_log.ErrorFormat("[{0}] something went wrong: {1}, terminating this pump", EngineID, e.Message);
}
}
protected List<OSHttpHandler> MatchHandlers(OSHttpRequest req, List<OSHttpHandler> handlers)
{
Dictionary<OSHttpHandler, int> scoredHandlers = new Dictionary<OSHttpHandler, int>();
foreach (OSHttpHandler h in handlers)
{
Regex pathRegex = h.Path;
Dictionary<string, Regex> headerRegexs = h.Headers;
Regex endPointsRegex = h.IPEndPointWhitelist;
int pathMatch = 0;
int headersMatch = 0;
// first, check whether IPEndPointWhitelist applies
// and, if it does, whether client is on that white
// list.
if (null != endPointsRegex)
{
// TODO: following code requires code changes to
// HttpServer.HttpRequest
// IPEndPoint remote = HttpServer.HttpRequest.RemoteIPEndPoint;
// Match epm = endPointsRegex.Match(remote.ToString());
// if (!epm.Success) continue;
}
// whitelist ok, now check path
if (null != pathRegex)
{
Match m = pathRegex.Match(req.HttpRequest.Uri.AbsolutePath);
if (!m.Success) continue;
scoredHandlers[h] = m.ToString().Length;
}
// whitelist & path ok, now check headers
if (null != headerRegexs)
{
// go through all header Regexs and evaluate
// match:
// if header field not present or does not match:
// remove handler from scoredHandlers
// continue
// else:
// add increment headersMatch
NameValueCollection headers = req.HttpRequest.Headers;
foreach (string tag in headerRegexs.Keys)
{
if (null != headers[tag])
{
Match hm = headerRegexs[tag].Match(headers[tag]);
if (hm.Success) {
headersMatch++;
continue;
}
}
scoredHandlers.Remove(h);
break;
}
// check whether h got kicked out
if (!scoredHandlers.ContainsKey(h)) continue;
scoredHandlers[h] += headersMatch;
}
}
List<OSHttpHandler> matchingHandlers = new List<OSHttpHandler>(scoredHandlers.Keys);
matchingHandlers.Sort(delegate(OSHttpHandler x, OSHttpHandler y)
{
return scoredHandlers[x] - scoredHandlers[y];
});
return matchingHandlers;
}
} }
} }

View File

@ -151,6 +151,10 @@ namespace OpenSim.Framework.Servers
_engine.Start(); _engine.Start();
ThreadTracker.Add(_engine); ThreadTracker.Add(_engine);
// start the pumps...
for (int i = 0; i < _pumps.Length; i++)
_pumps[i].Start();
} }
/// <summary> /// <summary>