diff --git a/OpenSim/Framework/Servers/OSHttpRequest.cs b/OpenSim/Framework/Servers/OSHttpRequest.cs index 530c91a6d9..10614b230a 100644 --- a/OpenSim/Framework/Servers/OSHttpRequest.cs +++ b/OpenSim/Framework/Servers/OSHttpRequest.cs @@ -144,6 +144,11 @@ namespace OpenSim.Framework.Servers get { return _queryString; } } + public HttpRequest HttpRequest + { + get { return _request; } + } + public OSHttpRequest() { } diff --git a/OpenSim/Framework/Servers/OSHttpRequestPump.cs b/OpenSim/Framework/Servers/OSHttpRequestPump.cs index 6214ab0502..f04134cfc5 100644 --- a/OpenSim/Framework/Servers/OSHttpRequestPump.cs +++ b/OpenSim/Framework/Servers/OSHttpRequestPump.cs @@ -26,6 +26,13 @@ */ 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; namespace OpenSim.Framework.Servers @@ -39,11 +46,29 @@ namespace OpenSim.Framework.Servers /// public class OSHttpRequestPump { + private static readonly ILog _log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + protected OSHttpServer _server; protected OSHttpRequestQueue _queue; + protected Thread _engine; + private int _id; + + public string EngineID + { + get { return String.Format("{0}-{1}", _server.EngineID, _id); } + } + + 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) @@ -53,9 +78,140 @@ namespace OpenSim.Framework.Servers { pumps[i]._server = server; pumps[i]._queue = queue; + pumps[i]._id = i; } 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 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 MatchHandlers(OSHttpRequest req, List handlers) + { + Dictionary scoredHandlers = new Dictionary(); + + foreach (OSHttpHandler h in handlers) + { + Regex pathRegex = h.Path; + Dictionary 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 matchingHandlers = new List(scoredHandlers.Keys); + matchingHandlers.Sort(delegate(OSHttpHandler x, OSHttpHandler y) + { + return scoredHandlers[x] - scoredHandlers[y]; + }); + + return matchingHandlers; + } + } } diff --git a/OpenSim/Framework/Servers/OSHttpServer.cs b/OpenSim/Framework/Servers/OSHttpServer.cs index 169ce13868..aade003626 100644 --- a/OpenSim/Framework/Servers/OSHttpServer.cs +++ b/OpenSim/Framework/Servers/OSHttpServer.cs @@ -151,6 +151,10 @@ namespace OpenSim.Framework.Servers _engine.Start(); ThreadTracker.Add(_engine); + + // start the pumps... + for (int i = 0; i < _pumps.Length; i++) + _pumps[i].Start(); } ///