bestMatch.Length)
+ {
+ // You have to specifically register for '/' and to get it, you must specificaly request it
+ //
+ if (pattern == "/" && searchquery == "/" || pattern != "/")
+ bestMatch = pattern;
+ }
+ }
+ }
+
+ if (String.IsNullOrEmpty(bestMatch))
+ {
+ llsdHandler = null;
+ return false;
+ }
+ else
+ {
+ llsdHandler = m_llsdHandlers[bestMatch];
+ return true;
+ }
+ }
+
+ private OSDMap GenerateNoLLSDHandlerResponse()
+ {
+ OSDMap map = new OSDMap();
+ map["reason"] = OSD.FromString("LLSDRequest");
+ map["message"] = OSD.FromString("No handler registered for LLSD Requests");
+ map["login"] = OSD.FromString("false");
+ return map;
+ }
+ ///
+ /// A specific agent handler was provided. Such a handler is expecetd to have an
+ /// intimate, and highly specific relationship with the client. Consequently,
+ /// nothing is done here.
+ ///
+ ///
+ ///
+ ///
+
+ private bool HandleAgentRequest(IHttpAgentHandler handler, OSHttpRequest request, OSHttpResponse response)
+ {
+ // In the case of REST, then handler is responsible for ALL aspects of
+ // the request/response handling. Nothing is done here, not even encoding.
+
+ try
+ {
+ return handler.Handle(request, response);
+ }
+ catch (Exception e)
+ {
+ // If the handler did in fact close the stream, then this will blow
+ // chunks. So that that doesn't disturb anybody we throw away any
+ // and all exceptions raised. We've done our best to release the
+ // client.
+ try
+ {
+ m_log.Warn("[HTTP-AGENT]: Error - " + e.Message);
+ response.SendChunked = false;
+ response.KeepAlive = true;
+ response.StatusCode = (int)OSHttpStatusCode.ServerErrorInternalError;
+ //response.OutputStream.Close();
+ try
+ {
+ response.Send();
+ }
+ catch (SocketException f)
+ {
+ // This has to be here to prevent a Linux/Mono crash
+ m_log.WarnFormat(
+ "[BASE HTTP SERVER]: XmlRpcRequest issue {0}.\nNOTE: this may be spurious on Linux.", f);
+ }
+ }
+ catch(Exception)
+ {
+ }
+ }
+
+ // Indicate that the request has been "handled"
+
+ return true;
+
+ }
+
+ public void HandleHTTPRequest(OSHttpRequest request, OSHttpResponse response)
+ {
+ switch (request.HttpMethod)
+ {
+ case "OPTIONS":
+ response.StatusCode = (int)OSHttpStatusCode.SuccessOk;
+ return;
+
+ default:
+ HandleContentVerbs(request, response);
+ return;
+ }
+ }
+
+ private void HandleContentVerbs(OSHttpRequest request, OSHttpResponse response)
+ {
+ // This is a test. There's a workable alternative.. as this way sucks.
+ // We'd like to put this into a text file parhaps that's easily editable.
+ //
+ // For this test to work, I used the following secondlife.exe parameters
+ // "C:\Program Files\SecondLifeWindLight\SecondLifeWindLight.exe" -settings settings_windlight.xml -channel "Second Life WindLight" -set SystemLanguage en-us -loginpage http://10.1.1.2:8002/?show_login_form=TRUE -loginuri http://10.1.1.2:8002 -user 10.1.1.2
+ //
+ // Even after all that, there's still an error, but it's a start.
+ //
+ // I depend on show_login_form being in the secondlife.exe parameters to figure out
+ // to display the form, or process it.
+ // a better way would be nifty.
+
+ Stream requestStream = request.InputStream;
+
+ Encoding encoding = Encoding.UTF8;
+ StreamReader reader = new StreamReader(requestStream, encoding);
+
+ string requestBody = reader.ReadToEnd();
+ // avoid warning for now
+ reader.ReadToEnd();
+ reader.Close();
+ requestStream.Close();
+
+ Hashtable keysvals = new Hashtable();
+ Hashtable headervals = new Hashtable();
+
+ Hashtable requestVars = new Hashtable();
+
+ string host = String.Empty;
+
+ string[] querystringkeys = request.QueryString.AllKeys;
+ string[] rHeaders = request.Headers.AllKeys;
+
+ keysvals.Add("body", requestBody);
+ keysvals.Add("uri", request.RawUrl);
+ keysvals.Add("content-type", request.ContentType);
+ keysvals.Add("http-method", request.HttpMethod);
+
+ foreach (string queryname in querystringkeys)
+ {
+ keysvals.Add(queryname, request.QueryString[queryname]);
+ requestVars.Add(queryname, keysvals[queryname]);
+ }
+
+ foreach (string headername in rHeaders)
+ {
+ //m_log.Warn("[HEADER]: " + headername + "=" + request.Headers[headername]);
+ headervals[headername] = request.Headers[headername];
+ }
+
+ if (headervals.Contains("Host"))
+ {
+ host = (string)headervals["Host"];
+ }
+
+ keysvals.Add("headers",headervals);
+ keysvals.Add("querystringkeys", querystringkeys);
+ keysvals.Add("requestvars", requestVars);
+
+ if (keysvals.Contains("method"))
+ {
+ //m_log.Warn("[HTTP]: Contains Method");
+ string method = (string) keysvals["method"];
+ //m_log.Warn("[HTTP]: " + requestBody);
+ GenericHTTPMethod requestprocessor;
+ bool foundHandler = TryGetHTTPHandler(method, out requestprocessor);
+ if (foundHandler)
+ {
+ Hashtable responsedata1 = requestprocessor(keysvals);
+ DoHTTPGruntWork(responsedata1,response);
+
+ //SendHTML500(response);
+ }
+ else
+ {
+ //m_log.Warn("[HTTP]: Handler Not Found");
+ SendHTML404(response, host);
+ }
+ }
+ else
+ {
+
+ GenericHTTPMethod requestprocessor;
+ bool foundHandler = TryGetHTTPHandlerPathBased(request.RawUrl, out requestprocessor);
+ if (foundHandler)
+ {
+ Hashtable responsedata2 = requestprocessor(keysvals);
+ DoHTTPGruntWork(responsedata2, response);
+
+ //SendHTML500(response);
+ }
+ else
+ {
+ //m_log.Warn("[HTTP]: Handler Not Found");
+ SendHTML404(response, host);
+ }
+ }
+ }
+
+ private bool TryGetHTTPHandlerPathBased(string path, out GenericHTTPMethod httpHandler)
+ {
+ httpHandler = null;
+ // Pull out the first part of the path
+ // splitting the path by '/' means we'll get the following return..
+ // {0}/{1}/{2}
+ // where {0} isn't something we really control 100%
+
+ string[] pathbase = path.Split('/');
+ string searchquery = "/";
+
+ if (pathbase.Length < 1)
+ return false;
+
+ for (int i = 1; i < pathbase.Length; i++)
+ {
+ searchquery += pathbase[i];
+ if (pathbase.Length - 1 != i)
+ searchquery += "/";
+ }
+
+ // while the matching algorithm below doesn't require it, we're expecting a query in the form
+ //
+ // [] = optional
+ // /resource/UUID/action[/action]
+ //
+ // now try to get the closest match to the reigstered path
+ // at least for OGP, registered path would probably only consist of the /resource/
+
+ string bestMatch = null;
+
+// m_log.DebugFormat(
+// "[BASE HTTP HANDLER]: TryGetHTTPHandlerPathBased() looking for HTTP handler to match {0}", searchquery);
+
+ lock (m_HTTPHandlers)
+ {
+ foreach (string pattern in m_HTTPHandlers.Keys)
+ {
+ if (searchquery.ToLower().StartsWith(pattern.ToLower()))
+ {
+ if (String.IsNullOrEmpty(bestMatch) || searchquery.Length > bestMatch.Length)
+ {
+ // You have to specifically register for '/' and to get it, you must specificaly request it
+ //
+ if (pattern == "/" && searchquery == "/" || pattern != "/")
+ bestMatch = pattern;
+ }
+ }
+ }
+
+ if (String.IsNullOrEmpty(bestMatch))
+ {
+ httpHandler = null;
+ return false;
+ }
+ else
+ {
+ if (bestMatch == "/" && searchquery != "/")
+ return false;
+
+ httpHandler = m_HTTPHandlers[bestMatch];
+ return true;
+ }
+ }
+ }
+
+ private static void DoHTTPGruntWork(Hashtable responsedata, OSHttpResponse response)
+ {
+ //m_log.Info("[BASE HTTP SERVER]: Doing HTTP Grunt work with response");
+ int responsecode = (int)responsedata["int_response_code"];
+ string responseString = (string)responsedata["str_response_string"];
+ string contentType = (string)responsedata["content_type"];
+
+ 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;
+
+ }
+ //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);
+
+ byte[] buffer;
+
+ if (!(contentType.Contains("image")
+ || contentType.Contains("x-shockwave-flash")
+ || contentType.Contains("application/x-oar")))
+ {
+ // Text
+ buffer = Encoding.UTF8.GetBytes(responseString);
+ }
+ else
+ {
+ // Binary!
+ buffer = Convert.FromBase64String(responseString);
+ }
+
+ response.SendChunked = false;
+ response.ContentLength64 = buffer.Length;
+ response.ContentEncoding = Encoding.UTF8;
+
+ try
+ {
+ response.OutputStream.Write(buffer, 0, buffer.Length);
+ }
+ catch (Exception ex)
+ {
+ m_log.Warn("[HTTPD]: Error - " + ex.Message);
+ }
+ finally
+ {
+ //response.OutputStream.Close();
+ try
+ {
+ response.Send();
+ }
+ catch (SocketException e)
+ {
+ // This has to be here to prevent a Linux/Mono crash
+ m_log.WarnFormat("[BASE HTTP SERVER] XmlRpcRequest issue {0}.\nNOTE: this may be spurious on Linux.", e);
+ }
+ }
+ }
+
+ public void SendHTML404(OSHttpResponse response, string host)
+ {
+ // I know this statuscode is dumb, but the client doesn't respond to 404s and 500s
+ response.StatusCode = 404;
+ response.AddHeader("Content-type", "text/html");
+
+ string responseString = GetHTTP404(host);
+ byte[] buffer = Encoding.UTF8.GetBytes(responseString);
+
+ response.SendChunked = false;
+ response.ContentLength64 = buffer.Length;
+ response.ContentEncoding = Encoding.UTF8;
+
+ try
+ {
+ response.OutputStream.Write(buffer, 0, buffer.Length);
+ }
+ catch (Exception ex)
+ {
+ m_log.Warn("[HTTPD]: Error - " + ex.Message);
+ }
+ finally
+ {
+ //response.OutputStream.Close();
+ try
+ {
+ response.Send();
+ }
+ catch (SocketException e)
+ {
+ // This has to be here to prevent a Linux/Mono crash
+ m_log.WarnFormat("[BASE HTTP SERVER] XmlRpcRequest issue {0}.\nNOTE: this may be spurious on Linux.", e);
+ }
+ }
+ }
+
+ public void SendHTML500(OSHttpResponse response)
+ {
+ // I know this statuscode is dumb, but the client doesn't respond to 404s and 500s
+ response.StatusCode = (int)OSHttpStatusCode.SuccessOk;
+ response.AddHeader("Content-type", "text/html");
+
+ string responseString = GetHTTP500();
+ byte[] buffer = Encoding.UTF8.GetBytes(responseString);
+
+ response.SendChunked = false;
+ response.ContentLength64 = buffer.Length;
+ response.ContentEncoding = Encoding.UTF8;
+ try
+ {
+ response.OutputStream.Write(buffer, 0, buffer.Length);
+ }
+ catch (Exception ex)
+ {
+ m_log.Warn("[HTTPD]: Error - " + ex.Message);
+ }
+ finally
+ {
+ //response.OutputStream.Close();
+ try
+ {
+ response.Send();
+ }
+ catch (SocketException e)
+ {
+ // This has to be here to prevent a Linux/Mono crash
+ m_log.WarnFormat("[BASE HTTP SERVER] XmlRpcRequest issue {0}.\nNOTE: this may be spurious on Linux.", e);
+ }
+ }
+ }
+
+ public void Start()
+ {
+ m_log.Info("[HTTPD]: Starting up HTTP Server");
+
+ //m_workerThread = new Thread(new ThreadStart(StartHTTP));
+ //m_workerThread.Name = "HttpThread";
+ //m_workerThread.IsBackground = true;
+ //m_workerThread.Start();
+ //ThreadTracker.Add(m_workerThread);
+ StartHTTP();
+ }
+
+ private void StartHTTP()
+ {
+ try
+ {
+ m_log.Info("[HTTPD]: Spawned main thread OK");
+ //m_httpListener = new HttpListener();
+ NotSocketErrors = 0;
+ if (!m_ssl)
+ {
+ //m_httpListener.Prefixes.Add("http://+:" + m_port + "/");
+ //m_httpListener.Prefixes.Add("http://10.1.1.5:" + m_port + "/");
+ m_httpListener2 = new CoolHTTPListener(IPAddress.Any, (int)m_port);
+ m_httpListener2.ExceptionThrown += httpServerException;
+ m_httpListener2.LogWriter = httpserverlog;
+
+ // Uncomment this line in addition to those in HttpServerLogWriter
+ // if you want more detailed trace information from the HttpServer
+ //m_httpListener2.UseTraceLogs = true;
+
+ m_httpListener2.DisconnectHandler = httpServerDisconnectMonitor;
+ }
+ else
+ {
+ //m_httpListener.Prefixes.Add("https://+:" + (m_sslport) + "/");
+ //m_httpListener.Prefixes.Add("http://+:" + m_port + "/");
+ }
+
+ m_httpListener2.RequestHandler += OnHandleRequestIOThread;
+ //m_httpListener.Start();
+ m_httpListener2.Start(64);
+ HTTPDRunning = true;
+
+ //HttpListenerContext context;
+ //while (true)
+ //{
+ // context = m_httpListener.GetContext();
+ // ThreadPool.QueueUserWorkItem(new WaitCallback(HandleRequest), context);
+ // }
+ }
+ catch (Exception e)
+ {
+ m_log.Error("[HTTPD]: Error - " + e.Message);
+ m_log.Error("[HTTPD]: Tip: Do you have permission to listen on port " + m_port + ", " + m_sslport + "?");
+
+ // We want this exception to halt the entire server since in current configurations we aren't too
+ // useful without inbound HTTP.
+ throw e;
+ }
+ }
+
+ public void httpServerDisconnectMonitor(IHttpClientContext source, SocketError err)
+ {
+ switch (err)
+ {
+ case SocketError.NotSocket:
+ NotSocketErrors++;
+
+ break;
+ }
+ }
+
+ public void httpServerException(object source, Exception exception)
+ {
+ m_log.ErrorFormat("[HTTPSERVER]: {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()
+ {
+ HTTPDRunning = false;
+ m_httpListener2.ExceptionThrown -= httpServerException;
+ m_httpListener2.DisconnectHandler = null;
+
+ m_httpListener2.LogWriter = null;
+ m_httpListener2.RequestHandler -= OnHandleRequestIOThread;
+
+ m_httpListener2.Stop();
+ }
+
+ public void RemoveStreamHandler(string httpMethod, string path)
+ {
+ string handlerKey = GetHandlerKey(httpMethod, path);
+
+ //m_log.DebugFormat("[BASE HTTP SERVER]: Removing handler key {0}", handlerKey);
+
+ lock (m_streamHandlers) m_streamHandlers.Remove(handlerKey);
+ }
+
+ public void RemoveHTTPHandler(string httpMethod, string path)
+ {
+ lock (m_HTTPHandlers)
+ {
+ if (httpMethod != null && httpMethod.Length == 0)
+ {
+ m_HTTPHandlers.Remove(path);
+ return;
+ }
+
+ m_HTTPHandlers.Remove(GetHandlerKey(httpMethod, path));
+ }
+ }
+
+ public bool RemoveAgentHandler(string agent, IHttpAgentHandler handler)
+ {
+ try
+ {
+ if (handler == m_agentHandlers[agent])
+ {
+ m_agentHandlers.Remove(agent);
+ return true;
+ }
+ }
+ catch(KeyNotFoundException)
+ {
+ }
+
+ return false;
+ }
+
+ public bool RemoveLLSDHandler(string path, LLSDMethod handler)
+ {
+ try
+ {
+ if (handler == m_llsdHandlers[path])
+ {
+ m_llsdHandlers.Remove(path);
+ return true;
+ }
+ }
+ catch (KeyNotFoundException)
+ {
+ // This is an exception to prevent crashing because of invalid code
+ }
+
+ return false;
+ }
+
+ public string GetHTTP404(string host)
+ {
+ string file = Path.Combine(".", "http_404.html");
+ if (!File.Exists(file))
+ return getDefaultHTTP404(host);
+
+ StreamReader sr = File.OpenText(file);
+ string result = sr.ReadToEnd();
+ sr.Close();
+ return result;
+ }
+
+ public string GetHTTP500()
+ {
+ string file = Path.Combine(".", "http_500.html");
+ if (!File.Exists(file))
+ return getDefaultHTTP500();
+
+ StreamReader sr = File.OpenText(file);
+ string result = sr.ReadToEnd();
+ sr.Close();
+ return result;
+ }
+
+ // Fallback HTTP responses in case the HTTP error response files don't exist
+ private static string getDefaultHTTP404(string host)
+ {
+ return "404 Page not found
Ooops!
The page you requested has been obsconded with by knomes. Find hippos quick!
If you are trying to log-in, your link parameters should have: "-loginpage http://" + host + "/?method=login -loginuri http://" + host + "/" in your link
";
+ }
+
+ private static string getDefaultHTTP500()
+ {
+ return "500 Internal Server Error
Ooops!
The server you requested is overun by knomes! Find hippos quick!
";
+ }
+ }
+
+ public class HttpServerContextObj
+ {
+ public IHttpClientContext context = null;
+ public IHttpRequest req = null;
+ public OSHttpRequest oreq = null;
+ public OSHttpResponse oresp = null;
+
+ public HttpServerContextObj(IHttpClientContext contxt, IHttpRequest reqs)
+ {
+ context = contxt;
+ req = reqs;
+ }
+
+ public HttpServerContextObj(OSHttpRequest osreq, OSHttpResponse osresp)
+ {
+ oreq = osreq;
+ oresp = osresp;
+ }
+ }
+
+ ///
+ /// Relays HttpServer log messages to our own logging mechanism.
+ ///
+ /// There is also a UseTraceLogs line in this file that can be uncommented for more detailed log information
+ public class HttpServerLogWriter : ILogWriter
+ {
+ //private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
+
+ public void Write(object source, LogPrio priority, string message)
+ {
+ /*
+ switch (priority)
+ {
+ case HttpServer.LogPrio.Debug:
+ m_log.DebugFormat("[{0}]: {1}", source.ToString(), message);
+ break;
+ case HttpServer.LogPrio.Error:
+ m_log.ErrorFormat("[{0}]: {1}", source.ToString(), message);
+ break;
+ case HttpServer.LogPrio.Info:
+ m_log.InfoFormat("[{0}]: {1}", source.ToString(), message);
+ break;
+ case HttpServer.LogPrio.Warning:
+ m_log.WarnFormat("[{0}]: {1}", source.ToString(), message);
+ break;
+ case HttpServer.LogPrio.Fatal:
+ m_log.ErrorFormat("[{0}]: FATAL! - {1}", source.ToString(), message);
+ break;
+ default:
+ break;
+ }
+ */
+
+ return;
+ }
+ }
+}
diff --git a/OpenSim/Framework/Servers/HttpServer/BaseRequestHandler.cs b/OpenSim/Framework/Servers/HttpServer/BaseRequestHandler.cs
new file mode 100644
index 0000000..9334972
--- /dev/null
+++ b/OpenSim/Framework/Servers/HttpServer/BaseRequestHandler.cs
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) Contributors, http://opensimulator.org/
+ * See CONTRIBUTORS.TXT for a full list of copyright holders.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the OpenSim Project nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+using System;
+
+namespace OpenSim.Framework.Servers.HttpServer
+{
+ public class BaseRequestHandler
+ {
+ public virtual string ContentType
+ {
+ get { return "application/xml"; }
+ }
+
+ private readonly string m_httpMethod;
+
+ public virtual string HttpMethod
+ {
+ get { return m_httpMethod; }
+ }
+
+ private readonly string m_path;
+
+ protected BaseRequestHandler(string httpMethod, string path)
+ {
+ m_httpMethod = httpMethod;
+ m_path = path;
+ }
+
+ public virtual string Path
+ {
+ get { return m_path; }
+ }
+
+ protected string GetParam(string path)
+ {
+ try
+ {
+ return path.Substring(m_path.Length);
+ }
+ catch (Exception)
+ {
+ return String.Empty;
+ }
+ }
+ }
+}
diff --git a/OpenSim/Framework/Servers/HttpServer/BaseStreamHandler.cs b/OpenSim/Framework/Servers/HttpServer/BaseStreamHandler.cs
new file mode 100644
index 0000000..734e3e4
--- /dev/null
+++ b/OpenSim/Framework/Servers/HttpServer/BaseStreamHandler.cs
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) Contributors, http://opensimulator.org/
+ * See CONTRIBUTORS.TXT for a full list of copyright holders.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the OpenSim Project nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+using System.IO;
+
+namespace OpenSim.Framework.Servers.HttpServer
+{
+ public abstract class BaseStreamHandler : BaseRequestHandler, IStreamedRequestHandler
+ {
+ public abstract byte[] Handle(string path, Stream request,
+ OSHttpRequest httpRequest, OSHttpResponse httpResponse);
+
+ protected BaseStreamHandler(string httpMethod, string path) : base(httpMethod, path)
+ {
+ }
+ }
+}
diff --git a/OpenSim/Framework/Servers/HttpServer/BinaryStreamHandler.cs b/OpenSim/Framework/Servers/HttpServer/BinaryStreamHandler.cs
new file mode 100644
index 0000000..fe5bcbc
--- /dev/null
+++ b/OpenSim/Framework/Servers/HttpServer/BinaryStreamHandler.cs
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) Contributors, http://opensimulator.org/
+ * See CONTRIBUTORS.TXT for a full list of copyright holders.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the OpenSim Project nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+using System.IO;
+using System.Text;
+
+namespace OpenSim.Framework.Servers.HttpServer
+{
+ public delegate string BinaryMethod(byte[] data, string path, string param);
+
+ public class BinaryStreamHandler : BaseStreamHandler
+ {
+ private BinaryMethod m_method;
+
+ public override byte[] Handle(string path, Stream request, OSHttpRequest httpRequest, OSHttpResponse httpResponse)
+ {
+ byte[] data = ReadFully(request);
+ string param = GetParam(path);
+ string responseString = m_method(data, path, param);
+
+ return Encoding.UTF8.GetBytes(responseString);
+ }
+
+ public BinaryStreamHandler(string httpMethod, string path, BinaryMethod binaryMethod)
+ : base(httpMethod, path)
+ {
+ m_method = binaryMethod;
+ }
+
+ private static byte[] ReadFully(Stream stream)
+ {
+ byte[] buffer = new byte[32768];
+ using (MemoryStream ms = new MemoryStream())
+ {
+ while (true)
+ {
+ int read = stream.Read(buffer, 0, buffer.Length);
+
+ if (read <= 0)
+ {
+ return ms.ToArray();
+ }
+
+ ms.Write(buffer, 0, read);
+ }
+ }
+ }
+ }
+}
diff --git a/OpenSim/Framework/Servers/HttpServer/GenericHTTPMethod.cs b/OpenSim/Framework/Servers/HttpServer/GenericHTTPMethod.cs
new file mode 100644
index 0000000..060761a
--- /dev/null
+++ b/OpenSim/Framework/Servers/HttpServer/GenericHTTPMethod.cs
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) Contributors, http://opensimulator.org/
+ * See CONTRIBUTORS.TXT for a full list of copyright holders.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the OpenSim Project nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+using System.Collections;
+
+namespace OpenSim.Framework.Servers.HttpServer
+{
+ public delegate Hashtable GenericHTTPMethod(Hashtable request);
+}
diff --git a/OpenSim/Framework/Servers/HttpServer/Interfaces/IHttpAgentHandler.cs b/OpenSim/Framework/Servers/HttpServer/Interfaces/IHttpAgentHandler.cs
new file mode 100644
index 0000000..60c8e6e
--- /dev/null
+++ b/OpenSim/Framework/Servers/HttpServer/Interfaces/IHttpAgentHandler.cs
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) Contributors, http://opensimulator.org/
+ * See CONTRIBUTORS.TXT for a full list of copyright holders.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the OpenSim Project nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+namespace OpenSim.Framework.Servers.HttpServer
+{
+ public interface IHttpAgentHandler
+ {
+ bool Handle(OSHttpRequest req, OSHttpResponse resp);
+ bool Match(OSHttpRequest req, OSHttpResponse resp);
+ }
+}
diff --git a/OpenSim/Framework/Servers/HttpServer/Interfaces/IHttpServer.cs b/OpenSim/Framework/Servers/HttpServer/Interfaces/IHttpServer.cs
new file mode 100644
index 0000000..6e3cc49
--- /dev/null
+++ b/OpenSim/Framework/Servers/HttpServer/Interfaces/IHttpServer.cs
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) Contributors, http://opensimulator.org/
+ * See CONTRIBUTORS.TXT for a full list of copyright holders.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the OpenSim Project nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+using Nwc.XmlRpc;
+
+namespace OpenSim.Framework.Servers.HttpServer
+{
+ ///
+ /// Interface to OpenSimulator's built in HTTP server. Use this to register handlers (http, llsd, xmlrpc, etc.)
+ /// for given URLs.
+ ///
+ public interface IHttpServer
+ {
+ uint SSLPort { get; }
+ string SSLCommonName { get; }
+
+ uint Port { get; }
+ bool UseSSL { get; }
+
+ // Note that the agent string is provided simply to differentiate
+ // the handlers - it is NOT required to be an actual agent header
+ // value.
+ bool AddAgentHandler(string agent, IHttpAgentHandler handler);
+
+ ///
+ /// Add a handler for an HTTP request
+ ///
+ ///
+ /// This handler can actually be invoked either as
+ ///
+ /// http://:/?method=
+ ///
+ /// or
+ ///
+ /// http://:
+ ///
+ /// if the method name starts with a slash. For example, AddHTTPHandler("/object/", ...) on a standalone region
+ /// server will register a handler that can be invoked with either
+ ///
+ /// http://localhost:9000/?method=/object/
+ ///
+ /// or
+ ///
+ /// http://localhost:9000/object/
+ ///
+ ///
+ ///
+ ///
+ /// true if the handler was successfully registered, false if a handler with the same name already existed.
+ ///
+ bool AddHTTPHandler(string methodName, GenericHTTPMethod handler);
+
+ ///
+ /// Adds a LLSD handler, yay.
+ ///
+ /// /resource/ path
+ /// handle the LLSD response
+ ///
+ bool AddLLSDHandler(string path, LLSDMethod handler);
+
+ ///
+ /// Add a stream handler to the http server. If the handler already exists, then nothing happens.
+ ///
+ ///
+ void AddStreamHandler(IRequestHandler handler);
+
+ bool AddXmlRPCHandler(string method, XmlRpcMethod handler);
+ bool AddXmlRPCHandler(string method, XmlRpcMethod handler, bool keepAlive);
+
+ ///
+ /// Gets the XML RPC handler for given method name
+ ///
+ /// Name of the method
+ /// Returns null if not found
+ XmlRpcMethod GetXmlRPCHandler(string method);
+
+ bool SetDefaultLLSDHandler(DefaultLLSDMethod handler);
+
+ ///
+ /// Remove the agent if it is registered.
+ ///
+ ///
+ ///
+ ///
+ bool RemoveAgentHandler(string agent, IHttpAgentHandler handler);
+
+ ///
+ /// Remove an HTTP handler
+ ///
+ ///
+ ///
+ void RemoveHTTPHandler(string httpMethod, string path);
+
+ bool RemoveLLSDHandler(string path, LLSDMethod handler);
+
+ void RemoveStreamHandler(string httpMethod, string path);
+
+ string GetHTTP404(string host);
+
+ string GetHTTP500();
+ }
+}
diff --git a/OpenSim/Framework/Servers/HttpServer/Interfaces/IStreamHandler.cs b/OpenSim/Framework/Servers/HttpServer/Interfaces/IStreamHandler.cs
new file mode 100644
index 0000000..6e27aba
--- /dev/null
+++ b/OpenSim/Framework/Servers/HttpServer/Interfaces/IStreamHandler.cs
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) Contributors, http://opensimulator.org/
+ * See CONTRIBUTORS.TXT for a full list of copyright holders.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the OpenSim Project nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+using System.Collections;
+using System.IO;
+
+namespace OpenSim.Framework.Servers.HttpServer
+{
+ public interface IRequestHandler
+ {
+ // Return response content type
+ string ContentType { get; }
+
+ // Return required http method
+ string HttpMethod { get; }
+
+ // Return path
+ string Path { get; }
+ }
+
+ public interface IStreamedRequestHandler : IRequestHandler
+ {
+ // Handle request stream, return byte array
+ byte[] Handle(string path, Stream request, OSHttpRequest httpRequest, OSHttpResponse httpResponse);
+ }
+
+ public interface IStreamHandler : IRequestHandler
+ {
+ // Handle request stream, return byte array
+ void Handle(string path, Stream request, Stream response, OSHttpRequest httpReqbuest, OSHttpResponse httpResponse);
+ }
+
+ public interface IGenericHTTPHandler : IRequestHandler
+ {
+ Hashtable Handle(string path, Hashtable request);
+ }
+}
diff --git a/OpenSim/Framework/Servers/HttpServer/Interfaces/OpenSim.Framework.Servers.Interfaces.csproj b/OpenSim/Framework/Servers/HttpServer/Interfaces/OpenSim.Framework.Servers.Interfaces.csproj
new file mode 100644
index 0000000..e8700f1
--- /dev/null
+++ b/OpenSim/Framework/Servers/HttpServer/Interfaces/OpenSim.Framework.Servers.Interfaces.csproj
@@ -0,0 +1,120 @@
+
+
+ Local
+ 8.0.50727
+ 2.0
+ {8673D009-0000-0000-0000-000000000000}
+ Debug
+ AnyCPU
+
+
+
+ OpenSim.Framework.Servers.Interfaces
+ JScript
+ Grid
+ IE50
+ false
+ v2.0
+ Library
+
+ OpenSim.Framework.Servers.Interfaces
+
+
+
+
+
+
+ False
+ 285212672
+ False
+
+
+ TRACE;DEBUG
+
+ True
+ 4096
+ False
+ ../../../../bin/
+ False
+ False
+ False
+ 4
+ False
+
+
+
+ False
+ 285212672
+ False
+
+
+ TRACE
+
+ False
+ 4096
+ True
+ ../../../../bin/
+ False
+ False
+ False
+ 4
+ False
+
+
+
+
+ HttpServer_OpenSim.dll
+ False
+
+
+ log4net.dll
+ False
+
+
+ OpenMetaverse.StructuredData.dll
+ False
+
+
+ OpenMetaverseTypes.dll
+ False
+
+
+ System
+ False
+
+
+ System.Xml
+ False
+
+
+ XMLRPC.dll
+ False
+
+
+
+
+ OpenSim.Data
+ {B75A430B-0000-0000-0000-000000000000}
+ {FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
+ False
+
+
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+
+
+
+
+
+
+
+
diff --git a/OpenSim/Framework/Servers/HttpServer/Interfaces/OpenSim.Framework.Servers.Interfaces.csproj.user b/OpenSim/Framework/Servers/HttpServer/Interfaces/OpenSim.Framework.Servers.Interfaces.csproj.user
new file mode 100644
index 0000000..b73b33f
--- /dev/null
+++ b/OpenSim/Framework/Servers/HttpServer/Interfaces/OpenSim.Framework.Servers.Interfaces.csproj.user
@@ -0,0 +1,12 @@
+
+
+ Debug
+ AnyCPU
+ /root/opensim-commit/bin/
+ 8.0.50727
+ ProjectFiles
+ 0
+
+
+
+
diff --git a/OpenSim/Framework/Servers/HttpServer/Interfaces/OpenSim.Framework.Servers.Interfaces.dll.build b/OpenSim/Framework/Servers/HttpServer/Interfaces/OpenSim.Framework.Servers.Interfaces.dll.build
new file mode 100644
index 0000000..102300f
--- /dev/null
+++ b/OpenSim/Framework/Servers/HttpServer/Interfaces/OpenSim.Framework.Servers.Interfaces.dll.build
@@ -0,0 +1,54 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/OpenSim/Framework/Servers/HttpServer/Interfaces/OpenSim.Framework.Servers.Interfaces.mdp b/OpenSim/Framework/Servers/HttpServer/Interfaces/OpenSim.Framework.Servers.Interfaces.mdp
new file mode 100644
index 0000000..96f6b46
--- /dev/null
+++ b/OpenSim/Framework/Servers/HttpServer/Interfaces/OpenSim.Framework.Servers.Interfaces.mdp
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/OpenSim/Framework/Servers/HttpServer/LLSDMethod.cs b/OpenSim/Framework/Servers/HttpServer/LLSDMethod.cs
new file mode 100644
index 0000000..d669182
--- /dev/null
+++ b/OpenSim/Framework/Servers/HttpServer/LLSDMethod.cs
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) Contributors, http://opensimulator.org/
+ * See CONTRIBUTORS.TXT for a full list of copyright holders.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the OpenSim Project nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+using OpenMetaverse.StructuredData;
+
+namespace OpenSim.Framework.Servers.HttpServer
+{
+ public delegate OSD LLSDMethod( string path, OSD request, string endpoint );
+ public delegate OSD DefaultLLSDMethod(OSD request);
+}
diff --git a/OpenSim/Framework/Servers/HttpServer/LLSDMethodString.cs b/OpenSim/Framework/Servers/HttpServer/LLSDMethodString.cs
new file mode 100644
index 0000000..61def78
--- /dev/null
+++ b/OpenSim/Framework/Servers/HttpServer/LLSDMethodString.cs
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) Contributors, http://opensimulator.org/
+ * See CONTRIBUTORS.TXT for a full list of copyright holders.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the OpenSim Project nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+using OpenMetaverse.StructuredData;
+
+namespace OpenSim.Framework.Servers.HttpServer
+{
+ public delegate OSD LLSDMethodString(OSD request, string thePath);
+}
diff --git a/OpenSim/Framework/Servers/HttpServer/OSHttpHandler.cs b/OpenSim/Framework/Servers/HttpServer/OSHttpHandler.cs
new file mode 100644
index 0000000..f1788a0
--- /dev/null
+++ b/OpenSim/Framework/Servers/HttpServer/OSHttpHandler.cs
@@ -0,0 +1,183 @@
+/*
+ * Copyright (c) Contributors, http://opensimulator.org/
+ * See CONTRIBUTORS.TXT for a full list of copyright holders.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the OpenSim Project nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Text.RegularExpressions;
+
+namespace OpenSim.Framework.Servers.HttpServer
+{
+ ///
+ /// Any OSHttpHandler must return one of the following results:
+ ///
+ ///
+ /// result code
+ /// meaning
+ ///
+ /// -
+ /// Pass
+ /// handler did not process the request
+ ///
+ /// -
+ /// Done
+ /// handler did process the request, OSHttpServer
+ /// can clean up and close the request
+ ///
+ ///
+ ///
+ public enum OSHttpHandlerResult
+ {
+ Unprocessed,
+ Pass,
+ Done,
+ }
+
+ ///
+ /// An OSHttpHandler that matches on the "content-type" header can
+ /// supply an OSHttpContentTypeChecker delegate which will be
+ /// invoked by the request matcher in OSHttpRequestPump.
+ ///
+ /// true if the handler is interested in the content;
+ /// false otherwise
+ public delegate bool OSHttpContentTypeChecker(OSHttpRequest req);
+
+ public abstract class OSHttpHandler
+ {
+ ///
+ /// Regular expression used to match against method of
+ /// the incoming HTTP request. If you want to match any string
+ /// either use '.*' or null. To match on the empty string use
+ /// '^$'.
+ ///
+ public virtual Regex Method
+ {
+ get { return _method; }
+ }
+ protected Regex _method;
+
+ ///
+ /// Regular expression used to match against path of the
+ /// incoming HTTP request. If you want to match any string
+ /// either use '.*' or null. To match on the emtpy string use
+ /// '^$'.
+ ///
+ public virtual Regex Path
+ {
+ get { return _path; }
+ }
+ protected Regex _path;
+
+ ///
+ /// Dictionary of (query name, regular expression) tuples,
+ /// allowing us to match on URI query fields.
+ ///
+ public virtual Dictionary Query
+ {
+ get { return _query; }
+ }
+ protected Dictionary _query;
+
+ ///
+ /// Dictionary of (header name, regular expression) tuples,
+ /// allowing us to match on HTTP header fields.
+ ///
+ public virtual Dictionary Headers
+ {
+ get { return _headers; }
+ }
+ protected Dictionary _headers;
+
+ ///
+ /// Dictionary of (header name, regular expression) tuples,
+ /// allowing us to match on HTTP header fields.
+ ///
+ ///
+ /// This feature is currently not implemented as it requires
+ /// (trivial) changes to HttpServer.HttpListener that have not
+ /// been implemented.
+ ///
+ public virtual Regex IPEndPointWhitelist
+ {
+ get { return _ipEndPointRegex; }
+ }
+ protected Regex _ipEndPointRegex;
+
+
+ ///
+ /// Base class constructor.
+ ///
+ /// null or path regex
+ /// null or dictionary of header
+ /// regexs
+ /// null or content type
+ /// regex
+ /// null or IP address regex
+ public OSHttpHandler(Regex method, Regex path, Dictionary query,
+ Dictionary headers, Regex contentType, Regex whitelist)
+ {
+ _method = method;
+ _path = path;
+ _query = query;
+ _ipEndPointRegex = whitelist;
+
+ if (null == _headers && null != contentType)
+ {
+ _headers = new Dictionary();
+ _headers.Add("content-type", contentType);
+ }
+ }
+
+
+ ///
+ /// Process an incoming OSHttpRequest that matched our
+ /// requirements.
+ ///
+ ///
+ /// OSHttpHandlerResult.Pass if we are after all not
+ /// interested in the request; OSHttpHandlerResult.Done if we
+ /// did process the request.
+ ///
+ public abstract OSHttpHandlerResult Process(OSHttpRequest request);
+
+ public override string ToString()
+ {
+ StringWriter sw = new StringWriter();
+ sw.WriteLine("{0}", base.ToString());
+ sw.WriteLine(" method regex {0}", null == Method ? "null" : Method.ToString());
+ sw.WriteLine(" path regex {0}", null == Path ? "null": Path.ToString());
+ foreach (string tag in Headers.Keys)
+ {
+ sw.WriteLine(" header {0} : {1}", tag, Headers[tag].ToString());
+ }
+ sw.WriteLine(" IP whitelist {0}", null == IPEndPointWhitelist ? "null" : IPEndPointWhitelist.ToString());
+ sw.WriteLine();
+ sw.Close();
+ return sw.ToString();
+ }
+ }
+}
diff --git a/OpenSim/Framework/Servers/HttpServer/OSHttpHttpHandler.cs b/OpenSim/Framework/Servers/HttpServer/OSHttpHttpHandler.cs
new file mode 100644
index 0000000..09d6f52
--- /dev/null
+++ b/OpenSim/Framework/Servers/HttpServer/OSHttpHttpHandler.cs
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) Contributors, http://opensimulator.org/
+ * See CONTRIBUTORS.TXT for a full list of copyright holders.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the OpenSim Project nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.IO;
+using System.Net;
+using System.Reflection;
+using System.Text;
+using System.Text.RegularExpressions;
+using System.Xml;
+using log4net;
+using Nwc.XmlRpc;
+
+namespace OpenSim.Framework.Servers.HttpServer
+{
+ public delegate XmlRpcResponse OSHttpHttpProcessor(XmlRpcRequest request);
+
+ public class OSHttpHttpHandler: OSHttpHandler
+ {
+ private static readonly ILog _log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
+
+ // contains handler for processing HTTP Request
+ private GenericHTTPMethod _handler;
+
+ ///
+ /// Instantiate an HTTP handler.
+ ///
+ /// a GenericHTTPMethod
+ /// null or HTTP method regex
+ /// null or path regex
+ /// null or dictionary with query regexs
+ /// null or dictionary with header
+ /// regexs
+ /// null or IP address whitelist
+ public OSHttpHttpHandler(GenericHTTPMethod handler, Regex method, Regex path,
+ Dictionary query,
+ Dictionary headers, Regex whitelist)
+ : base(method, path, query, headers, new Regex(@"^text/html", RegexOptions.IgnoreCase | RegexOptions.Compiled),
+ whitelist)
+ {
+ _handler = handler;
+ }
+
+ ///
+ /// Instantiate an HTTP handler.
+ ///
+ /// a GenericHTTPMethod
+ public OSHttpHttpHandler(GenericHTTPMethod handler)
+ : this(handler, new Regex(@"^GET$", RegexOptions.IgnoreCase | RegexOptions.Compiled), null, null, null, null)
+ {
+ }
+
+ ///
+ /// Invoked by OSHttpRequestPump.
+ ///
+ public override OSHttpHandlerResult Process(OSHttpRequest request)
+ {
+ // call handler method
+ Hashtable responseData = _handler(request.Query);
+
+ int responseCode = (int)responseData["int_response_code"];
+ string responseString = (string)responseData["str_response_string"];
+ string contentType = (string)responseData["content_type"];
+
+ //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";
+ }
+
+ OSHttpResponse response = new OSHttpResponse(request);
+
+ // We're forgoing the usual error status codes here because the client
+ // ignores anything but 200 and 301
+
+ response.StatusCode = (int)OSHttpStatusCode.SuccessOk;
+
+ if (responseCode == (int)OSHttpStatusCode.RedirectMovedPermanently)
+ {
+ response.RedirectLocation = (string)responseData["str_redirect_location"];
+ response.StatusCode = responseCode;
+ }
+
+ response.AddHeader("Content-type", contentType);
+
+ byte[] buffer;
+
+ if (!contentType.Contains("image"))
+ {
+ buffer = Encoding.UTF8.GetBytes(responseString);
+ }
+ else
+ {
+ buffer = Convert.FromBase64String(responseString);
+ }
+
+ response.SendChunked = false;
+ response.ContentLength64 = buffer.Length;
+ response.ContentEncoding = Encoding.UTF8;
+
+ try
+ {
+ response.Body.Write(buffer, 0, buffer.Length);
+ }
+ catch (Exception ex)
+ {
+ _log.ErrorFormat("[OSHttpHttpHandler]: Error: {0}", ex.Message);
+ }
+ finally
+ {
+ response.Send();
+ }
+
+ return OSHttpHandlerResult.Done;
+ }
+ }
+}
diff --git a/OpenSim/Framework/Servers/HttpServer/OSHttpRequest.cs b/OpenSim/Framework/Servers/HttpServer/OSHttpRequest.cs
new file mode 100644
index 0000000..0ca868c
--- /dev/null
+++ b/OpenSim/Framework/Servers/HttpServer/OSHttpRequest.cs
@@ -0,0 +1,228 @@
+/*
+ * Copyright (c) Contributors, http://opensimulator.org/
+ * See CONTRIBUTORS.TXT for a full list of copyright holders.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the OpenSim Project nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.Specialized;
+using System.IO;
+using System.Net;
+using System.Reflection;
+using System.Text;
+using HttpServer;
+using log4net;
+
+namespace OpenSim.Framework.Servers.HttpServer
+{
+ public class OSHttpRequest
+ {
+ private static readonly ILog _log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
+
+ protected IHttpRequest _request = null;
+ protected IHttpClientContext _context = null;
+
+ public string[] AcceptTypes
+ {
+ get { return _request.AcceptTypes; }
+ }
+
+ public Encoding ContentEncoding
+ {
+ get { return _contentEncoding; }
+ }
+ private Encoding _contentEncoding;
+
+ public long ContentLength
+ {
+ get { return _request.ContentLength; }
+ }
+
+ public long ContentLength64
+ {
+ get { return ContentLength; }
+ }
+
+ public string ContentType
+ {
+ get { return _contentType; }
+ }
+ private string _contentType;
+
+ public bool HasEntityBody
+ {
+ get { return _request.ContentLength != 0; }
+ }
+
+ public NameValueCollection Headers
+ {
+ get { return _request.Headers; }
+ }
+
+ public string HttpMethod
+ {
+ get { return _request.Method; }
+ }
+
+ public Stream InputStream
+ {
+ get { return _request.Body; }
+ }
+
+ public bool IsSecured
+ {
+ get { return _context.Secured; }
+ }
+
+ public bool KeepAlive
+ {
+ get { return ConnectionType.KeepAlive == _request.Connection; }
+ }
+
+ public NameValueCollection QueryString
+ {
+ get { return _queryString; }
+ }
+ private NameValueCollection _queryString;
+
+ public Hashtable Query
+ {
+ get { return _query; }
+ }
+ private Hashtable _query;
+
+ public string RawUrl
+ {
+ get { return _request.Uri.AbsolutePath; }
+ }
+
+ public IPEndPoint RemoteIPEndPoint
+ {
+ get { return _remoteIPEndPoint; }
+ }
+ private IPEndPoint _remoteIPEndPoint;
+
+ public Uri Url
+ {
+ get { return _request.Uri; }
+ }
+
+ public string UserAgent
+ {
+ get { return _userAgent; }
+ }
+ private string _userAgent;
+
+ internal IHttpRequest IHttpRequest
+ {
+ get { return _request; }
+ }
+
+ internal IHttpClientContext IHttpClientContext
+ {
+ get { return _context; }
+ }
+
+ ///
+ /// Internal whiteboard for handlers to store temporary stuff
+ /// into.
+ ///
+ internal Dictionary Whiteboard
+ {
+ get { return _whiteboard; }
+ }
+ private Dictionary _whiteboard = new Dictionary();
+
+
+ public OSHttpRequest() {}
+
+ public OSHttpRequest(IHttpClientContext context, IHttpRequest req)
+ {
+ _request = req;
+ _context = context;
+
+ if (null != req.Headers["content-encoding"])
+ _contentEncoding = Encoding.GetEncoding(_request.Headers["content-encoding"]);
+ if (null != req.Headers["content-type"])
+ _contentType = _request.Headers["content-type"];
+ if (null != req.Headers["user-agent"])
+ _userAgent = req.Headers["user-agent"];
+ if (null != req.Headers["remote_addr"])
+ {
+ try
+ {
+ IPAddress addr = IPAddress.Parse(req.Headers["remote_addr"]);
+ int port = Int32.Parse(req.Headers["remote_port"]);
+ _remoteIPEndPoint = new IPEndPoint(addr, port);
+ }
+ catch (FormatException)
+ {
+ _log.ErrorFormat("[OSHttpRequest]: format exception on addr/port {0}:{1}, ignoring",
+ req.Headers["remote_addr"], req.Headers["remote_port"]);
+ }
+ }
+
+ _queryString = new NameValueCollection();
+ _query = new Hashtable();
+ try
+ {
+ foreach (HttpInputItem item in req.QueryString)
+ {
+ try
+ {
+ _queryString.Add(item.Name, item.Value);
+ _query[item.Name] = item.Value;
+ }
+ catch (InvalidCastException)
+ {
+ _log.DebugFormat("[OSHttpRequest]: error parsing {0} query item, skipping it", item.Name);
+ continue;
+ }
+ }
+ }
+ catch (Exception)
+ {
+ _log.ErrorFormat("[OSHttpRequest]: Error parsing querystring");
+ }
+ }
+
+ public override string ToString()
+ {
+ StringBuilder me = new StringBuilder();
+ me.Append(String.Format("OSHttpRequest: {0} {1}\n", HttpMethod, RawUrl));
+ foreach (string k in Headers.AllKeys)
+ {
+ me.Append(String.Format(" {0}: {1}\n", k, Headers[k]));
+ }
+ if (null != RemoteIPEndPoint)
+ {
+ me.Append(String.Format(" IP: {0}\n", RemoteIPEndPoint));
+ }
+
+ return me.ToString();
+ }
+ }
+}
diff --git a/OpenSim/Framework/Servers/HttpServer/OSHttpRequestPump.cs b/OpenSim/Framework/Servers/HttpServer/OSHttpRequestPump.cs
new file mode 100644
index 0000000..893fa1b
--- /dev/null
+++ b/OpenSim/Framework/Servers/HttpServer/OSHttpRequestPump.cs
@@ -0,0 +1,298 @@
+/*
+ * Copyright (c) Contributors, http://opensimulator.org/
+ * See CONTRIBUTORS.TXT for a full list of copyright holders.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the OpenSim Project nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// #define DEBUGGING
+
+using System;
+using System.Collections.Generic;
+using System.Collections.Specialized;
+using System.Diagnostics;
+using System.IO;
+using System.Net;
+using System.Reflection;
+using System.Text.RegularExpressions;
+using System.Threading;
+using log4net;
+using HttpServer;
+
+namespace OpenSim.Framework.Servers.HttpServer
+{
+ ///
+ /// An OSHttpRequestPump fetches incoming OSHttpRequest objects
+ /// from the OSHttpRequestQueue and feeds them to all subscribed
+ /// parties. Each OSHttpRequestPump encapsulates one thread to do
+ /// the work and there is a fixed number of pumps for each
+ /// OSHttpServer object.
+ ///
+ 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} pump {1}", _server.EngineID, _id); }
+ }
+
+ public OSHttpRequestPump(OSHttpServer server, OSHttpRequestQueue queue, int id)
+ {
+ _server = server;
+ _queue = queue;
+ _id = id;
+
+ _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)
+ {
+ OSHttpRequestPump[] pumps = new OSHttpRequestPump[poolSize];
+ for (int i = 0; i < pumps.Length; i++)
+ {
+ pumps[i] = new OSHttpRequestPump(server, queue, 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;
+
+ while (true)
+ {
+ try
+ {
+ // dequeue an OSHttpRequest from OSHttpServer's
+ // request queue
+ req = _queue.Dequeue();
+
+ // get a copy of the list of registered handlers
+ List handlers = _server.OSHttpHandlers;
+
+ // prune list and have it sorted from most
+ // specific to least specific
+ handlers = MatchHandlers(req, handlers);
+
+ // process req: we try each handler in turn until
+ // we are either out of handlers or get back a
+ // Pass or Done
+ OSHttpHandlerResult rc = OSHttpHandlerResult.Unprocessed;
+ foreach (OSHttpHandler h in handlers)
+ {
+ rc = h.Process(req);
+
+ // Pass: handler did not process the request,
+ // try next handler
+ if (OSHttpHandlerResult.Pass == rc) continue;
+
+ // Handled: handler has processed the request
+ if (OSHttpHandlerResult.Done == rc) break;
+
+ // hmm, something went wrong
+ throw new Exception(String.Format("[{0}] got unexpected OSHttpHandlerResult {1}", EngineID, rc));
+ }
+
+ if (OSHttpHandlerResult.Unprocessed == rc)
+ {
+ _log.InfoFormat("[{0}] OSHttpHandler: no handler registered for {1}", EngineID, req);
+
+ // set up response header
+ OSHttpResponse resp = new OSHttpResponse(req);
+ resp.StatusCode = (int)OSHttpStatusCode.ClientErrorNotFound;
+ resp.StatusDescription = String.Format("no handler on call for {0}", req);
+ resp.ContentType = "text/html";
+
+ // add explanatory message
+ StreamWriter body = new StreamWriter(resp.Body);
+ body.WriteLine("");
+ body.WriteLine("Ooops...");
+ body.WriteLine(String.Format("{0}
", resp.StatusDescription));
+ body.WriteLine("");
+ body.Flush();
+
+ // and ship it back
+ resp.Send();
+ }
+ }
+ catch (Exception e)
+ {
+ _log.DebugFormat("[{0}] OSHttpHandler problem: {1}", EngineID, e.ToString());
+ _log.ErrorFormat("[{0}] OSHttpHandler problem: {1}", EngineID, e.Message);
+ }
+ }
+ }
+
+ protected List MatchHandlers(OSHttpRequest req, List handlers)
+ {
+ Dictionary scoredHandlers = new Dictionary();
+
+ _log.DebugFormat("[{0}] MatchHandlers for {1}", EngineID, req);
+ foreach (OSHttpHandler h in handlers)
+ {
+ // initial anchor
+ scoredHandlers[h] = 0;
+
+ // first, check whether IPEndPointWhitelist applies
+ // and, if it does, whether client is on that white
+ // list.
+ if (null != h.IPEndPointWhitelist)
+ {
+ // TODO: following code requires code changes to
+ // HttpServer.HttpRequest to become functional
+
+ IPEndPoint remote = req.RemoteIPEndPoint;
+ if (null != remote)
+ {
+ Match epm = h.IPEndPointWhitelist.Match(remote.ToString());
+ if (!epm.Success)
+ {
+ scoredHandlers.Remove(h);
+ continue;
+ }
+ }
+ }
+
+ if (null != h.Method)
+ {
+ Match m = h.Method.Match(req.HttpMethod);
+ if (!m.Success)
+ {
+ scoredHandlers.Remove(h);
+ continue;
+ }
+ scoredHandlers[h]++;
+ }
+
+ // whitelist ok, now check path
+ if (null != h.Path)
+ {
+ Match m = h.Path.Match(req.RawUrl);
+ if (!m.Success)
+ {
+ scoredHandlers.Remove(h);
+ continue;
+ }
+ scoredHandlers[h] += m.ToString().Length;
+ }
+
+ // whitelist & path ok, now check query string
+ if (null != h.Query)
+ {
+ int queriesMatch = MatchOnNameValueCollection(req.QueryString, h.Query);
+ if (0 == queriesMatch)
+ {
+ _log.DebugFormat("[{0}] request {1}", EngineID, req);
+ _log.DebugFormat("[{0}] dropping handler {1}", EngineID, h);
+
+ scoredHandlers.Remove(h);
+ continue;
+ }
+ scoredHandlers[h] += queriesMatch;
+ }
+
+ // whitelist, path, query string ok, now check headers
+ if (null != h.Headers)
+ {
+ int headersMatch = MatchOnNameValueCollection(req.Headers, h.Headers);
+ if (0 == headersMatch)
+ {
+ _log.DebugFormat("[{0}] request {1}", EngineID, req);
+ _log.DebugFormat("[{0}] dropping handler {1}", EngineID, h);
+
+ scoredHandlers.Remove(h);
+ continue;
+ }
+ scoredHandlers[h] += headersMatch;
+ }
+ }
+
+ List matchingHandlers = new List(scoredHandlers.Keys);
+ matchingHandlers.Sort(delegate(OSHttpHandler x, OSHttpHandler y)
+ {
+ return scoredHandlers[x] - scoredHandlers[y];
+ });
+ LogDumpHandlerList(matchingHandlers);
+ return matchingHandlers;
+ }
+
+ protected int MatchOnNameValueCollection(NameValueCollection collection, Dictionary regexs)
+ {
+ int matched = 0;
+
+ foreach (string tag in regexs.Keys)
+ {
+ // do we have a header "tag"?
+ if (null == collection[tag])
+ {
+ return 0;
+ }
+
+ // does the content of collection[tag] match
+ // the supplied regex?
+ Match cm = regexs[tag].Match(collection[tag]);
+ if (!cm.Success)
+ {
+ return 0;
+ }
+
+ // ok: matches
+ matched++;
+ continue;
+ }
+
+ return matched;
+ }
+
+ [ConditionalAttribute("DEBUGGING")]
+ private void LogDumpHandlerList(List l)
+ {
+ _log.DebugFormat("[{0}] OSHttpHandlerList dump:", EngineID);
+ foreach (OSHttpHandler h in l)
+ _log.DebugFormat(" ", h.ToString());
+ }
+ }
+}
diff --git a/OpenSim/Framework/Servers/HttpServer/OSHttpRequestQueue.cs b/OpenSim/Framework/Servers/HttpServer/OSHttpRequestQueue.cs
new file mode 100644
index 0000000..4e34b41
--- /dev/null
+++ b/OpenSim/Framework/Servers/HttpServer/OSHttpRequestQueue.cs
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) Contributors, http://opensimulator.org/
+ * See CONTRIBUTORS.TXT for a full list of copyright holders.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the OpenSim Project nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+using System;
+using System.Collections.Generic;
+using System.Threading;
+using HttpServer;
+
+namespace OpenSim.Framework.Servers.HttpServer
+{
+ ///
+ /// OSHttpRequestQueues are used to hand over incoming HTTP
+ /// requests to OSHttpRequestPump objects.
+ ///
+ public class OSHttpRequestQueue : Queue
+ {
+ private object _syncObject = new object();
+
+ new public void Enqueue(OSHttpRequest req)
+ {
+ lock (_syncObject)
+ {
+ base.Enqueue(req);
+ Monitor.Pulse(_syncObject);
+ }
+ }
+
+ new public OSHttpRequest Dequeue()
+ {
+ OSHttpRequest req = null;
+
+ lock (_syncObject)
+ {
+ while (null == req)
+ {
+ Monitor.Wait(_syncObject);
+ if (0 != this.Count) req = base.Dequeue();
+ }
+ }
+
+ return req;
+ }
+ }
+}
diff --git a/OpenSim/Framework/Servers/HttpServer/OSHttpResponse.cs b/OpenSim/Framework/Servers/HttpServer/OSHttpResponse.cs
new file mode 100644
index 0000000..210d122
--- /dev/null
+++ b/OpenSim/Framework/Servers/HttpServer/OSHttpResponse.cs
@@ -0,0 +1,302 @@
+/*
+ * Copyright (c) Contributors, http://opensimulator.org/
+ * See CONTRIBUTORS.TXT for a full list of copyright holders.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the OpenSim Project nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+using System.IO;
+using System.Net;
+using System.Text;
+using HttpServer;
+
+namespace OpenSim.Framework.Servers.HttpServer
+{
+ ///
+ /// OSHttpResponse is the OpenSim representation of an HTTP
+ /// response.
+ ///
+ public class OSHttpResponse
+ {
+ ///
+ /// Content type property.
+ ///
+ ///
+ /// Setting this property will also set IsContentTypeSet to
+ /// true.
+ ///
+ public string ContentType
+ {
+ get
+ {
+ return _httpResponse.ContentType;
+ }
+
+ set
+ {
+ _httpResponse.ContentType = value;
+ }
+ }
+
+ ///
+ /// Boolean property indicating whether the content type
+ /// property actively has been set.
+ ///
+ ///
+ /// IsContentTypeSet will go away together with .NET base.
+ ///
+ // public bool IsContentTypeSet
+ // {
+ // get { return _contentTypeSet; }
+ // }
+ // private bool _contentTypeSet;
+
+
+ ///
+ /// Length of the body content; 0 if there is no body.
+ ///
+ public long ContentLength
+ {
+ get
+ {
+ return _httpResponse.ContentLength;
+ }
+
+ set
+ {
+ _httpResponse.ContentLength = value;
+ }
+ }
+
+ ///
+ /// Alias for ContentLength.
+ ///
+ public long ContentLength64
+ {
+ get { return ContentLength; }
+ set { ContentLength = value; }
+ }
+
+ ///
+ /// Encoding of the body content.
+ ///
+ public Encoding ContentEncoding
+ {
+ get
+ {
+ return _httpResponse.Encoding;
+ }
+
+ set
+ {
+ _httpResponse.Encoding = value;
+ }
+ }
+
+ public bool KeepAlive
+ {
+ get
+ {
+ return _httpResponse.Connection == ConnectionType.KeepAlive;
+ }
+
+ set
+ {
+ if (value)
+ _httpResponse.Connection = ConnectionType.KeepAlive;
+ else
+ _httpResponse.Connection = ConnectionType.Close;
+ }
+ }
+
+ ///
+ /// Get or set the keep alive timeout property (default is
+ /// 20). Setting this to 0 also disables KeepAlive. Setting
+ /// this to something else but 0 also enable KeepAlive.
+ ///
+ public int KeepAliveTimeout
+ {
+ get
+ {
+ return _httpResponse.KeepAlive;
+ }
+
+ set
+ {
+ if (value == 0)
+ {
+ _httpResponse.Connection = ConnectionType.Close;
+ _httpResponse.KeepAlive = 0;
+ }
+ else
+ {
+ _httpResponse.Connection = ConnectionType.KeepAlive;
+ _httpResponse.KeepAlive = value;
+ }
+ }
+ }
+
+ ///
+ /// Return the output stream feeding the body.
+ ///
+ ///
+ /// On its way out...
+ ///
+ public Stream OutputStream
+ {
+ get
+ {
+ return _httpResponse.Body;
+ }
+ }
+
+ public string ProtocolVersion
+ {
+ get
+ {
+ return _httpResponse.ProtocolVersion;
+ }
+
+ set
+ {
+ _httpResponse.ProtocolVersion = value;
+ }
+ }
+
+ ///
+ /// Return the output stream feeding the body.
+ ///
+ public Stream Body
+ {
+ get
+ {
+ return _httpResponse.Body;
+ }
+ }
+
+ ///
+ /// Set a redirct location.
+ ///
+ public string RedirectLocation
+ {
+ // get { return _redirectLocation; }
+ set
+ {
+ _httpResponse.Redirect(value);
+ }
+ }
+
+
+ ///
+ /// Chunk transfers.
+ ///
+ public bool SendChunked
+ {
+ get
+ {
+ return _httpResponse.Chunked;
+ }
+
+ set
+ {
+ _httpResponse.Chunked = value;
+ }
+ }
+
+ ///
+ /// HTTP status code.
+ ///
+ public int StatusCode
+ {
+ get
+ {
+ return (int)_httpResponse.Status;
+ }
+
+ set
+ {
+ _httpResponse.Status = (HttpStatusCode)value;
+ }
+ }
+
+
+ ///
+ /// HTTP status description.
+ ///
+ public string StatusDescription
+ {
+ get
+ {
+ return _httpResponse.Reason;
+ }
+
+ set
+ {
+ _httpResponse.Reason = value;
+ }
+ }
+
+
+ protected IHttpResponse _httpResponse;
+
+ public OSHttpResponse() {}
+
+ public OSHttpResponse(IHttpResponse resp)
+ {
+ _httpResponse = resp;
+ }
+
+ ///
+ /// Instantiate an OSHttpResponse object from an OSHttpRequest
+ /// object.
+ /// Incoming OSHttpRequest to which we are
+ /// replying
+ public OSHttpResponse(OSHttpRequest req)
+ {
+ _httpResponse = new HttpResponse(req.IHttpClientContext, req.IHttpRequest);
+ }
+
+ ///
+ /// Add a header field and content to the response.
+ ///
+ /// string containing the header field
+ /// name
+ /// string containing the header field
+ /// value
+ public void AddHeader(string key, string value)
+ {
+ _httpResponse.AddHeader(key, value);
+ }
+
+ ///
+ /// Send the response back to the remote client
+ ///
+ public void Send()
+ {
+ _httpResponse.Body.Flush();
+ _httpResponse.Send();
+
+ }
+ }
+}
diff --git a/OpenSim/Framework/Servers/HttpServer/OSHttpServer.cs b/OpenSim/Framework/Servers/HttpServer/OSHttpServer.cs
new file mode 100644
index 0000000..e84f314
--- /dev/null
+++ b/OpenSim/Framework/Servers/HttpServer/OSHttpServer.cs
@@ -0,0 +1,210 @@
+/*
+ * Copyright (c) Contributors, http://opensimulator.org/
+ * See CONTRIBUTORS.TXT for a full list of copyright holders.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the OpenSim Project nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+using System;
+using System.Collections.Generic;
+using System.Net;
+using System.Net.Sockets;
+using System.Reflection;
+using System.Text.RegularExpressions;
+using System.Threading;
+using System.Security.Cryptography.X509Certificates;
+using log4net;
+using HttpServer;
+
+using HttpListener = HttpServer.HttpListener;
+
+namespace OpenSim.Framework.Servers.HttpServer
+{
+ ///
+ /// OSHttpServer provides an HTTP server bound to a specific
+ /// port. When instantiated with just address and port it uses
+ /// normal HTTP, when instantiated with address, port, and X509
+ /// certificate, it uses HTTPS.
+ ///
+ public class OSHttpServer
+ {
+ private static readonly ILog _log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
+
+ private object _syncObject = new object();
+
+ // underlying HttpServer.HttpListener
+ protected HttpListener _listener;
+ // underlying core/engine thread
+ protected Thread _engine;
+
+ // Queue containing (OS)HttpRequests
+ protected OSHttpRequestQueue _queue;
+
+ // OSHttpRequestPumps "pumping" incoming OSHttpRequests
+ // upwards
+ protected OSHttpRequestPump[] _pumps;
+
+ // thread identifier
+ protected string _engineId;
+ public string EngineID
+ {
+ get { return _engineId; }
+ }
+
+ ///
+ /// True if this is an HTTPS connection; false otherwise.
+ ///
+ protected bool _isSecure;
+ public bool IsSecure
+ {
+ get { return _isSecure; }
+ }
+
+ public int QueueSize
+ {
+ get { return _pumps.Length; }
+ }
+
+ ///
+ /// List of registered OSHttpHandlers for this OSHttpServer instance.
+ ///
+ protected List _httpHandlers = new List();
+ public List OSHttpHandlers
+ {
+ get
+ {
+ lock (_httpHandlers)
+ {
+ return new List(_httpHandlers);
+ }
+ }
+ }
+
+
+ ///
+ /// Instantiate an HTTP server.
+ ///
+ public OSHttpServer(IPAddress address, int port, int poolSize)
+ {
+ _engineId = String.Format("OSHttpServer (HTTP:{0})", port);
+ _isSecure = false;
+ _log.DebugFormat("[{0}] HTTP server instantiated", EngineID);
+
+ _listener = new HttpListener(address, port);
+ _queue = new OSHttpRequestQueue();
+ _pumps = OSHttpRequestPump.Pumps(this, _queue, poolSize);
+ }
+
+ ///
+ /// Instantiate an HTTPS server.
+ ///
+ public OSHttpServer(IPAddress address, int port, X509Certificate certificate, int poolSize)
+ {
+ _engineId = String.Format("OSHttpServer [HTTPS:{0}/ps:{1}]", port, poolSize);
+ _isSecure = true;
+ _log.DebugFormat("[{0}] HTTPS server instantiated", EngineID);
+
+ _listener = new HttpListener(address, port, certificate);
+ _queue = new OSHttpRequestQueue();
+ _pumps = OSHttpRequestPump.Pumps(this, _queue, poolSize);
+ }
+
+ ///
+ /// Turn an HttpRequest into an OSHttpRequestItem and place it
+ /// in the queue. The OSHttpRequestQueue object will pulse the
+ /// next available idle pump.
+ ///
+ protected void OnHttpRequest(HttpClientContext client, HttpRequest request)
+ {
+ // turn request into OSHttpRequest
+ OSHttpRequest req = new OSHttpRequest(client, request);
+
+ // place OSHttpRequest into _httpRequestQueue, will
+ // trigger Pulse to idle waiting pumps
+ _queue.Enqueue(req);
+ }
+
+ ///
+ /// Start the HTTP server engine.
+ ///
+ public void Start()
+ {
+ _engine = new Thread(new ThreadStart(Engine));
+ _engine.Name = _engineId;
+ _engine.IsBackground = true;
+ _engine.Start();
+
+ ThreadTracker.Add(_engine);
+
+ // start the pumps...
+ for (int i = 0; i < _pumps.Length; i++)
+ _pumps[i].Start();
+ }
+
+ public void Stop()
+ {
+ lock (_syncObject) Monitor.Pulse(_syncObject);
+ }
+
+ ///
+ /// Engine keeps the HTTP server running.
+ ///
+ private void Engine()
+ {
+ try {
+ _listener.RequestHandler += OnHttpRequest;
+ _listener.Start(QueueSize);
+ _log.InfoFormat("[{0}] HTTP server started", EngineID);
+
+ lock (_syncObject) Monitor.Wait(_syncObject);
+ }
+ catch (Exception ex)
+ {
+ _log.DebugFormat("[{0}] HTTP server startup failed: {1}", EngineID, ex.ToString());
+ }
+
+ _log.InfoFormat("[{0}] HTTP server terminated", EngineID);
+ }
+
+
+ ///
+ /// Add an HTTP request handler.
+ ///
+ /// OSHttpHandler delegate
+ /// regex object for path matching
+ /// dictionary containing header names
+ /// and regular expressions to match against header values
+ public void AddHandler(OSHttpHandler handler)
+ {
+ lock (_httpHandlers)
+ {
+ if (_httpHandlers.Contains(handler))
+ {
+ _log.DebugFormat("[OSHttpServer] attempt to add already existing handler ignored");
+ return;
+ }
+ _httpHandlers.Add(handler);
+ }
+ }
+ }
+}
diff --git a/OpenSim/Framework/Servers/HttpServer/OSHttpStatusCodes.cs b/OpenSim/Framework/Servers/HttpServer/OSHttpStatusCodes.cs
new file mode 100644
index 0000000..2f1ca0f
--- /dev/null
+++ b/OpenSim/Framework/Servers/HttpServer/OSHttpStatusCodes.cs
@@ -0,0 +1,170 @@
+/*
+ * Copyright (c) Contributors, http://opensimulator.org/
+ * See CONTRIBUTORS.TXT for a full list of copyright holders.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the OpenSim Project nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+namespace OpenSim.Framework.Servers.HttpServer
+{
+ ///
+ /// HTTP status codes (almost) as defined by W3C in
+ /// http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
+ ///
+ public enum OSHttpStatusCode: int
+ {
+ // 1xx Informational status codes providing a provisional
+ // response.
+ // 100 Tells client that to keep on going sending its request
+ InfoContinue = 100,
+ // 101 Server understands request, proposes to switch to different
+ // application level protocol
+ InfoSwitchingProtocols = 101,
+
+
+ // 2xx Success codes
+ // 200 Request successful
+ SuccessOk = 200,
+ // 201 Request successful, new resource created
+ SuccessOkCreated = 201,
+ // 202 Request accepted, processing still on-going
+ SuccessOkAccepted = 202,
+ // 203 Request successful, meta information not authoritative
+ SuccessOkNonAuthoritativeInformation = 203,
+ // 204 Request successful, nothing to return in the body
+ SuccessOkNoContent = 204,
+ // 205 Request successful, reset displayed content
+ SuccessOkResetContent = 205,
+ // 206 Request successful, partial content returned
+ SuccessOkPartialContent = 206,
+
+ // 3xx Redirect code: user agent needs to go somewhere else
+ // 300 Redirect: different presentation forms available, take
+ // a pick
+ RedirectMultipleChoices = 300,
+ // 301 Redirect: requested resource has moved and now lives
+ // somewhere else
+ RedirectMovedPermanently = 301,
+ // 302 Redirect: Resource temporarily somewhere else, location
+ // might change
+ RedirectFound = 302,
+ // 303 Redirect: See other as result of a POST
+ RedirectSeeOther = 303,
+ // 304 Redirect: Resource still the same as before
+ RedirectNotModified = 304,
+ // 305 Redirect: Resource must be accessed via proxy provided
+ // in location field
+ RedirectUseProxy = 305,
+ // 307 Redirect: Resource temporarily somewhere else, location
+ // might change
+ RedirectMovedTemporarily = 307,
+
+ // 4xx Client error: the client borked the request
+ // 400 Client error: bad request, server does not grok what
+ // the client wants
+ ClientErrorBadRequest = 400,
+ // 401 Client error: the client is not authorized, response
+ // provides WWW-Authenticate header field with a challenge
+ ClientErrorUnauthorized = 401,
+ // 402 Client error: Payment required (reserved for future use)
+ ClientErrorPaymentRequired = 402,
+ // 403 Client error: Server understood request, will not
+ // deliver, do not try again.
+ ClientErrorForbidden = 403,
+ // 404 Client error: Server cannot find anything matching the
+ // client request.
+ ClientErrorNotFound = 404,
+ // 405 Client error: The method specified by the client in the
+ // request is not allowed for the resource requested
+ ClientErrorMethodNotAllowed = 405,
+ // 406 Client error: Server cannot generate suitable response
+ // for the resource and content characteristics requested by
+ // the client
+ ClientErrorNotAcceptable = 406,
+ // 407 Client error: Similar to 401, Server requests that
+ // client authenticate itself with the proxy first
+ ClientErrorProxyAuthRequired = 407,
+ // 408 Client error: Server got impatient with client and
+ // decided to give up waiting for the client's request to
+ // arrive
+ ClientErrorRequestTimeout = 408,
+ // 409 Client error: Server could not fulfill the request for
+ // a resource as there is a conflict with the current state of
+ // the resource but thinks client can do something about this
+ ClientErrorConflict = 409,
+ // 410 Client error: The resource has moved somewhere else,
+ // but server has no clue where.
+ ClientErrorGone = 410,
+ // 411 Client error: The server is picky again and insists on
+ // having a content-length header field in the request
+ ClientErrorLengthRequired = 411,
+ // 412 Client error: one or more preconditions supplied in the
+ // client's request is false
+ ClientErrorPreconditionFailed = 412,
+ // 413 Client error: For fear of reflux, the server refuses to
+ // swallow that much data.
+ ClientErrorRequestEntityToLarge = 413,
+ // 414 Client error: The server considers the Request-URI to
+ // be indecently long and refuses to even look at it.
+ ClientErrorRequestURITooLong = 414,
+ // 415 Client error: The server has no clue about the media
+ // type requested by the client (contrary to popular belief it
+ // is not a warez server)
+ ClientErrorUnsupportedMediaType = 415,
+ // 416 Client error: The requested range cannot be delivered
+ // by the server.
+ ClientErrorRequestRangeNotSatisfiable = 416,
+ // 417 Client error: The expectations of the client as
+ // expressed in one or more Expect header fields cannot be met
+ // by the server, the server is awfully sorry about this.
+ ClientErrorExpectationFailed = 417,
+ // 499 Client error: Wildcard error.
+ ClientErrorJoker = 499,
+
+ // 5xx Server errors (rare)
+ // 500 Server error: something really strange and unexpected
+ // happened
+ ServerErrorInternalError = 500,
+ // 501 Server error: The server does not do the functionality
+ // required to carry out the client request. not at
+ // all. certainly not before breakfast. but also not after
+ // breakfast.
+ ServerErrorNotImplemented = 501,
+ // 502 Server error: While acting as a proxy or a gateway, the
+ // server got ditched by the upstream server and as a
+ // consequence regretfully cannot fulfill the client's request
+ ServerErrorBadGateway = 502,
+ // 503 Server error: Due to unforseen circumstances the server
+ // cannot currently deliver the service requested. Retry-After
+ // header might indicate when to try again.
+ ServerErrorServiceUnavailable = 503,
+ // 504 Server error: The server blames the upstream server
+ // for not being able to deliver the service requested and
+ // claims that the upstream server is too slow delivering the
+ // goods.
+ ServerErrorGatewayTimeout = 504,
+ // 505 Server error: The server does not support the HTTP
+ // version conveyed in the client's request.
+ ServerErrorHttpVersionNotSupported = 505,
+ }
+}
diff --git a/OpenSim/Framework/Servers/HttpServer/OSHttpXmlRpcHandler.cs b/OpenSim/Framework/Servers/HttpServer/OSHttpXmlRpcHandler.cs
new file mode 100644
index 0000000..49bae48
--- /dev/null
+++ b/OpenSim/Framework/Servers/HttpServer/OSHttpXmlRpcHandler.cs
@@ -0,0 +1,180 @@
+/*
+ * Copyright (c) Contributors, http://opensimulator.org/
+ * See CONTRIBUTORS.TXT for a full list of copyright holders.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the OpenSim Project nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Net;
+using System.Reflection;
+using System.Text;
+using System.Text.RegularExpressions;
+using System.Xml;
+using log4net;
+using Nwc.XmlRpc;
+
+namespace OpenSim.Framework.Servers.HttpServer
+{
+ public delegate XmlRpcResponse OSHttpXmlRpcProcessor(XmlRpcRequest request);
+
+ public class OSHttpXmlRpcHandler: OSHttpHandler
+ {
+ private static readonly ILog _log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
+
+ ///
+ /// XmlRpcMethodMatch tries to reify (deserialize) an incoming
+ /// XmlRpc request (and posts it to the "whiteboard") and
+ /// checks whether the method name is one we are interested
+ /// in.
+ ///
+ /// true if the handler is interested in the content;
+ /// false otherwise
+ protected bool XmlRpcMethodMatch(OSHttpRequest req)
+ {
+ XmlRpcRequest xmlRpcRequest = null;
+
+ // check whether req is already reified
+ // if not: reify (and post to whiteboard)
+ try
+ {
+ if (req.Whiteboard.ContainsKey("xmlrequest"))
+ {
+ xmlRpcRequest = req.Whiteboard["xmlrequest"] as XmlRpcRequest;
+ }
+ else
+ {
+ StreamReader body = new StreamReader(req.InputStream);
+ string requestBody = body.ReadToEnd();
+ xmlRpcRequest = (XmlRpcRequest)(new XmlRpcRequestDeserializer()).Deserialize(requestBody);
+ req.Whiteboard["xmlrequest"] = xmlRpcRequest;
+ }
+ }
+ catch (XmlException)
+ {
+ _log.ErrorFormat("[OSHttpXmlRpcHandler] failed to deserialize XmlRpcRequest from {0}", req.ToString());
+ return false;
+ }
+
+ // check against methodName
+ if ((null != xmlRpcRequest)
+ && !String.IsNullOrEmpty(xmlRpcRequest.MethodName)
+ && xmlRpcRequest.MethodName == _methodName)
+ {
+ _log.DebugFormat("[OSHttpXmlRpcHandler] located handler {0} for {1}", _methodName, req.ToString());
+ return true;
+ }
+
+ return false;
+ }
+
+ // contains handler for processing XmlRpc Request
+ private XmlRpcMethod _handler;
+
+ // contains XmlRpc method name
+ private string _methodName;
+
+
+ ///
+ /// Instantiate an XmlRpc handler.
+ ///
+ /// XmlRpcMethod
+ /// delegate
+ /// XmlRpc method name
+ /// XmlRpc path prefix (regular expression)
+ /// Dictionary with header names and
+ /// regular expressions to match content of headers
+ /// IP whitelist of remote end points
+ /// to accept (regular expression)
+ ///
+ /// Except for handler and methodName, all other parameters
+ /// can be null, in which case they are not taken into account
+ /// when the handler is being looked up.
+ ///
+ public OSHttpXmlRpcHandler(XmlRpcMethod handler, string methodName, Regex path,
+ Dictionary headers, Regex whitelist)
+ : base(new Regex(@"^POST$", RegexOptions.IgnoreCase | RegexOptions.Compiled), path, null, headers,
+ new Regex(@"^(text|application)/xml", RegexOptions.IgnoreCase | RegexOptions.Compiled),
+ whitelist)
+ {
+ _handler = handler;
+ _methodName = methodName;
+ }
+
+
+ ///
+ /// Instantiate an XmlRpc handler.
+ ///
+ /// XmlRpcMethod
+ /// delegate
+ /// XmlRpc method name
+ public OSHttpXmlRpcHandler(XmlRpcMethod handler, string methodName)
+ : this(handler, methodName, null, null, null)
+ {
+ }
+
+
+ ///
+ /// Invoked by OSHttpRequestPump.
+ ///
+ public override OSHttpHandlerResult Process(OSHttpRequest request)
+ {
+ XmlRpcResponse xmlRpcResponse;
+ string responseString;
+
+ // check whether we are interested in this request
+ if (!XmlRpcMethodMatch(request)) return OSHttpHandlerResult.Pass;
+
+
+ OSHttpResponse resp = new OSHttpResponse(request);
+ try
+ {
+ // reified XmlRpcRequest must still be on the whiteboard
+ XmlRpcRequest xmlRpcRequest = request.Whiteboard["xmlrequest"] as XmlRpcRequest;
+ xmlRpcResponse = _handler(xmlRpcRequest);
+ responseString = XmlRpcResponseSerializer.Singleton.Serialize(xmlRpcResponse);
+
+ resp.ContentType = "text/xml";
+ byte[] buffer = Encoding.UTF8.GetBytes(responseString);
+
+ resp.SendChunked = false;
+ resp.ContentLength = buffer.Length;
+ resp.ContentEncoding = Encoding.UTF8;
+
+ resp.Body.Write(buffer, 0, buffer.Length);
+ resp.Body.Flush();
+
+ resp.Send();
+
+ }
+ catch (Exception ex)
+ {
+ _log.WarnFormat("[OSHttpXmlRpcHandler]: Error: {0}", ex.Message);
+ return OSHttpHandlerResult.Pass;
+ }
+ return OSHttpHandlerResult.Done;
+ }
+ }
+}
diff --git a/OpenSim/Framework/Servers/HttpServer/OpenSim.Framework.Servers.HttpServer.csproj b/OpenSim/Framework/Servers/HttpServer/OpenSim.Framework.Servers.HttpServer.csproj
new file mode 100644
index 0000000..097a251
--- /dev/null
+++ b/OpenSim/Framework/Servers/HttpServer/OpenSim.Framework.Servers.HttpServer.csproj
@@ -0,0 +1,180 @@
+
+
+ Local
+ 8.0.50727
+ 2.0
+ {1CBD339A-0000-0000-0000-000000000000}
+ Debug
+ AnyCPU
+
+
+
+ OpenSim.Framework.Servers.HttpServer
+ JScript
+ Grid
+ IE50
+ false
+ v2.0
+ Library
+
+ OpenSim.Framework.Servers.HttpServer
+
+
+
+
+
+
+ False
+ 285212672
+ False
+
+
+ TRACE;DEBUG
+
+ True
+ 4096
+ False
+ ../../../../bin/
+ False
+ False
+ False
+ 4
+ False
+
+
+
+ False
+ 285212672
+ False
+
+
+ TRACE
+
+ False
+ 4096
+ True
+ ../../../../bin/
+ False
+ False
+ False
+ 4
+ False
+
+
+
+
+ HttpServer_OpenSim.dll
+ False
+
+
+ log4net.dll
+ False
+
+
+ OpenMetaverse.StructuredData.dll
+ False
+
+
+ OpenMetaverseTypes.dll
+ False
+
+
+ System
+ False
+
+
+ System.Xml
+ False
+
+
+ XMLRPC.dll
+ False
+
+
+
+
+ OpenSim.Data
+ {B75A430B-0000-0000-0000-000000000000}
+ {FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
+ False
+
+
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+
+
+
+
+
+
+
+
diff --git a/OpenSim/Framework/Servers/HttpServer/OpenSim.Framework.Servers.HttpServer.csproj.user b/OpenSim/Framework/Servers/HttpServer/OpenSim.Framework.Servers.HttpServer.csproj.user
new file mode 100644
index 0000000..b73b33f
--- /dev/null
+++ b/OpenSim/Framework/Servers/HttpServer/OpenSim.Framework.Servers.HttpServer.csproj.user
@@ -0,0 +1,12 @@
+
+
+ Debug
+ AnyCPU
+ /root/opensim-commit/bin/
+ 8.0.50727
+ ProjectFiles
+ 0
+
+
+
+
diff --git a/OpenSim/Framework/Servers/HttpServer/OpenSim.Framework.Servers.HttpServer.dll.build b/OpenSim/Framework/Servers/HttpServer/OpenSim.Framework.Servers.HttpServer.dll.build
new file mode 100644
index 0000000..f814703
--- /dev/null
+++ b/OpenSim/Framework/Servers/HttpServer/OpenSim.Framework.Servers.HttpServer.dll.build
@@ -0,0 +1,74 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/OpenSim/Framework/Servers/HttpServer/OpenSim.Framework.Servers.HttpServer.mdp b/OpenSim/Framework/Servers/HttpServer/OpenSim.Framework.Servers.HttpServer.mdp
new file mode 100644
index 0000000..7556d59
--- /dev/null
+++ b/OpenSim/Framework/Servers/HttpServer/OpenSim.Framework.Servers.HttpServer.mdp
@@ -0,0 +1,54 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/OpenSim/Framework/Servers/HttpServer/RestDeserialiseHandler.cs b/OpenSim/Framework/Servers/HttpServer/RestDeserialiseHandler.cs
new file mode 100644
index 0000000..d5ab926
--- /dev/null
+++ b/OpenSim/Framework/Servers/HttpServer/RestDeserialiseHandler.cs
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) Contributors, http://opensimulator.org/
+ * See CONTRIBUTORS.TXT for a full list of copyright holders.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the OpenSim Project nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+using System.IO;
+using System.Xml;
+using System.Xml.Serialization;
+
+namespace OpenSim.Framework.Servers.HttpServer
+{
+ public delegate TResponse RestDeserialiseMethod(TRequest request);
+
+ public class RestDeserialiseHandler : BaseRequestHandler, IStreamHandler
+ where TRequest : new()
+ {
+ private RestDeserialiseMethod m_method;
+
+ public RestDeserialiseHandler(string httpMethod, string path, RestDeserialiseMethod method)
+ : base(httpMethod, path)
+ {
+ m_method = method;
+ }
+
+ public void Handle(string path, Stream request, Stream responseStream,
+ OSHttpRequest httpRequest, OSHttpResponse httpResponse)
+ {
+ TRequest deserial;
+ using (XmlTextReader xmlReader = new XmlTextReader(request))
+ {
+ XmlSerializer deserializer = new XmlSerializer(typeof (TRequest));
+ deserial = (TRequest) deserializer.Deserialize(xmlReader);
+ }
+
+ TResponse response = m_method(deserial);
+
+ using (XmlWriter xmlWriter = XmlTextWriter.Create(responseStream))
+ {
+ XmlSerializer serializer = new XmlSerializer(typeof (TResponse));
+ serializer.Serialize(xmlWriter, response);
+ }
+ }
+ }
+}
diff --git a/OpenSim/Framework/Servers/HttpServer/RestHTTPHandler.cs b/OpenSim/Framework/Servers/HttpServer/RestHTTPHandler.cs
new file mode 100644
index 0000000..175a0f2
--- /dev/null
+++ b/OpenSim/Framework/Servers/HttpServer/RestHTTPHandler.cs
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) Contributors, http://opensimulator.org/
+ * See CONTRIBUTORS.TXT for a full list of copyright holders.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the OpenSim Project nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+using System.Collections;
+
+namespace OpenSim.Framework.Servers.HttpServer
+{
+ public class RestHTTPHandler : BaseHTTPHandler
+ {
+ private GenericHTTPMethod m_dhttpMethod;
+
+ public GenericHTTPMethod Method
+ {
+ get { return m_dhttpMethod; }
+ }
+
+ public override Hashtable Handle(string path, Hashtable request)
+ {
+
+ string param = GetParam(path);
+ request.Add("param", param);
+ request.Add("path", path);
+ return m_dhttpMethod(request);
+ }
+
+ public RestHTTPHandler(string httpMethod, string path, GenericHTTPMethod dhttpMethod)
+ : base(httpMethod, path)
+ {
+ m_dhttpMethod = dhttpMethod;
+ }
+ }
+}
diff --git a/OpenSim/Framework/Servers/HttpServer/RestMethod.cs b/OpenSim/Framework/Servers/HttpServer/RestMethod.cs
new file mode 100644
index 0000000..08ee35a
--- /dev/null
+++ b/OpenSim/Framework/Servers/HttpServer/RestMethod.cs
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) Contributors, http://opensimulator.org/
+ * See CONTRIBUTORS.TXT for a full list of copyright holders.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the OpenSim Project nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+namespace OpenSim.Framework.Servers.HttpServer
+{
+ public delegate string RestMethod(string request, string path, string param,
+ OSHttpRequest httpRequest, OSHttpResponse httpResponse);
+}
diff --git a/OpenSim/Framework/Servers/HttpServer/RestObjectPoster.cs b/OpenSim/Framework/Servers/HttpServer/RestObjectPoster.cs
new file mode 100644
index 0000000..5a424d8
--- /dev/null
+++ b/OpenSim/Framework/Servers/HttpServer/RestObjectPoster.cs
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) Contributors, http://opensimulator.org/
+ * See CONTRIBUTORS.TXT for a full list of copyright holders.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the OpenSim Project nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+using System;
+using System.IO;
+using System.Net;
+using System.Text;
+using System.Xml;
+using System.Xml.Serialization;
+
+namespace OpenSim.Framework.Servers.HttpServer
+{
+ ///
+ /// Makes an asynchronous REST request which doesn't require us to do anything with the response.
+ ///
+ public class RestObjectPoster
+ {
+ public static void BeginPostObject(string requestUrl, TRequest obj)
+ {
+ BeginPostObject("POST", requestUrl, obj);
+ }
+
+ public static void BeginPostObject(string verb, string requestUrl, TRequest obj)
+ {
+ Type type = typeof (TRequest);
+
+ WebRequest request = WebRequest.Create(requestUrl);
+ request.Method = verb;
+ request.ContentType = "text/xml";
+
+ MemoryStream buffer = new MemoryStream();
+
+ XmlWriterSettings settings = new XmlWriterSettings();
+ settings.Encoding = Encoding.UTF8;
+
+ using (XmlWriter writer = XmlWriter.Create(buffer, settings))
+ {
+ XmlSerializer serializer = new XmlSerializer(type);
+ serializer.Serialize(writer, obj);
+ writer.Flush();
+ }
+
+ int length = (int) buffer.Length;
+ request.ContentLength = length;
+
+ Stream requestStream = request.GetRequestStream();
+ requestStream.Write(buffer.ToArray(), 0, length);
+ // IAsyncResult result = request.BeginGetResponse(AsyncCallback, request);
+ request.BeginGetResponse(AsyncCallback, request);
+ }
+
+ private static void AsyncCallback(IAsyncResult result)
+ {
+ WebRequest request = (WebRequest) result.AsyncState;
+ using (WebResponse resp = request.EndGetResponse(result))
+ {
+ }
+ }
+ }
+}
diff --git a/OpenSim/Framework/Servers/HttpServer/RestObjectPosterResponse.cs b/OpenSim/Framework/Servers/HttpServer/RestObjectPosterResponse.cs
new file mode 100644
index 0000000..690c583
--- /dev/null
+++ b/OpenSim/Framework/Servers/HttpServer/RestObjectPosterResponse.cs
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) Contributors, http://opensimulator.org/
+ * See CONTRIBUTORS.TXT for a full list of copyright holders.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the OpenSim Project nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+using System;
+using System.IO;
+using System.Net;
+using System.Text;
+using System.Xml;
+using System.Xml.Serialization;
+
+namespace OpenSim.Framework.Servers.HttpServer
+{
+ public delegate void ReturnResponse(T reponse);
+
+ ///
+ /// Makes an asynchronous REST request with a callback to invoke with the response.
+ ///
+ public class RestObjectPosterResponse
+ {
+// private static readonly log4net.ILog m_log
+// = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
+
+ public ReturnResponse ResponseCallback;
+
+ public void BeginPostObject(string requestUrl, TRequest obj)
+ {
+ BeginPostObject("POST", requestUrl, obj);
+ }
+
+ public void BeginPostObject(string verb, string requestUrl, TRequest obj)
+ {
+ Type type = typeof (TRequest);
+
+ WebRequest request = WebRequest.Create(requestUrl);
+ request.Method = verb;
+ request.ContentType = "text/xml";
+ request.Timeout = 10000;
+
+ MemoryStream buffer = new MemoryStream();
+
+ XmlWriterSettings settings = new XmlWriterSettings();
+ settings.Encoding = Encoding.UTF8;
+
+ using (XmlWriter writer = XmlWriter.Create(buffer, settings))
+ {
+ XmlSerializer serializer = new XmlSerializer(type);
+ serializer.Serialize(writer, obj);
+ writer.Flush();
+ }
+
+ int length = (int) buffer.Length;
+ request.ContentLength = length;
+
+ Stream requestStream = request.GetRequestStream();
+ requestStream.Write(buffer.ToArray(), 0, length);
+ requestStream.Close();
+ // IAsyncResult result = request.BeginGetResponse(AsyncCallback, request);
+ request.BeginGetResponse(AsyncCallback, request);
+ }
+
+ private void AsyncCallback(IAsyncResult result)
+ {
+ WebRequest request = (WebRequest) result.AsyncState;
+ using (WebResponse resp = request.EndGetResponse(result))
+ {
+ TResponse deserial;
+ XmlSerializer deserializer = new XmlSerializer(typeof (TResponse));
+ Stream stream = resp.GetResponseStream();
+
+ // This is currently a bad debug stanza since it gobbles us the response...
+// StreamReader reader = new StreamReader(stream);
+// m_log.DebugFormat("[REST OBJECT POSTER RESPONSE]: Received {0}", reader.ReadToEnd());
+
+ deserial = (TResponse) deserializer.Deserialize(stream);
+
+ if (deserial != null && ResponseCallback != null)
+ {
+ ResponseCallback(deserial);
+ }
+ }
+ }
+ }
+}
diff --git a/OpenSim/Framework/Servers/HttpServer/RestSessionService.cs b/OpenSim/Framework/Servers/HttpServer/RestSessionService.cs
new file mode 100644
index 0000000..f5e4248
--- /dev/null
+++ b/OpenSim/Framework/Servers/HttpServer/RestSessionService.cs
@@ -0,0 +1,291 @@
+/*
+ * Copyright (c) Contributors, http://opensimulator.org/
+ * See CONTRIBUTORS.TXT for a full list of copyright holders.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the OpenSimulator Project nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+using System;
+using System.IO;
+using System.Net;
+using System.Reflection;
+using System.Text;
+using System.Xml;
+using System.Xml.Serialization;
+using log4net;
+
+namespace OpenSim.Framework.Servers.HttpServer
+{
+ public class RestSessionObject
+ {
+ private string sid;
+ private string aid;
+ private TRequest request_body;
+
+ public string SessionID
+ {
+ get { return sid; }
+ set { sid = value; }
+ }
+
+ public string AvatarID
+ {
+ get { return aid; }
+ set { aid = value; }
+ }
+
+ public TRequest Body
+ {
+ get { return request_body; }
+ set { request_body = value; }
+ }
+ }
+
+ public class SynchronousRestSessionObjectPoster
+ {
+ public static TResponse BeginPostObject(string verb, string requestUrl, TRequest obj, string sid, string aid)
+ {
+ RestSessionObject sobj = new RestSessionObject();
+ sobj.SessionID = sid;
+ sobj.AvatarID = aid;
+ sobj.Body = obj;
+
+ Type type = typeof(RestSessionObject);
+
+ WebRequest request = WebRequest.Create(requestUrl);
+ request.Method = verb;
+ request.ContentType = "text/xml";
+
+ MemoryStream buffer = new MemoryStream();
+
+ XmlWriterSettings settings = new XmlWriterSettings();
+ settings.Encoding = Encoding.UTF8;
+
+ using (XmlWriter writer = XmlWriter.Create(buffer, settings))
+ {
+ XmlSerializer serializer = new XmlSerializer(type);
+ serializer.Serialize(writer, sobj);
+ writer.Flush();
+ }
+
+ int length = (int)buffer.Length;
+ request.ContentLength = length;
+
+ Stream requestStream = request.GetRequestStream();
+ requestStream.Write(buffer.ToArray(), 0, length);
+ TResponse deserial = default(TResponse);
+ using (WebResponse resp = request.GetResponse())
+ {
+ XmlSerializer deserializer = new XmlSerializer(typeof(TResponse));
+ deserial = (TResponse)deserializer.Deserialize(resp.GetResponseStream());
+ }
+ return deserial;
+ }
+ }
+
+ public class RestSessionObjectPosterResponse
+ {
+ public ReturnResponse ResponseCallback;
+
+ public void BeginPostObject(string requestUrl, TRequest obj, string sid, string aid)
+ {
+ BeginPostObject("POST", requestUrl, obj, sid, aid);
+ }
+
+ public void BeginPostObject(string verb, string requestUrl, TRequest obj, string sid, string aid)
+ {
+ RestSessionObject sobj = new RestSessionObject();
+ sobj.SessionID = sid;
+ sobj.AvatarID = aid;
+ sobj.Body = obj;
+
+ Type type = typeof(RestSessionObject);
+
+ WebRequest request = WebRequest.Create(requestUrl);
+ request.Method = verb;
+ request.ContentType = "text/xml";
+ request.Timeout = 10000;
+
+ MemoryStream buffer = new MemoryStream();
+
+ XmlWriterSettings settings = new XmlWriterSettings();
+ settings.Encoding = Encoding.UTF8;
+
+ using (XmlWriter writer = XmlWriter.Create(buffer, settings))
+ {
+ XmlSerializer serializer = new XmlSerializer(type);
+ serializer.Serialize(writer, sobj);
+ writer.Flush();
+ }
+
+ int length = (int)buffer.Length;
+ request.ContentLength = length;
+
+ Stream requestStream = request.GetRequestStream();
+ requestStream.Write(buffer.ToArray(), 0, length);
+ requestStream.Close();
+ // IAsyncResult result = request.BeginGetResponse(AsyncCallback, request);
+ request.BeginGetResponse(AsyncCallback, request);
+ }
+
+ private void AsyncCallback(IAsyncResult result)
+ {
+ WebRequest request = (WebRequest)result.AsyncState;
+ using (WebResponse resp = request.EndGetResponse(result))
+ {
+ TResponse deserial;
+ XmlSerializer deserializer = new XmlSerializer(typeof(TResponse));
+ Stream stream = resp.GetResponseStream();
+
+ // This is currently a bad debug stanza since it gobbles us the response...
+ // StreamReader reader = new StreamReader(stream);
+ // m_log.DebugFormat("[REST OBJECT POSTER RESPONSE]: Received {0}", reader.ReadToEnd());
+
+ deserial = (TResponse)deserializer.Deserialize(stream);
+
+ if (deserial != null && ResponseCallback != null)
+ {
+ ResponseCallback(deserial);
+ }
+ }
+ }
+ }
+
+ public delegate bool CheckIdentityMethod(string sid, string aid);
+
+ public class RestDeserialiseSecureHandler : BaseRequestHandler, IStreamHandler
+ where TRequest : new()
+ {
+ private static readonly ILog m_log
+ = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
+
+ private RestDeserialiseMethod m_method;
+ private CheckIdentityMethod m_smethod;
+
+ public RestDeserialiseSecureHandler(
+ string httpMethod, string path,
+ RestDeserialiseMethod method, CheckIdentityMethod smethod)
+ : base(httpMethod, path)
+ {
+ m_smethod = smethod;
+ m_method = method;
+ }
+
+ public void Handle(string path, Stream request, Stream responseStream,
+ OSHttpRequest httpRequest, OSHttpResponse httpResponse)
+ {
+ RestSessionObject deserial = default(RestSessionObject);
+ bool fail = false;
+
+ using (XmlTextReader xmlReader = new XmlTextReader(request))
+ {
+ try
+ {
+ XmlSerializer deserializer = new XmlSerializer(typeof(RestSessionObject));
+ deserial = (RestSessionObject)deserializer.Deserialize(xmlReader);
+ }
+ catch (Exception e)
+ {
+ m_log.Error("[REST]: Deserialization problem. Ignoring request. " + e);
+ fail = true;
+ }
+ }
+
+ TResponse response = default(TResponse);
+ if (!fail && m_smethod(deserial.SessionID, deserial.AvatarID))
+ {
+ response = m_method(deserial.Body);
+ }
+
+ using (XmlWriter xmlWriter = XmlTextWriter.Create(responseStream))
+ {
+ XmlSerializer serializer = new XmlSerializer(typeof(TResponse));
+ serializer.Serialize(xmlWriter, response);
+ }
+ }
+ }
+
+ public delegate bool CheckTrustedSourceMethod(IPEndPoint peer);
+
+ public class RestDeserialiseTrustedHandler : BaseRequestHandler, IStreamHandler
+ where TRequest : new()
+ {
+ private static readonly ILog m_log
+ = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
+
+ ///
+ /// The operation to perform once trust has been established.
+ ///
+ ///
+ ///
+ ///
+ ///
+ private RestDeserialiseMethod m_method;
+
+ ///
+ /// The method used to check whether a request is trusted.
+ ///
+ private CheckTrustedSourceMethod m_tmethod;
+
+ public RestDeserialiseTrustedHandler(string httpMethod, string path, RestDeserialiseMethod method, CheckTrustedSourceMethod tmethod)
+ : base(httpMethod, path)
+ {
+ m_tmethod = tmethod;
+ m_method = method;
+ }
+
+ public void Handle(string path, Stream request, Stream responseStream,
+ OSHttpRequest httpRequest, OSHttpResponse httpResponse)
+ {
+ TRequest deserial = default(TRequest);
+ bool fail = false;
+
+ using (XmlTextReader xmlReader = new XmlTextReader(request))
+ {
+ try
+ {
+ XmlSerializer deserializer = new XmlSerializer(typeof(TRequest));
+ deserial = (TRequest)deserializer.Deserialize(xmlReader);
+ }
+ catch (Exception e)
+ {
+ m_log.Error("[REST]: Deserialization problem. Ignoring request. " + e);
+ fail = true;
+ }
+ }
+
+ TResponse response = default(TResponse);
+ if (!fail && m_tmethod(httpRequest.RemoteIPEndPoint))
+ {
+ response = m_method(deserial);
+ }
+
+ using (XmlWriter xmlWriter = XmlTextWriter.Create(responseStream))
+ {
+ XmlSerializer serializer = new XmlSerializer(typeof(TResponse));
+ serializer.Serialize(xmlWriter, response);
+ }
+ }
+ }
+
+}
diff --git a/OpenSim/Framework/Servers/HttpServer/RestStreamHandler.cs b/OpenSim/Framework/Servers/HttpServer/RestStreamHandler.cs
new file mode 100644
index 0000000..f213c15
--- /dev/null
+++ b/OpenSim/Framework/Servers/HttpServer/RestStreamHandler.cs
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) Contributors, http://opensimulator.org/
+ * See CONTRIBUTORS.TXT for a full list of copyright holders.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the OpenSim Project nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+using System.IO;
+using System.Text;
+
+namespace OpenSim.Framework.Servers.HttpServer
+{
+ public class RestStreamHandler : BaseStreamHandler
+ {
+ private RestMethod m_restMethod;
+
+ public RestMethod Method
+ {
+ get { return m_restMethod; }
+ }
+
+ public override byte[] Handle(string path, Stream request, OSHttpRequest httpRequest, OSHttpResponse httpResponse)
+ {
+ Encoding encoding = Encoding.UTF8;
+ StreamReader streamReader = new StreamReader(request, encoding);
+
+ string requestBody = streamReader.ReadToEnd();
+ streamReader.Close();
+
+ string param = GetParam(path);
+ string responseString = m_restMethod(requestBody, path, param, httpRequest, httpResponse);
+
+ return Encoding.UTF8.GetBytes(responseString);
+ }
+
+ public RestStreamHandler(string httpMethod, string path, RestMethod restMethod) : base(httpMethod, path)
+ {
+ m_restMethod = restMethod;
+ }
+ }
+}
diff --git a/OpenSim/Framework/Servers/HttpServer/SynchronousRestObjectPoster.cs b/OpenSim/Framework/Servers/HttpServer/SynchronousRestObjectPoster.cs
new file mode 100644
index 0000000..b754c36
--- /dev/null
+++ b/OpenSim/Framework/Servers/HttpServer/SynchronousRestObjectPoster.cs
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) Contributors, http://opensimulator.org/
+ * See CONTRIBUTORS.TXT for a full list of copyright holders.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the OpenSim Project nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+using System;
+using System.IO;
+using System.Net;
+using System.Text;
+using System.Xml;
+using System.Xml.Serialization;
+
+namespace OpenSim.Framework.Servers.HttpServer
+{
+ public class SynchronousRestObjectPoster
+ {
+ ///
+ /// Perform a synchronous REST request.
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ /// Thrown if we encounter a network issue while posting
+ /// the request. You'll want to make sure you deal with this as they're not uncommon
+ public static TResponse BeginPostObject(string verb, string requestUrl, TRequest obj)
+ {
+ Type type = typeof (TRequest);
+
+ WebRequest request = WebRequest.Create(requestUrl);
+ request.Method = verb;
+ request.ContentType = "text/xml";
+
+ MemoryStream buffer = new MemoryStream();
+
+ XmlWriterSettings settings = new XmlWriterSettings();
+ settings.Encoding = Encoding.UTF8;
+
+ using (XmlWriter writer = XmlWriter.Create(buffer, settings))
+ {
+ XmlSerializer serializer = new XmlSerializer(type);
+ serializer.Serialize(writer, obj);
+ writer.Flush();
+ }
+
+ int length = (int) buffer.Length;
+ request.ContentLength = length;
+
+ Stream requestStream = request.GetRequestStream();
+ requestStream.Write(buffer.ToArray(), 0, length);
+ TResponse deserial = default(TResponse);
+ using (WebResponse resp = request.GetResponse())
+ {
+ XmlSerializer deserializer = new XmlSerializer(typeof (TResponse));
+ deserial = (TResponse) deserializer.Deserialize(resp.GetResponseStream());
+ }
+ return deserial;
+ }
+ }
+}
diff --git a/OpenSim/Framework/Servers/HttpServer/XmlRpcMethod.cs b/OpenSim/Framework/Servers/HttpServer/XmlRpcMethod.cs
new file mode 100644
index 0000000..843b3f7
--- /dev/null
+++ b/OpenSim/Framework/Servers/HttpServer/XmlRpcMethod.cs
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) Contributors, http://opensimulator.org/
+ * See CONTRIBUTORS.TXT for a full list of copyright holders.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the OpenSim Project nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+using Nwc.XmlRpc;
+
+namespace OpenSim.Framework.Servers.HttpServer
+{
+ public delegate XmlRpcResponse XmlRpcMethod(XmlRpcRequest request);
+}
diff --git a/OpenSim/Framework/Servers/HttpServer/bin/Debug/OpenSim.Framework.Servers.HttpServer.dll b/OpenSim/Framework/Servers/HttpServer/bin/Debug/OpenSim.Framework.Servers.HttpServer.dll
new file mode 100755
index 0000000..a191346
Binary files /dev/null and b/OpenSim/Framework/Servers/HttpServer/bin/Debug/OpenSim.Framework.Servers.HttpServer.dll differ
diff --git a/OpenSim/Framework/Servers/HttpServer/bin/Debug/OpenSim.Framework.Servers.HttpServer.dll.mdb b/OpenSim/Framework/Servers/HttpServer/bin/Debug/OpenSim.Framework.Servers.HttpServer.dll.mdb
new file mode 100644
index 0000000..25a50b9
Binary files /dev/null and b/OpenSim/Framework/Servers/HttpServer/bin/Debug/OpenSim.Framework.Servers.HttpServer.dll.mdb differ
diff --git a/OpenSim/Framework/Servers/MessageServerInfo.cs b/OpenSim/Framework/Servers/MessageServerInfo.cs
new file mode 100644
index 0000000..17b5f10
--- /dev/null
+++ b/OpenSim/Framework/Servers/MessageServerInfo.cs
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) Contributors, http://opensimulator.org/
+ * See CONTRIBUTORS.TXT for a full list of copyright holders.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the OpenSim Project nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+using System.Collections.Generic;
+
+namespace OpenSim.Framework.Servers
+{
+ public class MessageServerInfo
+ {
+ public string URI;
+ public string sendkey;
+ public string recvkey;
+ public List responsibleForRegions;
+
+ public MessageServerInfo()
+ {
+ }
+
+ public override string ToString()
+ {
+ return URI;
+ }
+ }
+}
diff --git a/OpenSim/Framework/Servers/PostAssetStreamHandler.cs b/OpenSim/Framework/Servers/PostAssetStreamHandler.cs
new file mode 100644
index 0000000..419b408
--- /dev/null
+++ b/OpenSim/Framework/Servers/PostAssetStreamHandler.cs
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) Contributors, http://opensimulator.org/
+ * See CONTRIBUTORS.TXT for a full list of copyright holders.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the OpenSimulator Project nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+using System.IO;
+using System.Reflection;
+using System.Xml.Serialization;
+using log4net;
+using OpenMetaverse;
+using OpenSim.Data;
+using OpenSim.Framework;
+using OpenSim.Framework.Servers.HttpServer;
+
+namespace OpenSim.Framework.Servers
+{
+ public class PostAssetStreamHandler : BaseStreamHandler
+ {
+ private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
+
+ // private OpenAsset_Main m_assetManager;
+ private IAssetDataPlugin m_assetProvider;
+
+ public override byte[] Handle(string path, Stream request,
+ OSHttpRequest httpRequest, OSHttpResponse httpResponse)
+ {
+ string param = GetParam(path);
+
+ UUID assetId;
+ if (param.Length > 0)
+ UUID.TryParse(param, out assetId);
+ // byte[] txBuffer = new byte[4096];
+
+ XmlSerializer xs = new XmlSerializer(typeof (AssetBase));
+ AssetBase asset = (AssetBase) xs.Deserialize(request);
+
+ m_log.InfoFormat("[REST]: Creating asset {0}", asset.FullID);
+ m_assetProvider.CreateAsset(asset);
+
+ return new byte[] {};
+ }
+
+ public PostAssetStreamHandler(IAssetDataPlugin assetProvider)
+ : base("POST", "/assets")
+ {
+ // m_assetManager = assetManager;
+ m_assetProvider = assetProvider;
+ }
+ }
+}
diff --git a/OpenSim/Framework/Servers/Tests/OSHttpTests.cs b/OpenSim/Framework/Servers/Tests/OSHttpTests.cs
new file mode 100644
index 0000000..ee8ab09
--- /dev/null
+++ b/OpenSim/Framework/Servers/Tests/OSHttpTests.cs
@@ -0,0 +1,394 @@
+/*
+ * Copyright (c) Contributors, http://opensimulator.org/
+ * See CONTRIBUTORS.TXT for a full list of copyright holders.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the OpenSim Project nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+using System;
+using System.Collections.Specialized;
+using System.IO;
+using System.Net;
+using System.Net.Sockets;
+using System.Text;
+using HttpServer;
+using HttpServer.FormDecoders;
+using NUnit.Framework;
+using NUnit.Framework.SyntaxHelpers;
+using OpenSim.Framework.Servers.HttpServer;
+
+namespace OpenSim.Framework.Servers.Tests
+{
+ [TestFixture]
+ public class OSHttpTests
+ {
+ // we need an IHttpClientContext for our tests
+ public class TestHttpClientContext: IHttpClientContext
+ {
+ private bool _secured;
+ public bool Secured
+ {
+ get { return _secured; }
+ }
+
+ public TestHttpClientContext(bool secured)
+ {
+ _secured = secured;
+ }
+
+ public void Disconnect(SocketError error) {}
+ public void Respond(string httpVersion, HttpStatusCode statusCode, string reason, string body) {}
+ public void Respond(string httpVersion, HttpStatusCode statusCode, string reason) {}
+ public void Respond(string body) {}
+ public void Send(byte[] buffer) {}
+ public void Send(byte[] buffer, int offset, int size) {}
+ }
+
+ public class TestHttpRequest: IHttpRequest
+ {
+ public bool BodyIsComplete
+ {
+ get { return true; }
+ }
+ public string[] AcceptTypes
+ {
+ get {return _acceptTypes; }
+ }
+ private string[] _acceptTypes;
+ public Stream Body
+ {
+ get { return _body; }
+ set { _body = value;}
+ }
+ private Stream _body;
+ public ConnectionType Connection
+ {
+ get { return _connection; }
+ set { _connection = value; }
+ }
+ private ConnectionType _connection;
+ public int ContentLength
+ {
+ get { return _contentLength; }
+ set { _contentLength = value; }
+ }
+ private int _contentLength;
+ public NameValueCollection Headers
+ {
+ get { return _headers; }
+ }
+ private NameValueCollection _headers = new NameValueCollection();
+ public string HttpVersion
+ {
+ get { return _httpVersion; }
+ set { _httpVersion = value; }
+ }
+ private string _httpVersion = null;
+ public string Method
+ {
+ get { return _method; }
+ set { _method = value; }
+ }
+ private string _method = null;
+ public HttpInput QueryString
+ {
+ get { return _queryString; }
+ }
+ private HttpInput _queryString = null;
+ public Uri Uri
+ {
+ get { return _uri; }
+ set { _uri = value; }
+ }
+ private Uri _uri = null;
+ public string[] UriParts
+ {
+ get { return _uri.Segments; }
+ }
+ public HttpParam Param
+ {
+ get { return null; }
+ }
+ public HttpForm Form
+ {
+ get { return null; }
+ }
+ public bool IsAjax
+ {
+ get { return false; }
+ }
+ public RequestCookies Cookies
+ {
+ get { return null; }
+ }
+
+ public TestHttpRequest() {}
+
+ public TestHttpRequest(string contentEncoding, string contentType, string userAgent,
+ string remoteAddr, string remotePort, string[] acceptTypes,
+ ConnectionType connectionType, int contentLength, Uri uri)
+ {
+ _headers["content-encoding"] = contentEncoding;
+ _headers["content-type"] = contentType;
+ _headers["user-agent"] = userAgent;
+ _headers["remote_addr"] = remoteAddr;
+ _headers["remote_port"] = remotePort;
+
+ _acceptTypes = acceptTypes;
+ _connection = connectionType;
+ _contentLength = contentLength;
+ _uri = uri;
+ }
+
+ public void DecodeBody(FormDecoderProvider providers) {}
+ public void SetCookies(RequestCookies cookies) {}
+ public void AddHeader(string name, string value)
+ {
+ _headers.Add(name, value);
+ }
+ public int AddToBody(byte[] bytes, int offset, int length)
+ {
+ return 0;
+ }
+ public void Clear() {}
+
+ public object Clone()
+ {
+ TestHttpRequest clone = new TestHttpRequest();
+ clone._acceptTypes = _acceptTypes;
+ clone._connection = _connection;
+ clone._contentLength = _contentLength;
+ clone._uri = _uri;
+ clone._headers = new NameValueCollection(_headers);
+
+ return clone;
+ }
+ }
+
+ public class TestHttpResponse: IHttpResponse
+ {
+ public Stream Body
+ {
+ get { return _body; }
+
+ set { _body = value; }
+ }
+ private Stream _body;
+
+ public string ProtocolVersion
+ {
+ get { return _protocolVersion; }
+ set { _protocolVersion = value; }
+ }
+ private string _protocolVersion;
+
+ public bool Chunked
+ {
+ get { return _chunked; }
+
+ set { _chunked = value; }
+ }
+ private bool _chunked;
+
+ public ConnectionType Connection
+ {
+ get { return _connection; }
+
+ set { _connection = value; }
+ }
+ private ConnectionType _connection;
+
+ public Encoding Encoding
+ {
+ get { return _encoding; }
+
+ set { _encoding = value; }
+ }
+ private Encoding _encoding;
+
+ public int KeepAlive
+ {
+ get { return _keepAlive; }
+
+ set { _keepAlive = value; }
+ }
+ private int _keepAlive;
+
+ public HttpStatusCode Status
+ {
+ get { return _status; }
+
+ set { _status = value; }
+ }
+ private HttpStatusCode _status;
+
+ public string Reason
+ {
+ get { return _reason; }
+
+ set { _reason = value; }
+ }
+ private string _reason;
+
+ public long ContentLength
+ {
+ get { return _contentLength; }
+
+ set { _contentLength = value; }
+ }
+ private long _contentLength;
+
+ public string ContentType
+ {
+ get { return _contentType; }
+
+ set { _contentType = value; }
+ }
+ private string _contentType;
+
+ public bool HeadersSent
+ {
+ get { return _headersSent; }
+ }
+ private bool _headersSent;
+
+ public bool Sent
+ {
+ get { return _sent; }
+ }
+ private bool _sent;
+
+ public ResponseCookies Cookies
+ {
+ get { return _cookies; }
+ }
+ private ResponseCookies _cookies = null;
+
+ public TestHttpResponse()
+ {
+ _headersSent = false;
+ _sent = false;
+ }
+
+ public void AddHeader(string name, string value) {}
+ public void Send()
+ {
+ if (!_headersSent) SendHeaders();
+ if (_sent) throw new InvalidOperationException("stuff already sent");
+ _sent = true;
+ }
+
+ public void SendBody(byte[] buffer, int offset, int count)
+ {
+ if (!_headersSent) SendHeaders();
+ _sent = true;
+ }
+ public void SendBody(byte[] buffer)
+ {
+ if (!_headersSent) SendHeaders();
+ _sent = true;
+ }
+
+ public void SendHeaders()
+ {
+ if (_headersSent) throw new InvalidOperationException("headers already sent");
+ _headersSent = true;
+ }
+
+ public void Redirect(Uri uri) {}
+ public void Redirect(string url) {}
+ }
+
+
+ public OSHttpRequest req0;
+ public OSHttpRequest req1;
+
+ public OSHttpResponse rsp0;
+
+ public IPEndPoint ipEP0;
+
+ [TestFixtureSetUp]
+ public void Init()
+ {
+ TestHttpRequest threq0 = new TestHttpRequest("utf-8", "text/xml", "OpenSim Test Agent", "192.168.0.1", "4711",
+ new string[] {"text/xml"},
+ ConnectionType.KeepAlive, 4711,
+ new Uri("http://127.0.0.1/admin/inventory/Dr+Who/Tardis"));
+ threq0.Method = "GET";
+ threq0.HttpVersion = HttpHelper.HTTP10;
+
+ TestHttpRequest threq1 = new TestHttpRequest("utf-8", "text/xml", "OpenSim Test Agent", "192.168.0.1", "4711",
+ new string[] {"text/xml"},
+ ConnectionType.KeepAlive, 4711,
+ new Uri("http://127.0.0.1/admin/inventory/Dr+Who/Tardis?a=0&b=1&c=2"));
+ threq1.Method = "POST";
+ threq1.HttpVersion = HttpHelper.HTTP11;
+ threq1.Headers["x-wuff"] = "wuffwuff";
+ threq1.Headers["www-authenticate"] = "go away";
+
+ req0 = new OSHttpRequest(new TestHttpClientContext(false), threq0);
+ req1 = new OSHttpRequest(new TestHttpClientContext(false), threq1);
+
+ rsp0 = new OSHttpResponse(new TestHttpResponse());
+
+ ipEP0 = new IPEndPoint(IPAddress.Parse("192.168.0.1"), 4711);
+
+ }
+
+ [Test]
+ public void T000_OSHttpRequest()
+ {
+ Assert.That(req0.HttpMethod, Is.EqualTo("GET"));
+ Assert.That(req0.ContentType, Is.EqualTo("text/xml"));
+ Assert.That(req0.ContentLength, Is.EqualTo(4711));
+
+ Assert.That(req1.HttpMethod, Is.EqualTo("POST"));
+ }
+
+ [Test]
+ public void T001_OSHttpRequestHeaderAccess()
+ {
+ Assert.That(req1.Headers["x-wuff"], Is.EqualTo("wuffwuff"));
+ Assert.That(req1.Headers.Get("x-wuff"), Is.EqualTo("wuffwuff"));
+
+ Assert.That(req1.Headers["www-authenticate"], Is.EqualTo("go away"));
+ Assert.That(req1.Headers.Get("www-authenticate"), Is.EqualTo("go away"));
+
+ Assert.That(req0.RemoteIPEndPoint, Is.EqualTo(ipEP0));
+ }
+
+ [Test]
+ public void T002_OSHttpRequestUriParsing()
+ {
+ Assert.That(req0.RawUrl, Is.EqualTo("/admin/inventory/Dr+Who/Tardis"));
+ Assert.That(req1.Url.ToString(), Is.EqualTo("http://127.0.0.1/admin/inventory/Dr+Who/Tardis?a=0&b=1&c=2"));
+ }
+
+ [Test]
+ public void T100_OSHttpResponse()
+ {
+ rsp0.ContentType = "text/xml";
+ Assert.That(rsp0.ContentType, Is.EqualTo("text/xml"));
+ }
+ }
+}
diff --git a/OpenSim/Framework/Servers/VersionInfo.cs b/OpenSim/Framework/Servers/VersionInfo.cs
new file mode 100644
index 0000000..bdf9354
--- /dev/null
+++ b/OpenSim/Framework/Servers/VersionInfo.cs
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) Contributors, http://opensimulator.org/
+ * See CONTRIBUTORS.TXT for a full list of copyright holders.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the OpenSim Project nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+namespace OpenSim
+{
+ public class VersionInfo
+ {
+ ///
+ /// This is the OpenSim version string. Change this if you are releasing a new OpenSim version.
+ ///
+ public readonly static string Version = "OpenSimulator Server 0.6.4"; // stay with 27 chars (used in regioninfo)
+
+ ///
+ /// This is the external interface version. It is separate from the OpenSimulator project version.
+ ///
+ /// This version number should be
+ /// increased by 1 every time a code change makes the previous OpenSimulator revision incompatible
+ /// with the new revision. This will usually be due to interregion or grid facing interface changes.
+ ///
+ /// Changes which are compatible with an older revision (e.g. older revisions experience degraded functionality
+ /// but not outright failure) do not need a version number increment.
+ ///
+ /// Having this version number allows the grid service to reject connections from regions running a version
+ /// of the code that is too old.
+ ///
+ ///
+ public readonly static int MajorInterfaceVersion = 3;
+ }
+}
--
cgit v1.1