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