From 5e4d6cab00cb29cd088ab7b62ab13aff103b64cb Mon Sep 17 00:00:00 2001 From: onefang Date: Sun, 19 May 2019 21:24:15 +1000 Subject: Dump OpenSim 0.9.0.1 into it's own branch. --- .../Framework/Servers/HttpServer/BaseHttpServer.cs | 204 ++++++++----- .../Servers/HttpServer/BaseRequestHandler.cs | 14 +- .../Servers/HttpServer/BaseStreamHandler.cs | 4 +- .../BaseStreamHandlerBasicDOSProtector.cs | 8 +- .../HttpServer/GenericHTTPBasicDOSProtector.cs | 6 +- .../Servers/HttpServer/Interfaces/IHttpServer.cs | 34 +-- .../HttpServer/Interfaces/IStreamHandler.cs | 2 +- .../Servers/HttpServer/JsonRpcRequestManager.cs | 7 +- .../Servers/HttpServer/JsonRpcResponse.cs | 2 +- .../Framework/Servers/HttpServer/OSHttpRequest.cs | 12 +- .../Framework/Servers/HttpServer/OSHttpResponse.cs | 4 +- .../Servers/HttpServer/OSHttpStatusCodes.cs | 2 +- .../Servers/HttpServer/PollServiceEventArgs.cs | 10 +- .../Servers/HttpServer/PollServiceHttpRequest.cs | 85 +++++- .../HttpServer/PollServiceRequestManager.cs | 327 +++++++++------------ .../Servers/HttpServer/Properties/AssemblyInfo.cs | 10 +- .../Servers/HttpServer/RestDeserialiseHandler.cs | 2 + .../Servers/HttpServer/RestSessionService.cs | 6 +- .../Servers/HttpServer/RestStreamHandler.cs | 7 +- .../Servers/HttpServer/WebsocketServerHandler.cs | 82 +++--- .../Servers/HttpServer/XmlRpcBasicDOSProtector.cs | 6 +- 21 files changed, 463 insertions(+), 371 deletions(-) (limited to 'OpenSim/Framework/Servers/HttpServer') diff --git a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs index f252bd5..f4ba02f 100644 --- a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs +++ b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs @@ -58,7 +58,7 @@ namespace OpenSim.Framework.Servers.HttpServer /// /// This is a pending websocket request before it got an sucessful upgrade response. - /// The consumer must call handler.HandshakeAndUpgrade() to signal to the handler to + /// The consumer must call handler.HandshakeAndUpgrade() to signal to the handler to /// start the connection and optionally provide an origin authentication method. /// /// @@ -104,7 +104,7 @@ namespace OpenSim.Framework.Servers.HttpServer new Dictionary(); protected Dictionary m_WebSocketHandlers = - new Dictionary(); + new Dictionary(); protected uint m_port; protected uint m_sslport; @@ -253,7 +253,7 @@ namespace OpenSim.Framework.Servers.HttpServer return new List(m_rpcHandlers.Keys); } - // JsonRPC + // JsonRPC public bool AddJsonRPCHandler(string method, JsonRPCMethod handler) { lock(jsonRpcHandlers) @@ -399,10 +399,10 @@ namespace OpenSim.Framework.Servers.HttpServer Stream requestStream = req.InputStream; + string requestBody; Encoding encoding = Encoding.UTF8; - StreamReader reader = new StreamReader(requestStream, encoding); - - string requestBody = reader.ReadToEnd(); + using(StreamReader reader = new StreamReader(requestStream, encoding)) + requestBody = reader.ReadToEnd(); Hashtable keysvals = new Hashtable(); Hashtable headervals = new Hashtable(); @@ -458,10 +458,11 @@ namespace OpenSim.Framework.Servers.HttpServer dWebSocketRequestDelegate(req.Url.AbsolutePath, new WebSocketHttpServerHandler(req, context, 8192)); return; } - + OSHttpResponse resp = new OSHttpResponse(new HttpResponse(context, request),context); resp.ReuseContext = true; - HandleRequest(req, resp); +// resp.ReuseContext = false; + HandleRequest(req, resp); // !!!HACK ALERT!!! // There seems to be a bug in the underlying http code that makes subsequent requests @@ -552,7 +553,7 @@ namespace OpenSim.Framework.Servers.HttpServer LogIncomingToStreamHandler(request, requestHandler); response.ContentType = requestHandler.ContentType; // Lets do this defaulting before in case handler has varying content type. - + if (requestHandler is IStreamedRequestHandler) { IStreamedRequestHandler streamedRequestHandler = requestHandler as IStreamedRequestHandler; @@ -565,13 +566,10 @@ namespace OpenSim.Framework.Servers.HttpServer IGenericHTTPHandler HTTPRequestHandler = requestHandler as IGenericHTTPHandler; Stream requestStream = request.InputStream; + string requestBody; Encoding encoding = Encoding.UTF8; - StreamReader reader = new StreamReader(requestStream, encoding); - - string requestBody = reader.ReadToEnd(); - - reader.Close(); - //requestStream.Close(); + using(StreamReader reader = new StreamReader(requestStream, encoding)) + requestBody = reader.ReadToEnd(); Hashtable keysvals = new Hashtable(); Hashtable headervals = new Hashtable(); @@ -628,16 +626,16 @@ namespace OpenSim.Framework.Servers.HttpServer case "text/html": if (DebugLevel >= 3) LogIncomingToContentTypeHandler(request); - + buffer = HandleHTTPRequest(request, response); break; - + case "application/llsd+xml": case "application/xml+llsd": case "application/llsd+json": if (DebugLevel >= 3) LogIncomingToContentTypeHandler(request); - + buffer = HandleLLSDRequests(request, response); break; @@ -647,7 +645,7 @@ namespace OpenSim.Framework.Servers.HttpServer buffer = HandleJsonRpcRequests(request, response); break; - + case "text/xml": case "application/xml": case "application/json": @@ -664,7 +662,7 @@ namespace OpenSim.Framework.Servers.HttpServer { if (DebugLevel >= 3) LogIncomingToContentTypeHandler(request); - + buffer = HandleLLSDRequests(request, response); } // m_log.DebugFormat("[BASE HTTP SERVER]: Checking for HTTP Handler for request {0}", request.RawUrl); @@ -672,23 +670,24 @@ namespace OpenSim.Framework.Servers.HttpServer { if (DebugLevel >= 3) LogIncomingToContentTypeHandler(request); - + buffer = HandleHTTPRequest(request, response); } else { if (DebugLevel >= 3) LogIncomingToXmlRpcHandler(request); - + // generic login request. buffer = HandleXmlRpcRequests(request, response); } - + break; } } - request.InputStream.Close(); + if(request.InputStream.CanRead) + request.InputStream.Dispose(); if (buffer != null) { @@ -759,7 +758,7 @@ namespace OpenSim.Framework.Servers.HttpServer // Every month or so this will wrap and give bad numbers, not really a problem // since its just for reporting int tickdiff = requestEndTick - requestStartTick; - if (tickdiff > 3000 && requestHandler != null && requestHandler.Name != "GetTexture") + if (tickdiff > 3000 && (requestHandler == null || requestHandler.Name == null || requestHandler.Name != "GetTexture")) { m_log.InfoFormat( "[LOGHTTP] Slow handling of {0} {1} {2} {3} {4} from {5} took {6}ms", @@ -970,7 +969,7 @@ namespace OpenSim.Framework.Servers.HttpServer // private bool TryGetAgentHandler(OSHttpRequest request, OSHttpResponse response, out IHttpAgentHandler agentHandler) // { // agentHandler = null; -// +// // lock (m_agentHandlers) // { // foreach (IHttpAgentHandler handler in m_agentHandlers.Values) @@ -996,7 +995,7 @@ namespace OpenSim.Framework.Servers.HttpServer { String requestBody; - Stream requestStream = request.InputStream; + Stream requestStream = Util.Copy(request.InputStream); Stream innerStream = null; try { @@ -1007,9 +1006,8 @@ namespace OpenSim.Framework.Servers.HttpServer } using (StreamReader reader = new StreamReader(requestStream, Encoding.UTF8)) - { requestBody = reader.ReadToEnd(); - } + } finally { @@ -1024,6 +1022,19 @@ namespace OpenSim.Framework.Servers.HttpServer string responseString = String.Empty; XmlRpcRequest xmlRprcRequest = null; + bool gridproxy = false; + if (requestBody.Contains("encoding=\"utf-8")) + { + int channelindx = -1; + int optionsindx = requestBody.IndexOf(">options<"); + if(optionsindx >0) + { + channelindx = requestBody.IndexOf(">channel<"); + if (optionsindx < channelindx) + gridproxy = true; + } + } + try { xmlRprcRequest = (XmlRpcRequest) (new XmlRpcRequestDeserializer()).Deserialize(requestBody); @@ -1081,6 +1092,8 @@ namespace OpenSim.Framework.Servers.HttpServer } xmlRprcRequest.Params.Add(request.Headers.Get(xff)); // Param[3] + if (gridproxy) + xmlRprcRequest.Params.Add("gridproxy"); // Param[4] try { xmlRpcResponse = method(xmlRprcRequest, request.RemoteIPEndPoint); @@ -1154,7 +1167,7 @@ namespace OpenSim.Framework.Servers.HttpServer return buffer; } - // JsonRpc (v2.0 only) + // JsonRpc (v2.0 only) // Batch requests not yet supported private byte[] HandleJsonRpcRequests(OSHttpRequest request, OSHttpResponse response) { @@ -1171,7 +1184,7 @@ namespace OpenSim.Framework.Servers.HttpServer jsonRpcResponse.Error.Code = ErrorCode.InternalError; jsonRpcResponse.Error.Message = e.Message; } - + requestStream.Close(); if (jsonRpcRequest != null) @@ -1236,7 +1249,7 @@ namespace OpenSim.Framework.Servers.HttpServer string responseData = string.Empty; responseData = jsonRpcResponse.Serialize(); - + byte[] buffer = Encoding.UTF8.GetBytes(responseData); return buffer; } @@ -1246,12 +1259,10 @@ namespace OpenSim.Framework.Servers.HttpServer //m_log.Warn("[BASE HTTP SERVER]: We've figured out it's a LLSD Request"); Stream requestStream = request.InputStream; + string requestBody; Encoding encoding = Encoding.UTF8; - StreamReader reader = new StreamReader(requestStream, encoding); - - string requestBody = reader.ReadToEnd(); - reader.Close(); - requestStream.Close(); + using(StreamReader reader = new StreamReader(requestStream, encoding)) + requestBody= reader.ReadToEnd(); //m_log.DebugFormat("[OGP]: {0}:{1}", request.RawUrl, requestBody); response.KeepAlive = true; @@ -1516,7 +1527,7 @@ namespace OpenSim.Framework.Servers.HttpServer } } } - + if (String.IsNullOrEmpty(bestMatch)) { llsdHandler = null; @@ -1575,15 +1586,10 @@ namespace OpenSim.Framework.Servers.HttpServer byte[] buffer; Stream requestStream = request.InputStream; - + string requestBody; Encoding encoding = Encoding.UTF8; - StreamReader reader = new StreamReader(requestStream, encoding); - - string requestBody = reader.ReadToEnd(); - // avoid warning for now - reader.ReadToEnd(); - reader.Close(); - requestStream.Close(); + using(StreamReader reader = new StreamReader(requestStream, encoding)) + requestBody = reader.ReadToEnd(); Hashtable keysvals = new Hashtable(); Hashtable headervals = new Hashtable(); @@ -1732,10 +1738,40 @@ namespace OpenSim.Framework.Servers.HttpServer internal byte[] 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"]; + int responsecode; + string responseString = String.Empty; + byte[] responseData = null; + string contentType; + + if (responsedata == null) + { + responsecode = 500; + responseString = "No response could be obtained"; + contentType = "text/plain"; + responsedata = new Hashtable(); + } + else + { + try + { + //m_log.Info("[BASE HTTP SERVER]: Doing HTTP Grunt work with response"); + responsecode = (int)responsedata["int_response_code"]; + if (responsedata["bin_response_data"] != null) + responseData = (byte[])responsedata["bin_response_data"]; + else + responseString = (string)responsedata["str_response_string"]; + contentType = (string)responsedata["content_type"]; + if (responseString == null) + responseString = String.Empty; + } + catch + { + responsecode = 500; + responseString = "No response could be obtained"; + contentType = "text/plain"; + responsedata = new Hashtable(); + } + } if (responsedata.ContainsKey("error_status_text")) { @@ -1745,16 +1781,19 @@ namespace OpenSim.Framework.Servers.HttpServer { response.ProtocolVersion = (string)responsedata["http_protocol_version"]; } - +/* if (responsedata.ContainsKey("keepalive")) { bool keepalive = (bool)responsedata["keepalive"]; response.KeepAlive = keepalive; - } if (responsedata.ContainsKey("reusecontext")) response.ReuseContext = (bool) responsedata["reusecontext"]; +*/ + // disable this things + response.KeepAlive = false; + response.ReuseContext = false; // Cross-Origin Resource Sharing with simple requests if (responsedata.ContainsKey("access_control_allow_origin")) @@ -1768,8 +1807,11 @@ namespace OpenSim.Framework.Servers.HttpServer 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) @@ -1780,25 +1822,40 @@ namespace OpenSim.Framework.Servers.HttpServer response.AddHeader("Content-Type", contentType); + if (responsedata.ContainsKey("headers")) + { + Hashtable headerdata = (Hashtable)responsedata["headers"]; + + foreach (string header in headerdata.Keys) + response.AddHeader(header, headerdata[header].ToString()); + } + byte[] buffer; - if (!(contentType.Contains("image") - || contentType.Contains("x-shockwave-flash") - || contentType.Contains("application/x-oar") - || contentType.Contains("application/vnd.ll.mesh"))) + if (responseData != null) { - // Text - buffer = Encoding.UTF8.GetBytes(responseString); + buffer = responseData; } else { - // Binary! - buffer = Convert.FromBase64String(responseString); - } + if (!(contentType.Contains("image") + || contentType.Contains("x-shockwave-flash") + || contentType.Contains("application/x-oar") + || contentType.Contains("application/vnd.ll.mesh"))) + { + // Text + buffer = Encoding.UTF8.GetBytes(responseString); + } + else + { + // Binary! + buffer = Convert.FromBase64String(responseString); + } - response.SendChunked = false; - response.ContentLength64 = buffer.Length; - response.ContentEncoding = Encoding.UTF8; + response.SendChunked = false; + response.ContentLength64 = buffer.Length; + response.ContentEncoding = Encoding.UTF8; + } return buffer; } @@ -1831,8 +1888,8 @@ namespace OpenSim.Framework.Servers.HttpServer response.SendChunked = false; response.ContentLength64 = buffer.Length; response.ContentEncoding = Encoding.UTF8; - - + + return buffer; } @@ -1886,7 +1943,8 @@ namespace OpenSim.Framework.Servers.HttpServer m_httpListener2.Start(64); // Long Poll Service Manager with 3 worker threads a 25 second timeout for no events - PollServiceRequestManager = new PollServiceRequestManager(this, performPollResponsesAsync, 3, 25000); + + PollServiceRequestManager = new PollServiceRequestManager(this, performPollResponsesAsync, 2, 25000); PollServiceRequestManager.Start(); HTTPDRunning = true; @@ -1908,7 +1966,7 @@ namespace OpenSim.Framework.Servers.HttpServer throw e; } - m_requestsProcessedStat + m_requestsProcessedStat = new Stat( "HTTPRequestsServed", "Number of inbound HTTP requests processed", @@ -1920,7 +1978,7 @@ namespace OpenSim.Framework.Servers.HttpServer MeasuresOfInterest.AverageChangeOverTime, stat => stat.Value = RequestNumber, StatVerbosity.Debug); - + StatsManager.RegisterStat(m_requestsProcessedStat); } @@ -1937,7 +1995,9 @@ namespace OpenSim.Framework.Servers.HttpServer public void httpServerException(object source, Exception exception) { - m_log.Error(String.Format("[BASE HTTP SERVER]: {0} had an exception: {1} ", source.ToString(), exception.Message), exception); + if (source.ToString() == "HttpServer.HttpListener" && exception.ToString().StartsWith("Mono.Security.Protocol.Tls.TlsException")) + return; + m_log.ErrorFormat("[BASE HTTP SERVER]: {0} had an exception {1}", source.ToString(), exception.ToString()); /* if (HTTPDRunning)// && NotSocketErrors > 5) { @@ -1957,7 +2017,8 @@ namespace OpenSim.Framework.Servers.HttpServer try { - PollServiceRequestManager.Stop(); + if(PollServiceRequestManager != null) + PollServiceRequestManager.Stop(); m_httpListener2.ExceptionThrown -= httpServerException; //m_httpListener2.DisconnectHandler = null; @@ -1984,6 +2045,7 @@ namespace OpenSim.Framework.Servers.HttpServer public void RemoveHTTPHandler(string httpMethod, string path) { + if (path == null) return; // Caps module isn't loaded, tries to remove handler where path = null lock (m_HTTPHandlers) { if (httpMethod != null && httpMethod.Length == 0) diff --git a/OpenSim/Framework/Servers/HttpServer/BaseRequestHandler.cs b/OpenSim/Framework/Servers/HttpServer/BaseRequestHandler.cs index d4a1ec3..01d95e9 100644 --- a/OpenSim/Framework/Servers/HttpServer/BaseRequestHandler.cs +++ b/OpenSim/Framework/Servers/HttpServer/BaseRequestHandler.cs @@ -69,13 +69,13 @@ namespace OpenSim.Framework.Servers.HttpServer { StatsManager.RegisterStat( new Stat( - "requests", - "requests", - "Number of requests received by this service endpoint", - "requests", - "service", - string.Format("{0}:{1}", httpMethod, path), - StatType.Pull, + "requests", + "requests", + "Number of requests received by this service endpoint", + "requests", + "service", + string.Format("{0}:{1}", httpMethod, path), + StatType.Pull, MeasuresOfInterest.AverageChangeOverTime, s => s.Value = RequestsReceived, StatVerbosity.Debug)); diff --git a/OpenSim/Framework/Servers/HttpServer/BaseStreamHandler.cs b/OpenSim/Framework/Servers/HttpServer/BaseStreamHandler.cs index 41aa19b..7fc9f0b 100644 --- a/OpenSim/Framework/Servers/HttpServer/BaseStreamHandler.cs +++ b/OpenSim/Framework/Servers/HttpServer/BaseStreamHandler.cs @@ -47,7 +47,7 @@ namespace OpenSim.Framework.Servers.HttpServer : base(httpMethod, path, name, description) {} protected BaseStreamHandler(string httpMethod, string path, IServiceAuth auth) - : base(httpMethod, path, null, null) + : base(httpMethod, path, null, null) { m_Auth = auth; } @@ -62,7 +62,7 @@ namespace OpenSim.Framework.Servers.HttpServer HttpStatusCode statusCode; if (!m_Auth.Authenticate(httpRequest.Headers, httpResponse.AddHeader, out statusCode)) - { + { httpResponse.StatusCode = (int)statusCode; httpResponse.ContentType = "text/plain"; return new byte[0]; diff --git a/OpenSim/Framework/Servers/HttpServer/BaseStreamHandlerBasicDOSProtector.cs b/OpenSim/Framework/Servers/HttpServer/BaseStreamHandlerBasicDOSProtector.cs index 1b88545..9619e03 100644 --- a/OpenSim/Framework/Servers/HttpServer/BaseStreamHandlerBasicDOSProtector.cs +++ b/OpenSim/Framework/Servers/HttpServer/BaseStreamHandlerBasicDOSProtector.cs @@ -37,7 +37,7 @@ namespace OpenSim.Framework.Servers.HttpServer /// public abstract class BaseStreamHandlerBasicDOSProtector : BaseRequestHandler, IStreamedRequestHandler { - + private readonly BasicDosProtectorOptions _options; private readonly BasicDOSProtector _dosProtector; @@ -63,7 +63,7 @@ namespace OpenSim.Framework.Servers.HttpServer result = ThrottledRequest(path, request, httpRequest, httpResponse); if (_options.MaxConcurrentSessions > 0) _dosProtector.ProcessEnd(clientstring, endpoint); - + RequestsHandled++; return result; @@ -81,7 +81,7 @@ namespace OpenSim.Framework.Servers.HttpServer return new byte[0]; } - + private string GetRemoteAddr(IOSHttpRequest httpRequest) { string remoteaddr = string.Empty; @@ -101,7 +101,7 @@ namespace OpenSim.Framework.Servers.HttpServer clientstring = GetRemoteAddr(httpRequest); return clientstring; - + } } } diff --git a/OpenSim/Framework/Servers/HttpServer/GenericHTTPBasicDOSProtector.cs b/OpenSim/Framework/Servers/HttpServer/GenericHTTPBasicDOSProtector.cs index cd4b8ff..98d33e4 100644 --- a/OpenSim/Framework/Servers/HttpServer/GenericHTTPBasicDOSProtector.cs +++ b/OpenSim/Framework/Servers/HttpServer/GenericHTTPBasicDOSProtector.cs @@ -33,7 +33,7 @@ namespace OpenSim.Framework.Servers.HttpServer { private readonly GenericHTTPMethod _normalMethod; private readonly GenericHTTPMethod _throttledMethod; - + private readonly BasicDosProtectorOptions _options; private readonly BasicDOSProtector _dosProtector; @@ -41,7 +41,7 @@ namespace OpenSim.Framework.Servers.HttpServer { _normalMethod = normalMethod; _throttledMethod = throttledMethod; - + _options = options; _dosProtector = new BasicDOSProtector(_options); } @@ -60,7 +60,7 @@ namespace OpenSim.Framework.Servers.HttpServer return process; } - + private string GetRemoteAddr(Hashtable request) { string remoteaddr = ""; diff --git a/OpenSim/Framework/Servers/HttpServer/Interfaces/IHttpServer.cs b/OpenSim/Framework/Servers/HttpServer/Interfaces/IHttpServer.cs index d162bc1..3a04074 100644 --- a/OpenSim/Framework/Servers/HttpServer/Interfaces/IHttpServer.cs +++ b/OpenSim/Framework/Servers/HttpServer/Interfaces/IHttpServer.cs @@ -45,26 +45,26 @@ namespace OpenSim.Framework.Servers.HttpServer // // 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= - /// + /// 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/ /// /// In addition, the handler invoked by the HTTP server for any request is the one when best matches the request @@ -87,7 +87,7 @@ namespace OpenSim.Framework.Servers.HttpServer /// 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. /// @@ -98,7 +98,7 @@ namespace OpenSim.Framework.Servers.HttpServer bool AddXmlRPCHandler(string method, XmlRpcMethod handler, bool keepAlive); bool AddJsonRPCHandler(string method, JsonRPCMethod handler); - + /// /// Websocket HTTP server handlers. /// @@ -108,7 +108,7 @@ namespace OpenSim.Framework.Servers.HttpServer void RemoveWebSocketHandler(string servicepath); - + /// /// Gets the XML RPC handler for given method name /// @@ -125,7 +125,7 @@ namespace OpenSim.Framework.Servers.HttpServer // /// // /// // bool RemoveAgentHandler(string agent, IHttpAgentHandler handler); - + /// /// Remove an HTTP handler /// @@ -134,15 +134,15 @@ namespace OpenSim.Framework.Servers.HttpServer void RemoveHTTPHandler(string httpMethod, string path); void RemovePollServiceHTTPHandler(string httpMethod, string path); - + bool RemoveLLSDHandler(string path, LLSDMethod handler); - + void RemoveStreamHandler(string httpMethod, string path); void RemoveXmlRPCHandler(string method); void RemoveJsonRPCHandler(string method); - + string GetHTTP404(string host); string GetHTTP500(); diff --git a/OpenSim/Framework/Servers/HttpServer/Interfaces/IStreamHandler.cs b/OpenSim/Framework/Servers/HttpServer/Interfaces/IStreamHandler.cs index b8541cb..62d92fb 100644 --- a/OpenSim/Framework/Servers/HttpServer/Interfaces/IStreamHandler.cs +++ b/OpenSim/Framework/Servers/HttpServer/Interfaces/IStreamHandler.cs @@ -83,7 +83,7 @@ namespace OpenSim.Framework.Servers.HttpServer { void Handle(string path, Stream request, Stream response, IOSHttpRequest httpReqbuest, IOSHttpResponse httpResponse); } - + public interface IGenericHTTPHandler : IRequestHandler { Hashtable Handle(string path, Hashtable request); diff --git a/OpenSim/Framework/Servers/HttpServer/JsonRpcRequestManager.cs b/OpenSim/Framework/Servers/HttpServer/JsonRpcRequestManager.cs index 2fe1a7d..411ee31 100644 --- a/OpenSim/Framework/Servers/HttpServer/JsonRpcRequestManager.cs +++ b/OpenSim/Framework/Servers/HttpServer/JsonRpcRequestManager.cs @@ -43,7 +43,7 @@ namespace OpenSim.Framework.Servers.HttpServer public class JsonRpcRequestManager { static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - + public JsonRpcRequestManager() { } @@ -77,6 +77,9 @@ namespace OpenSim.Framework.Servers.HttpServer if (parameters == null) throw new ArgumentNullException("parameters"); + if(string.IsNullOrWhiteSpace(uri)) + return false; + OSDMap request = new OSDMap(); request.Add("jsonrpc", OSD.FromString("2.0")); request.Add("id", OSD.FromString(jsonId)); @@ -185,6 +188,6 @@ namespace OpenSim.Framework.Servers.HttpServer return true; } - + } } diff --git a/OpenSim/Framework/Servers/HttpServer/JsonRpcResponse.cs b/OpenSim/Framework/Servers/HttpServer/JsonRpcResponse.cs index 2c50587..91d284b 100644 --- a/OpenSim/Framework/Servers/HttpServer/JsonRpcResponse.cs +++ b/OpenSim/Framework/Servers/HttpServer/JsonRpcResponse.cs @@ -144,7 +144,7 @@ namespace OpenSim.Framework.Servers.HttpServer { } - return result; + return result; } } } diff --git a/OpenSim/Framework/Servers/HttpServer/OSHttpRequest.cs b/OpenSim/Framework/Servers/HttpServer/OSHttpRequest.cs index 05ec6dc..1a6b8cf 100644 --- a/OpenSim/Framework/Servers/HttpServer/OSHttpRequest.cs +++ b/OpenSim/Framework/Servers/HttpServer/OSHttpRequest.cs @@ -155,11 +155,11 @@ namespace OpenSim.Framework.Servers.HttpServer private string _userAgent; internal IHttpRequest IHttpRequest - { + { get { return _request; } } - internal IHttpClientContext IHttpClientContext + internal IHttpClientContext IHttpClientContext { get { return _context; } } @@ -192,19 +192,19 @@ namespace OpenSim.Framework.Servers.HttpServer // ignore } } - + 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"]); // sometimes req.Headers["remote_port"] returns a comma separated list, so use - // the first one in the list and log it + // the first one in the list and log it string[] strPorts = req.Headers["remote_port"].Split(new char[] { ',' }); if (strPorts.Length > 1) { @@ -216,7 +216,7 @@ namespace OpenSim.Framework.Servers.HttpServer } catch (FormatException) { - _log.ErrorFormat("[OSHttpRequest]: format exception on addr/port {0}:{1}, ignoring", + _log.ErrorFormat("[OSHttpRequest]: format exception on addr/port {0}:{1}, ignoring", req.Headers["remote_addr"], req.Headers["remote_port"]); } } diff --git a/OpenSim/Framework/Servers/HttpServer/OSHttpResponse.cs b/OpenSim/Framework/Servers/HttpServer/OSHttpResponse.cs index 89fb5d4..d7744fc 100644 --- a/OpenSim/Framework/Servers/HttpServer/OSHttpResponse.cs +++ b/OpenSim/Framework/Servers/HttpServer/OSHttpResponse.cs @@ -115,7 +115,7 @@ namespace OpenSim.Framework.Servers.HttpServer public bool KeepAlive { - get + get { return _httpResponse.Connection == ConnectionType.KeepAlive; } @@ -148,6 +148,7 @@ namespace OpenSim.Framework.Servers.HttpServer _httpResponse.Connection = ConnectionType.Close; _httpResponse.KeepAlive = 0; } + else { _httpResponse.Connection = ConnectionType.KeepAlive; @@ -320,6 +321,7 @@ namespace OpenSim.Framework.Servers.HttpServer public void Send() { _httpResponse.Body.Flush(); + _httpResponse.Send(); } diff --git a/OpenSim/Framework/Servers/HttpServer/OSHttpStatusCodes.cs b/OpenSim/Framework/Servers/HttpServer/OSHttpStatusCodes.cs index a736c8b..88e3068 100644 --- a/OpenSim/Framework/Servers/HttpServer/OSHttpStatusCodes.cs +++ b/OpenSim/Framework/Servers/HttpServer/OSHttpStatusCodes.cs @@ -91,7 +91,7 @@ namespace OpenSim.Framework.Servers.HttpServer /// 300 Redirect: different presentation forms available, take a pick /// RedirectMultipleChoices = 300, - + /// /// 301 Redirect: requested resource has moved and now lives somewhere else /// diff --git a/OpenSim/Framework/Servers/HttpServer/PollServiceEventArgs.cs b/OpenSim/Framework/Servers/HttpServer/PollServiceEventArgs.cs index 9477100..7150aad 100644 --- a/OpenSim/Framework/Servers/HttpServer/PollServiceEventArgs.cs +++ b/OpenSim/Framework/Servers/HttpServer/PollServiceEventArgs.cs @@ -46,13 +46,15 @@ namespace OpenSim.Framework.Servers.HttpServer public RequestMethod Request; public UUID Id; public int TimeOutms; - public EventType Type; + public EventType Type; public enum EventType : int { - LongPoll = 0, + Poll = 0, LslHttp = 1, - Inventory = 2 + Inventory = 2, + Texture = 3, + Mesh = 4 } public string Url { get; set; } @@ -80,7 +82,7 @@ namespace OpenSim.Framework.Servers.HttpServer NoEvents = pNoEvents; Id = pId; TimeOutms = pTimeOutms; - Type = EventType.LongPoll; + Type = EventType.Poll; } } } diff --git a/OpenSim/Framework/Servers/HttpServer/PollServiceHttpRequest.cs b/OpenSim/Framework/Servers/HttpServer/PollServiceHttpRequest.cs index caf0e98..fefcb20 100644 --- a/OpenSim/Framework/Servers/HttpServer/PollServiceHttpRequest.cs +++ b/OpenSim/Framework/Servers/HttpServer/PollServiceHttpRequest.cs @@ -27,6 +27,7 @@ using System; using System.Collections; +using System.Collections.Generic; using System.Reflection; using System.Text; using HttpServer; @@ -44,6 +45,24 @@ namespace OpenSim.Framework.Servers.HttpServer public readonly IHttpRequest Request; public readonly int RequestTime; public readonly UUID RequestID; + public int contextHash; + + private void GenContextHash() + { + Random rnd = new Random(); + contextHash = 0; + if (Request.Headers["remote_addr"] != null) + contextHash = (Request.Headers["remote_addr"]).GetHashCode() << 16; + else + contextHash = rnd.Next() << 16; + if (Request.Headers["remote_port"] != null) + { + string[] strPorts = Request.Headers["remote_port"].Split(new char[] { ',' }); + contextHash += Int32.Parse(strPorts[0]); + } + else + contextHash += rnd.Next() & 0xffff; + } public PollServiceHttpRequest( PollServiceEventArgs pPollServiceArgs, IHttpClientContext pHttpContext, IHttpRequest pRequest) @@ -53,6 +72,7 @@ namespace OpenSim.Framework.Servers.HttpServer Request = pRequest; RequestTime = System.Environment.TickCount; RequestID = UUID.Random(); + GenContextHash(); } internal void DoHTTPGruntWork(BaseHttpServer server, Hashtable responsedata) @@ -62,36 +82,69 @@ namespace OpenSim.Framework.Servers.HttpServer byte[] buffer = server.DoHTTPGruntWork(responsedata, response); + if(Request.Body.CanRead) + Request.Body.Dispose(); + response.SendChunked = false; response.ContentLength64 = buffer.Length; response.ContentEncoding = Encoding.UTF8; + response.ReuseContext = false; try { response.OutputStream.Write(buffer, 0, buffer.Length); + response.OutputStream.Flush(); + response.Send(); + buffer = null; } catch (Exception ex) { m_log.Warn("[POLL SERVICE WORKER THREAD]: Error ", ex); } - finally + + PollServiceArgs.RequestsHandled++; + } + + internal void DoHTTPstop(BaseHttpServer server) + { + OSHttpResponse response + = new OSHttpResponse(new HttpResponse(HttpContext, Request), HttpContext); + + if(Request.Body.CanRead) + Request.Body.Dispose(); + + response.SendChunked = false; + response.ContentLength64 = 0; + response.ContentEncoding = Encoding.UTF8; + response.ReuseContext = false; + response.KeepAlive = false; + response.SendChunked = false; + response.StatusCode = 503; + + try { - //response.OutputStream.Close(); - try - { - response.OutputStream.Flush(); - response.Send(); - - //if (!response.KeepAlive && response.ReuseContext) - // response.FreeContext(); - } - catch (Exception e) - { - m_log.Warn("[POLL SERVICE WORKER THREAD]: Error ", e); - } - - PollServiceArgs.RequestsHandled++; + response.OutputStream.Flush(); + response.Send(); } + catch (Exception e) + { + } + } + } + + class PollServiceHttpRequestComparer : IEqualityComparer + { + public bool Equals(PollServiceHttpRequest b1, PollServiceHttpRequest b2) + { + if (b1.contextHash != b2.contextHash) + return false; + bool b = Object.ReferenceEquals(b1.HttpContext, b2.HttpContext); + return b; + } + + public int GetHashCode(PollServiceHttpRequest b2) + { + return (int)b2.contextHash; } } } \ No newline at end of file diff --git a/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs b/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs index 28bba70..c6a3e65 100644 --- a/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs +++ b/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs @@ -44,200 +44,183 @@ namespace OpenSim.Framework.Servers.HttpServer { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - /// - /// Is the poll service request manager running? - /// - /// - /// Can be running either synchronously or asynchronously - /// - public bool IsRunning { get; private set; } - - /// - /// Is the poll service performing responses asynchronously (with its own threads) or synchronously (via - /// external calls)? - /// - public bool PerformResponsesAsync { get; private set; } - - /// - /// Number of responses actually processed and sent to viewer (or aborted due to error). - /// - public int ResponsesProcessed { get; private set; } - private readonly BaseHttpServer m_server; + private Dictionary> m_bycontext; private BlockingQueue m_requests = new BlockingQueue(); - private static List m_longPollRequests = new List(); + private static Queue m_retryRequests = new Queue(); private uint m_WorkerThreadCount = 0; private Thread[] m_workerThreads; + private Thread m_retrysThread; - private SmartThreadPool m_threadPool = new SmartThreadPool(20000, 12, 2); + private bool m_running = false; -// private int m_timeout = 1000; // increase timeout 250; now use the event one + private SmartThreadPool m_threadPool; public PollServiceRequestManager( BaseHttpServer pSrv, bool performResponsesAsync, uint pWorkerThreadCount, int pTimeout) { m_server = pSrv; - PerformResponsesAsync = performResponsesAsync; m_WorkerThreadCount = pWorkerThreadCount; m_workerThreads = new Thread[m_WorkerThreadCount]; - StatsManager.RegisterStat( - new Stat( - "QueuedPollResponses", - "Number of poll responses queued for processing.", - "", - "", - "httpserver", - m_server.Port.ToString(), - StatType.Pull, - MeasuresOfInterest.AverageChangeOverTime, - stat => stat.Value = m_requests.Count(), - StatVerbosity.Debug)); - - StatsManager.RegisterStat( - new Stat( - "ProcessedPollResponses", - "Number of poll responses processed.", - "", - "", - "httpserver", - m_server.Port.ToString(), - StatType.Pull, - MeasuresOfInterest.AverageChangeOverTime, - stat => stat.Value = ResponsesProcessed, - StatVerbosity.Debug)); + PollServiceHttpRequestComparer preqCp = new PollServiceHttpRequestComparer(); + m_bycontext = new Dictionary>(preqCp); + + STPStartInfo startInfo = new STPStartInfo(); + startInfo.IdleTimeout = 30000; + startInfo.MaxWorkerThreads = 20; + startInfo.MinWorkerThreads = 1; + startInfo.ThreadPriority = ThreadPriority.Normal; + startInfo.StartSuspended = true; + startInfo.ThreadPoolName = "PoolService"; + + m_threadPool = new SmartThreadPool(startInfo); } public void Start() { - IsRunning = true; - - if (PerformResponsesAsync) + m_running = true; + m_threadPool.Start(); + //startup worker threads + for (uint i = 0; i < m_WorkerThreadCount; i++) { - //startup worker threads - for (uint i = 0; i < m_WorkerThreadCount; i++) - { - m_workerThreads[i] - = WorkManager.StartThread( - PoolWorkerJob, - string.Format("PollServiceWorkerThread{0}:{1}", i, m_server.Port), - ThreadPriority.Normal, - false, - false, - null, - int.MaxValue); - } - - WorkManager.StartThread( - this.CheckLongPollThreads, - string.Format("LongPollServiceWatcherThread:{0}", m_server.Port), - ThreadPriority.Normal, - false, - true, - null, - 1000 * 60 * 10); + m_workerThreads[i] + = WorkManager.StartThread( + PoolWorkerJob, + string.Format("PollServiceWorkerThread {0}:{1}", i, m_server.Port), + ThreadPriority.Normal, + true, + false, + null, + int.MaxValue); } + + m_retrysThread = WorkManager.StartThread( + this.CheckRetries, + string.Format("PollServiceWatcherThread:{0}", m_server.Port), + ThreadPriority.Normal, + true, + true, + null, + 1000 * 60 * 10); + + } private void ReQueueEvent(PollServiceHttpRequest req) { - if (IsRunning) + if (m_running) { - // delay the enqueueing for 100ms. There's no need to have the event - // actively on the queue - Timer t = new Timer(self => { - ((Timer)self).Dispose(); - m_requests.Enqueue(req); - }); - - t.Change(100, Timeout.Infinite); - + lock (m_retryRequests) + m_retryRequests.Enqueue(req); } } public void Enqueue(PollServiceHttpRequest req) { - if (IsRunning) + lock (m_bycontext) { - if (req.PollServiceArgs.Type == PollServiceEventArgs.EventType.LongPoll) + Queue ctxQeueue; + if (m_bycontext.TryGetValue(req, out ctxQeueue)) { - lock (m_longPollRequests) - m_longPollRequests.Add(req); + ctxQeueue.Enqueue(req); } else - m_requests.Enqueue(req); + { + ctxQeueue = new Queue(); + m_bycontext[req] = ctxQeueue; + EnqueueInt(req); + } } } - private void CheckLongPollThreads() + public void byContextDequeue(PollServiceHttpRequest req) { - // The only purpose of this thread is to check the EQs for events. - // If there are events, that thread will be placed in the "ready-to-serve" queue, m_requests. - // If there are no events, that thread will be back to its "waiting" queue, m_longPollRequests. - // All other types of tasks (Inventory handlers, http-in, etc) don't have the long-poll nature, - // so if they aren't ready to be served by a worker thread (no events), they are placed - // directly back in the "ready-to-serve" queue by the worker thread. - while (IsRunning) + Queue ctxQeueue; + lock (m_bycontext) { - Thread.Sleep(500); - Watchdog.UpdateThread(); - -// List not_ready = new List(); - lock (m_longPollRequests) + if (m_bycontext.TryGetValue(req, out ctxQeueue)) { - if (m_longPollRequests.Count > 0 && IsRunning) + if (ctxQeueue.Count > 0) + { + PollServiceHttpRequest newreq = ctxQeueue.Dequeue(); + EnqueueInt(newreq); + } + else { - List ready = m_longPollRequests.FindAll(req => - (req.PollServiceArgs.HasEvents(req.RequestID, req.PollServiceArgs.Id) || // there are events in this EQ - (Environment.TickCount - req.RequestTime) > req.PollServiceArgs.TimeOutms) // no events, but timeout - ); + m_bycontext.Remove(req); + } + } + } + } - ready.ForEach(req => - { - m_requests.Enqueue(req); - m_longPollRequests.Remove(req); - }); + public void EnqueueInt(PollServiceHttpRequest req) + { + if (m_running) + m_requests.Enqueue(req); + } - } + private void CheckRetries() + { + while (m_running) + { + Thread.Sleep(100); // let the world move .. back to faster rate + Watchdog.UpdateThread(); + lock (m_retryRequests) + { + while (m_retryRequests.Count > 0 && m_running) + m_requests.Enqueue(m_retryRequests.Dequeue()); } } } public void Stop() { - IsRunning = false; -// m_timeout = -10000; // cause all to expire - Thread.Sleep(1000); // let the world move + m_running = false; + + Thread.Sleep(100); // let the world move foreach (Thread t in m_workerThreads) Watchdog.AbortThread(t.ManagedThreadId); - PollServiceHttpRequest wreq; + m_threadPool.Shutdown(); + + // any entry in m_bycontext should have a active request on the other queues + // so just delete contents to easy GC + foreach (Queue qu in m_bycontext.Values) + qu.Clear(); + m_bycontext.Clear(); - lock (m_longPollRequests) + try + { + foreach (PollServiceHttpRequest req in m_retryRequests) + { + req.DoHTTPstop(m_server); + } + } + catch { - if (m_longPollRequests.Count > 0 && IsRunning) - m_longPollRequests.ForEach(req => m_requests.Enqueue(req)); } + PollServiceHttpRequest wreq; + + m_retryRequests.Clear(); + while (m_requests.Count() > 0) { try { wreq = m_requests.Dequeue(0); - ResponsesProcessed++; - wreq.DoHTTPGruntWork( - m_server, wreq.PollServiceArgs.NoEvents(wreq.RequestID, wreq.PollServiceArgs.Id)); + wreq.DoHTTPstop(m_server); } catch { } } - m_longPollRequests.Clear(); m_requests.Clear(); } @@ -245,87 +228,69 @@ namespace OpenSim.Framework.Servers.HttpServer private void PoolWorkerJob() { - while (IsRunning) + while (m_running) { + PollServiceHttpRequest req = m_requests.Dequeue(4500); Watchdog.UpdateThread(); - WaitPerformResponse(); - } - } - - public void WaitPerformResponse() - { - PollServiceHttpRequest req = m_requests.Dequeue(5000); -// m_log.DebugFormat("[YYY]: Dequeued {0}", (req == null ? "null" : req.PollServiceArgs.Type.ToString())); - - if (req != null) - { - try + if (req != null) { - if (req.PollServiceArgs.HasEvents(req.RequestID, req.PollServiceArgs.Id)) + try { - Hashtable responsedata = req.PollServiceArgs.GetEvents(req.RequestID, req.PollServiceArgs.Id); - - if (responsedata == null) - return; - - // This is the event queue. - // Even if we're not running we can still perform responses by explicit request. - if (req.PollServiceArgs.Type == PollServiceEventArgs.EventType.LongPoll - || !PerformResponsesAsync) - { - try - { - ResponsesProcessed++; - req.DoHTTPGruntWork(m_server, responsedata); - } - catch (ObjectDisposedException e) // Browser aborted before we could read body, server closed the stream - { - // Ignore it, no need to reply - m_log.Error(e); - } - } - else + if (req.PollServiceArgs.HasEvents(req.RequestID, req.PollServiceArgs.Id)) { + Hashtable responsedata = req.PollServiceArgs.GetEvents(req.RequestID, req.PollServiceArgs.Id); + m_threadPool.QueueWorkItem(x => { try { - ResponsesProcessed++; req.DoHTTPGruntWork(m_server, responsedata); } - catch (ObjectDisposedException e) // Browser aborted before we could read body, server closed the stream + catch (ObjectDisposedException) { - // Ignore it, no need to reply - m_log.Error(e); } - catch (Exception e) + finally { - m_log.Error(e); + byContextDequeue(req); } - return null; }, null); } - } - else - { - if ((Environment.TickCount - req.RequestTime) > req.PollServiceArgs.TimeOutms) - { - ResponsesProcessed++; - req.DoHTTPGruntWork( - m_server, req.PollServiceArgs.NoEvents(req.RequestID, req.PollServiceArgs.Id)); - } else { - ReQueueEvent(req); + if ((Environment.TickCount - req.RequestTime) > req.PollServiceArgs.TimeOutms) + { + m_threadPool.QueueWorkItem(x => + { + try + { + req.DoHTTPGruntWork(m_server, + req.PollServiceArgs.NoEvents(req.RequestID, req.PollServiceArgs.Id)); + } + catch (ObjectDisposedException) + { + // Ignore it, no need to reply + } + finally + { + byContextDequeue(req); + } + return null; + }, null); + } + else + { + ReQueueEvent(req); + } } } - } - catch (Exception e) - { - m_log.ErrorFormat("Exception in poll service thread: " + e.ToString()); + catch (Exception e) + { + m_log.ErrorFormat("Exception in poll service thread: " + e.ToString()); + } } } } + } -} \ No newline at end of file +} diff --git a/OpenSim/Framework/Servers/HttpServer/Properties/AssemblyInfo.cs b/OpenSim/Framework/Servers/HttpServer/Properties/AssemblyInfo.cs index 5e630dc..9b663ba 100644 --- a/OpenSim/Framework/Servers/HttpServer/Properties/AssemblyInfo.cs +++ b/OpenSim/Framework/Servers/HttpServer/Properties/AssemblyInfo.cs @@ -2,7 +2,7 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -// General Information about an assembly is controlled through the following +// General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. [assembly: AssemblyTitle("OpenSim.Framework.Servers.HttpServer")] @@ -14,8 +14,8 @@ using System.Runtime.InteropServices; [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from // COM, set the ComVisible attribute to true on that type. [assembly: ComVisible(false)] @@ -25,9 +25,9 @@ using System.Runtime.InteropServices; // Version information for an assembly consists of the following four values: // // Major Version -// Minor Version +// Minor Version // Build Number // Revision // -[assembly: AssemblyVersion("0.8.3.*")] +[assembly: AssemblyVersion(OpenSim.VersionInfo.AssemblyVersionNumber)] diff --git a/OpenSim/Framework/Servers/HttpServer/RestDeserialiseHandler.cs b/OpenSim/Framework/Servers/HttpServer/RestDeserialiseHandler.cs index bd55657..67fc14e 100644 --- a/OpenSim/Framework/Servers/HttpServer/RestDeserialiseHandler.cs +++ b/OpenSim/Framework/Servers/HttpServer/RestDeserialiseHandler.cs @@ -54,6 +54,8 @@ namespace OpenSim.Framework.Servers.HttpServer TRequest deserial; using (XmlTextReader xmlReader = new XmlTextReader(request)) { + xmlReader.ProhibitDtd = true; + XmlSerializer deserializer = new XmlSerializer(typeof (TRequest)); deserial = (TRequest) deserializer.Deserialize(xmlReader); } diff --git a/OpenSim/Framework/Servers/HttpServer/RestSessionService.cs b/OpenSim/Framework/Servers/HttpServer/RestSessionService.cs index ad69cd2..158befa 100644 --- a/OpenSim/Framework/Servers/HttpServer/RestSessionService.cs +++ b/OpenSim/Framework/Servers/HttpServer/RestSessionService.cs @@ -210,6 +210,8 @@ namespace OpenSim.Framework.Servers.HttpServer { try { + xmlReader.ProhibitDtd = true; + XmlSerializer deserializer = new XmlSerializer(typeof(RestSessionObject)); deserial = (RestSessionObject)deserializer.Deserialize(xmlReader); } @@ -269,6 +271,8 @@ namespace OpenSim.Framework.Servers.HttpServer { try { + xmlReader.ProhibitDtd = true; + XmlSerializer deserializer = new XmlSerializer(typeof(TRequest)); deserial = (TRequest)deserializer.Deserialize(xmlReader); } @@ -291,5 +295,5 @@ namespace OpenSim.Framework.Servers.HttpServer serializer.Serialize(xmlWriter, response); } } - } + } } \ No newline at end of file diff --git a/OpenSim/Framework/Servers/HttpServer/RestStreamHandler.cs b/OpenSim/Framework/Servers/HttpServer/RestStreamHandler.cs index 0305dee..dfc2715 100644 --- a/OpenSim/Framework/Servers/HttpServer/RestStreamHandler.cs +++ b/OpenSim/Framework/Servers/HttpServer/RestStreamHandler.cs @@ -50,11 +50,10 @@ namespace OpenSim.Framework.Servers.HttpServer protected override byte[] ProcessRequest(string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) { + string requestBody; Encoding encoding = Encoding.UTF8; - StreamReader streamReader = new StreamReader(request, encoding); - - string requestBody = streamReader.ReadToEnd(); - streamReader.Close(); + using(StreamReader streamReader = new StreamReader(request,encoding)) + requestBody = streamReader.ReadToEnd(); string param = GetParam(path); string responseString = m_restMethod(requestBody, path, param, httpRequest, httpResponse); diff --git a/OpenSim/Framework/Servers/HttpServer/WebsocketServerHandler.cs b/OpenSim/Framework/Servers/HttpServer/WebsocketServerHandler.cs index c2925e3..c8af90f 100644 --- a/OpenSim/Framework/Servers/HttpServer/WebsocketServerHandler.cs +++ b/OpenSim/Framework/Servers/HttpServer/WebsocketServerHandler.cs @@ -75,7 +75,7 @@ namespace OpenSim.Framework.Servers.HttpServer public event PongDelegate OnPong; /// - /// This is a regular HTTP Request... This may be removed in the future. + /// This is a regular HTTP Request... This may be removed in the future. /// // public event RegularHttpRequestDelegate OnRegularHttpRequest; @@ -93,9 +93,9 @@ namespace OpenSim.Framework.Servers.HttpServer /// When the websocket is closed, this will be fired. /// public event CloseDelegate OnClose; - + /// - /// Set this delegate to allow your module to validate the origin of the + /// Set this delegate to allow your module to validate the origin of the /// Websocket request. Primary line of defense against cross site scripting /// public ValidateHandshake HandshakeValidateMethodOverride = null; @@ -181,7 +181,7 @@ namespace OpenSim.Framework.Servers.HttpServer { throw new InvalidOperationException("The socket has been shutdown"); } - } + } set { if (_networkContext != null && _networkContext.Socket != null) @@ -194,8 +194,8 @@ namespace OpenSim.Framework.Servers.HttpServer } /// - /// This triggers the websocket to start the upgrade process... - /// This is a Generalized Networking 'common sense' helper method. Some people expect to call Start() instead + /// This triggers the websocket to start the upgrade process... + /// This is a Generalized Networking 'common sense' helper method. Some people expect to call Start() instead /// of the more context appropriate HandshakeAndUpgrade() /// public void Start() @@ -261,7 +261,7 @@ namespace OpenSim.Framework.Servers.HttpServer acceptKey = GenerateAcceptKey(websocketKey); string rawaccept = string.Format(HandshakeAcceptText, acceptKey); SendUpgradeSuccess(rawaccept); - + } else @@ -282,7 +282,7 @@ namespace OpenSim.Framework.Servers.HttpServer } /// - /// Generates a handshake response key string based on the client's + /// Generates a handshake response key string based on the client's /// provided key to prove to the client that we're allowing the Websocket /// upgrade of our own free will and we were not coerced into doing it. /// @@ -298,7 +298,7 @@ namespace OpenSim.Framework.Servers.HttpServer SHA1 hashobj = SHA1.Create(); string ret = Convert.ToBase64String(hashobj.ComputeHash(Encoding.UTF8.GetBytes(acceptkey))); hashobj.Clear(); - + return ret; } @@ -310,11 +310,11 @@ namespace OpenSim.Framework.Servers.HttpServer { // Create a new websocket state so we can keep track of data in between network reads. WebSocketState socketState = new WebSocketState() { ReceivedBytes = new List(), Header = WebsocketFrameHeader.HeaderDefault(), FrameComplete = true}; - + byte[] bhandshakeResponse = Encoding.UTF8.GetBytes(pHandshakeResponse); - - + + try { @@ -324,7 +324,7 @@ namespace OpenSim.Framework.Servers.HttpServer } // Begin reading the TCP stream before writing the Upgrade success message to the other side of the stream. _networkContext.Stream.BeginRead(_buffer, 0, _bufferLength, OnReceive, socketState); - + // Write the upgrade handshake success message _networkContext.Stream.Write(bhandshakeResponse, 0, bhandshakeResponse.Length); _networkContext.Stream.Flush(); @@ -345,7 +345,7 @@ namespace OpenSim.Framework.Servers.HttpServer catch (ObjectDisposedException) { Close(string.Empty); - } + } } /// @@ -369,7 +369,7 @@ namespace OpenSim.Framework.Servers.HttpServer /// /// This is our ugly Async OnReceive event handler. - /// This chunks the input stream based on the length of the provided buffer and processes out + /// This chunks the input stream based on the length of the provided buffer and processes out /// as many frames as it can. It then moves the unprocessed data to the beginning of the buffer. /// /// Our Async State from beginread @@ -390,7 +390,7 @@ namespace OpenSim.Framework.Servers.HttpServer if (_bufferPosition > _bufferLength) { - // Message too big for chunksize.. not sure how this happened... + // Message too big for chunksize.. not sure how this happened... //Close(string.Empty); } @@ -413,7 +413,7 @@ namespace OpenSim.Framework.Servers.HttpServer if (pheader.PayloadLen > (ulong) _maxPayloadBytes) { Close("Invalid Payload size"); - + return; } if (pheader.PayloadLen > 0) @@ -487,7 +487,7 @@ namespace OpenSim.Framework.Servers.HttpServer _socketState.ReceivedBytes.Clear(); _socketState.ExpectedBytes = 0; // do some processing - } + } } } if (offset > 0) @@ -504,7 +504,7 @@ namespace OpenSim.Framework.Servers.HttpServer } else { - // We can't read the stream anymore... + // We can't read the stream anymore... } } catch (IOException) @@ -533,7 +533,7 @@ namespace OpenSim.Framework.Servers.HttpServer textMessageFrame.Header.Opcode = WebSocketReader.OpCode.Text; textMessageFrame.Header.IsEnd = true; SendSocket(textMessageFrame.ToBytes()); - + } public void SendData(byte[] data) @@ -657,7 +657,7 @@ namespace OpenSim.Framework.Servers.HttpServer SendSocket(pongFrame.ToBytes()); break; case WebSocketReader.OpCode.Pong: - + PongDelegate pongD = OnPong; if (pongD != null) { @@ -701,7 +701,7 @@ namespace OpenSim.Framework.Servers.HttpServer { textD(this, new WebsocketTextEventArgs() { Data = Encoding.UTF8.GetString(psocketState.ReceivedBytes.ToArray()) }); } - + // Send Done Event! } break; @@ -719,7 +719,7 @@ namespace OpenSim.Framework.Servers.HttpServer { if (psocketState.ContinuationFrame.Header.Opcode == WebSocketReader.OpCode.Text) { - // Send Done event + // Send Done event TextDelegate textD = OnText; if (textD != null) { @@ -744,9 +744,9 @@ namespace OpenSim.Framework.Servers.HttpServer break; case WebSocketReader.OpCode.Close: Close(string.Empty); - + break; - + } psocketState.Header.SetDefault(); psocketState.ReceivedBytes.Clear(); @@ -837,12 +837,12 @@ namespace OpenSim.Framework.Servers.HttpServer } /// - /// Attempts to read a header off the provided buffer. Returns true, exports a WebSocketFrameheader, + /// Attempts to read a header off the provided buffer. Returns true, exports a WebSocketFrameheader, /// and an int to move the buffer forward when it reads a header. False when it can't read a header /// /// Bytes read from the stream /// Starting place in the stream to begin trying to read from - /// Lenth in the stream to try and read from. Provided for cases where the + /// Lenth in the stream to try and read from. Provided for cases where the /// buffer's length is larger then the data in it /// Outputs the read WebSocket frame header /// Informs the calling stream to move the buffer forward @@ -897,7 +897,7 @@ namespace OpenSim.Framework.Servers.HttpServer oHeader.PayloadLen = BitConverter.ToUInt16(pBuffer, pOffset + index); index += 2; break; - case 127: // we got more this is a bigger frame + case 127: // we got more this is a bigger frame // 8 bytes - uint64 - most significant bit 0 network byte order minumheadersize += 8; if (length < minumheadersize) @@ -909,7 +909,7 @@ namespace OpenSim.Framework.Servers.HttpServer oHeader.PayloadLen = BitConverter.ToUInt64(pBuffer, pOffset + index); index += 8; break; - + } //oHeader.PayloadLeft = oHeader.PayloadLen; // Start the count in case it's chunked over the network. This is different then frame fragmentation if (oHeader.IsMasked) @@ -937,9 +937,9 @@ namespace OpenSim.Framework.Servers.HttpServer /* * RFC6455 nib 0 1 2 3 4 5 6 7 -byt 0 1 2 3 -dec 0 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +byt 0 1 2 3 +dec 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-------+-+-------------+-------------------------------+ |F|R|R|R| opcode|M| Payload len | Extended payload length | |I|S|S|S| (4) |A| (7) | (16/64) + @@ -963,7 +963,7 @@ dec 0 1 2 3 public static readonly WebSocketFrame DefaultFrame = new WebSocketFrame(){Header = new WebsocketFrameHeader(),WebSocketPayload = new byte[0]}; public WebsocketFrameHeader Header; public byte[] WebSocketPayload; - + public byte[] ToBytes() { Header.PayloadLen = (ulong)WebSocketPayload.Length; @@ -991,7 +991,7 @@ dec 0 1 2 3 public int Mask; /* byt 0 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +---------------+---------------+---------------+---------------+ | Octal 1 | Octal 2 | Octal 3 | Octal 4 | +---------------+---------------+---------------+---------------+ @@ -1002,11 +1002,11 @@ byt 0 1 2 3 public UInt64 PayloadLen; //public UInt64 PayloadLeft; - // Payload is X + Y + // Payload is X + Y //public UInt64 ExtensionDataLength; //public UInt64 ApplicationDataLength; public static readonly WebsocketFrameHeader ZeroHeader = WebsocketFrameHeader.HeaderDefault(); - + public void SetDefault() { @@ -1025,16 +1025,16 @@ byt 0 1 2 3 /// /// Returns a byte array representing the Frame header /// - /// This is the frame data payload. The header describes the size of the payload. + /// This is the frame data payload. The header describes the size of the payload. /// If payload is null, a Zero sized payload is assumed /// Returns a byte array representing the frame header public byte[] ToBytes(byte[] payload) { List result = new List(); - + // Squeeze in our opcode and our ending bit. result.Add((byte)((byte)Opcode | (IsEnd?0x80:0x00) )); - + // Again with the three different byte interpretations of size.. //bytesize @@ -1056,7 +1056,7 @@ byt 0 1 2 3 Array.Reverse(payloadLengthByte); result.AddRange(payloadLengthByte); } - + // Only add a payload if it's not null if (payload != null) { @@ -1155,5 +1155,5 @@ byt 0 1 2 3 } - + } diff --git a/OpenSim/Framework/Servers/HttpServer/XmlRpcBasicDOSProtector.cs b/OpenSim/Framework/Servers/HttpServer/XmlRpcBasicDOSProtector.cs index f212208..6b2c0ab 100644 --- a/OpenSim/Framework/Servers/HttpServer/XmlRpcBasicDOSProtector.cs +++ b/OpenSim/Framework/Servers/HttpServer/XmlRpcBasicDOSProtector.cs @@ -36,7 +36,7 @@ namespace OpenSim.Framework.Servers.HttpServer { private readonly XmlRpcMethod _normalMethod; private readonly XmlRpcMethod _throttledMethod; - + private readonly BasicDosProtectorOptions _options; private readonly BasicDOSProtector _dosProtector; @@ -44,7 +44,7 @@ namespace OpenSim.Framework.Servers.HttpServer { _normalMethod = normalMethod; _throttledMethod = throttledMethod; - + _options = options; _dosProtector = new BasicDOSProtector(_options); @@ -87,5 +87,5 @@ namespace OpenSim.Framework.Servers.HttpServer } - + } -- cgit v1.1