aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Framework/Servers
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--OpenSim/Framework/Servers/BaseOpenSimServer.cs58
-rw-r--r--OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs59
-rw-r--r--OpenSim/Framework/Servers/HttpServer/BaseOutputStreamHandler.cs60
-rw-r--r--OpenSim/Framework/Servers/HttpServer/BaseRequestHandler.cs4
-rw-r--r--OpenSim/Framework/Servers/HttpServer/BaseStreamHandler.cs27
-rw-r--r--OpenSim/Framework/Servers/HttpServer/BaseStreamHandlerBasicDOSProtector.cs107
-rw-r--r--OpenSim/Framework/Servers/HttpServer/BinaryStreamHandler.cs2
-rw-r--r--OpenSim/Framework/Servers/HttpServer/GenericHTTPBasicDOSProtector.cs119
-rw-r--r--OpenSim/Framework/Servers/HttpServer/Interfaces/IStreamHandler.cs15
-rw-r--r--OpenSim/Framework/Servers/HttpServer/PollServiceEventArgs.cs18
-rw-r--r--OpenSim/Framework/Servers/HttpServer/PollServiceHttpRequest.cs45
-rw-r--r--OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs64
-rw-r--r--OpenSim/Framework/Servers/HttpServer/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Framework/Servers/HttpServer/RestDeserialiseHandler.cs4
-rw-r--r--OpenSim/Framework/Servers/HttpServer/RestSessionService.cs13
-rw-r--r--OpenSim/Framework/Servers/HttpServer/RestStreamHandler.cs2
-rw-r--r--OpenSim/Framework/Servers/HttpServer/WebsocketServerHandler.cs87
-rw-r--r--OpenSim/Framework/Servers/HttpServer/XmlRpcBasicDOSProtector.cs91
-rw-r--r--OpenSim/Framework/Servers/MainServer.cs13
-rw-r--r--OpenSim/Framework/Servers/ServerBase.cs254
-rw-r--r--OpenSim/Framework/Servers/VersionInfo.cs2
21 files changed, 905 insertions, 141 deletions
diff --git a/OpenSim/Framework/Servers/BaseOpenSimServer.cs b/OpenSim/Framework/Servers/BaseOpenSimServer.cs
index 6c04c69..3055865 100644
--- a/OpenSim/Framework/Servers/BaseOpenSimServer.cs
+++ b/OpenSim/Framework/Servers/BaseOpenSimServer.cs
@@ -59,7 +59,7 @@ namespace OpenSim.Framework.Servers
59 /// This will control a periodic log printout of the current 'show stats' (if they are active) for this 59 /// This will control a periodic log printout of the current 'show stats' (if they are active) for this
60 /// server. 60 /// server.
61 /// </summary> 61 /// </summary>
62 private Timer m_periodicDiagnosticsTimer = new Timer(60 * 60 * 1000); 62// private Timer m_periodicDiagnosticsTimer = new Timer(60 * 60 * 1000);
63 63
64 /// <summary> 64 /// <summary>
65 /// Random uuid for private data 65 /// Random uuid for private data
@@ -77,8 +77,8 @@ namespace OpenSim.Framework.Servers
77 // Random uuid for private data 77 // Random uuid for private data
78 m_osSecret = UUID.Random().ToString(); 78 m_osSecret = UUID.Random().ToString();
79 79
80 m_periodicDiagnosticsTimer.Elapsed += new ElapsedEventHandler(LogDiagnostics); 80// m_periodicDiagnosticsTimer.Elapsed += new ElapsedEventHandler(LogDiagnostics);
81 m_periodicDiagnosticsTimer.Enabled = true; 81// m_periodicDiagnosticsTimer.Enabled = true;
82 } 82 }
83 83
84 /// <summary> 84 /// <summary>
@@ -86,26 +86,23 @@ namespace OpenSim.Framework.Servers
86 /// </summary> 86 /// </summary>
87 protected virtual void StartupSpecific() 87 protected virtual void StartupSpecific()
88 { 88 {
89 if (m_console == null) 89 StatsManager.SimExtraStats = new SimExtraStatsCollector();
90 return;
91
92 RegisterCommonCommands(); 90 RegisterCommonCommands();
93 91 RegisterCommonComponents(Config);
94 m_console.Commands.AddCommand("General", false, "quit", 92 }
95 "quit", 93
96 "Quit the application", HandleQuit); 94 protected override void ShutdownSpecific()
95 {
96 m_log.Info("[SHUTDOWN]: Shutdown processing on main thread complete. Exiting...");
97
98 RemovePIDFile();
97 99
98 m_console.Commands.AddCommand("General", false, "shutdown", 100 base.ShutdownSpecific();
99 "shutdown", 101
100 "Quit the application", HandleQuit); 102 Environment.Exit(0);
101 } 103 }
102 104
103 /// <summary> 105 /// <summary>
104 /// Should be overriden and referenced by descendents if they need to perform extra shutdown processing
105 /// </summary>
106 public virtual void ShutdownSpecific() {}
107
108 /// <summary>
109 /// Provides a list of help topics that are available. Overriding classes should append their topics to the 106 /// Provides a list of help topics that are available. Overriding classes should append their topics to the
110 /// information returned when the base method is called. 107 /// information returned when the base method is called.
111 /// </summary> 108 /// </summary>
@@ -148,30 +145,13 @@ namespace OpenSim.Framework.Servers
148 145
149 TimeSpan timeTaken = DateTime.Now - m_startuptime; 146 TimeSpan timeTaken = DateTime.Now - m_startuptime;
150 147
151 m_log.InfoFormat( 148// MainConsole.Instance.OutputFormat(
152 "[STARTUP]: Non-script portion of startup took {0}m {1}s. PLEASE WAIT FOR LOGINS TO BE ENABLED ON REGIONS ONCE SCRIPTS HAVE STARTED.", 149// "PLEASE WAIT FOR LOGINS TO BE ENABLED ON REGIONS ONCE SCRIPTS HAVE STARTED. Non-script portion of startup took {0}m {1}s.",
153 timeTaken.Minutes, timeTaken.Seconds); 150// timeTaken.Minutes, timeTaken.Seconds);
154 } 151 }
155 152
156 /// <summary> 153 public string osSecret
157 /// Should be overriden and referenced by descendents if they need to perform extra shutdown processing
158 /// </summary>
159 public virtual void Shutdown()
160 { 154 {
161 ShutdownSpecific();
162
163 m_log.Info("[SHUTDOWN]: Shutdown processing on main thread complete. Exiting...");
164 RemovePIDFile();
165
166 Environment.Exit(0);
167 }
168
169 private void HandleQuit(string module, string[] args)
170 {
171 Shutdown();
172 }
173
174 public string osSecret {
175 // Secret uuid for the simulator 155 // Secret uuid for the simulator
176 get { return m_osSecret; } 156 get { return m_osSecret; }
177 } 157 }
diff --git a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs
index 97035e3..7841f47 100644
--- a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs
+++ b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs
@@ -54,7 +54,6 @@ namespace OpenSim.Framework.Servers.HttpServer
54 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 54 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
55 private HttpServerLogWriter httpserverlog = new HttpServerLogWriter(); 55 private HttpServerLogWriter httpserverlog = new HttpServerLogWriter();
56 56
57
58 /// <summary> 57 /// <summary>
59 /// This is a pending websocket request before it got an sucessful upgrade response. 58 /// This is a pending websocket request before it got an sucessful upgrade response.
60 /// The consumer must call handler.HandshakeAndUpgrade() to signal to the handler to 59 /// The consumer must call handler.HandshakeAndUpgrade() to signal to the handler to
@@ -81,6 +80,11 @@ namespace OpenSim.Framework.Servers.HttpServer
81 /// </remarks> 80 /// </remarks>
82 public int RequestNumber { get; private set; } 81 public int RequestNumber { get; private set; }
83 82
83 /// <summary>
84 /// Statistic for holding number of requests processed.
85 /// </summary>
86 private Stat m_requestsProcessedStat;
87
84 private volatile int NotSocketErrors = 0; 88 private volatile int NotSocketErrors = 0;
85 public volatile bool HTTPDRunning = false; 89 public volatile bool HTTPDRunning = false;
86 90
@@ -383,6 +387,8 @@ namespace OpenSim.Framework.Servers.HttpServer
383 387
384 if (TryGetPollServiceHTTPHandler(request.UriPath.ToString(), out psEvArgs)) 388 if (TryGetPollServiceHTTPHandler(request.UriPath.ToString(), out psEvArgs))
385 { 389 {
390 psEvArgs.RequestsReceived++;
391
386 PollServiceHttpRequest psreq = new PollServiceHttpRequest(psEvArgs, context, request); 392 PollServiceHttpRequest psreq = new PollServiceHttpRequest(psEvArgs, context, request);
387 393
388 if (psEvArgs.Request != null) 394 if (psEvArgs.Request != null)
@@ -437,9 +443,8 @@ namespace OpenSim.Framework.Servers.HttpServer
437 } 443 }
438 } 444 }
439 445
440 public void OnHandleRequestIOThread(IHttpClientContext context, IHttpRequest request) 446 private void OnHandleRequestIOThread(IHttpClientContext context, IHttpRequest request)
441 { 447 {
442
443 OSHttpRequest req = new OSHttpRequest(context, request); 448 OSHttpRequest req = new OSHttpRequest(context, request);
444 WebSocketRequestDelegate dWebSocketRequestDelegate = null; 449 WebSocketRequestDelegate dWebSocketRequestDelegate = null;
445 lock (m_WebSocketHandlers) 450 lock (m_WebSocketHandlers)
@@ -454,9 +459,8 @@ namespace OpenSim.Framework.Servers.HttpServer
454 } 459 }
455 460
456 OSHttpResponse resp = new OSHttpResponse(new HttpResponse(context, request),context); 461 OSHttpResponse resp = new OSHttpResponse(new HttpResponse(context, request),context);
457 462 resp.ReuseContext = true;
458 HandleRequest(req, resp); 463 HandleRequest(req, resp);
459
460 464
461 // !!!HACK ALERT!!! 465 // !!!HACK ALERT!!!
462 // There seems to be a bug in the underlying http code that makes subsequent requests 466 // There seems to be a bug in the underlying http code that makes subsequent requests
@@ -687,7 +691,7 @@ namespace OpenSim.Framework.Servers.HttpServer
687 691
688 if (buffer != null) 692 if (buffer != null)
689 { 693 {
690 if (!response.SendChunked) 694 if (!response.SendChunked && response.ContentLength64 <= 0)
691 response.ContentLength64 = buffer.LongLength; 695 response.ContentLength64 = buffer.LongLength;
692 696
693 response.OutputStream.Write(buffer, 0, buffer.Length); 697 response.OutputStream.Write(buffer, 0, buffer.Length);
@@ -782,7 +786,7 @@ namespace OpenSim.Framework.Servers.HttpServer
782 "[BASE HTTP SERVER]: HTTP IN {0} :{1} {2} content type handler {3} {4} from {5}", 786 "[BASE HTTP SERVER]: HTTP IN {0} :{1} {2} content type handler {3} {4} from {5}",
783 RequestNumber, 787 RequestNumber,
784 Port, 788 Port,
785 (request.ContentType == null || request.ContentType == "") ? "not set" : request.ContentType, 789 string.IsNullOrEmpty(request.ContentType) ? "not set" : request.ContentType,
786 request.HttpMethod, 790 request.HttpMethod,
787 request.Url.PathAndQuery, 791 request.Url.PathAndQuery,
788 request.RemoteIPEndPoint); 792 request.RemoteIPEndPoint);
@@ -1053,7 +1057,21 @@ namespace OpenSim.Framework.Servers.HttpServer
1053 } 1057 }
1054 1058
1055 response.ContentType = "text/xml"; 1059 response.ContentType = "text/xml";
1056 responseString = XmlRpcResponseSerializer.Singleton.Serialize(xmlRpcResponse); 1060 using (MemoryStream outs = new MemoryStream())
1061 {
1062 using (XmlTextWriter writer = new XmlTextWriter(outs, Encoding.UTF8))
1063 {
1064 writer.Formatting = Formatting.None;
1065 XmlRpcResponseSerializer.Singleton.Serialize(writer, xmlRpcResponse);
1066 writer.Flush();
1067 outs.Flush();
1068 outs.Position = 0;
1069 using (StreamReader sr = new StreamReader(outs))
1070 {
1071 responseString = sr.ReadToEnd();
1072 }
1073 }
1074 }
1057 } 1075 }
1058 else 1076 else
1059 { 1077 {
@@ -1850,8 +1868,8 @@ namespace OpenSim.Framework.Servers.HttpServer
1850 m_httpListener2.Start(64); 1868 m_httpListener2.Start(64);
1851 1869
1852 // Long Poll Service Manager with 3 worker threads a 25 second timeout for no events 1870 // Long Poll Service Manager with 3 worker threads a 25 second timeout for no events
1853// m_PollServiceManager = new PollServiceRequestManager(this, 3, 25000);
1854 m_PollServiceManager = new PollServiceRequestManager(this, 4, 25000); 1871 m_PollServiceManager = new PollServiceRequestManager(this, 4, 25000);
1872 m_PollServiceManager.Start();
1855 HTTPDRunning = true; 1873 HTTPDRunning = true;
1856 1874
1857 //HttpListenerContext context; 1875 //HttpListenerContext context;
@@ -1870,6 +1888,21 @@ namespace OpenSim.Framework.Servers.HttpServer
1870 // useful without inbound HTTP. 1888 // useful without inbound HTTP.
1871 throw e; 1889 throw e;
1872 } 1890 }
1891
1892 m_requestsProcessedStat
1893 = new Stat(
1894 "HTTPRequestsServed",
1895 "Number of inbound HTTP requests processed",
1896 "",
1897 "requests",
1898 "httpserver",
1899 Port.ToString(),
1900 StatType.Pull,
1901 MeasuresOfInterest.AverageChangeOverTime,
1902 stat => stat.Value = RequestNumber,
1903 StatVerbosity.Debug);
1904
1905 StatsManager.RegisterStat(m_requestsProcessedStat);
1873 } 1906 }
1874 1907
1875 public void httpServerDisconnectMonitor(IHttpClientContext source, SocketError err) 1908 public void httpServerDisconnectMonitor(IHttpClientContext source, SocketError err)
@@ -1902,9 +1935,12 @@ namespace OpenSim.Framework.Servers.HttpServer
1902 public void Stop() 1935 public void Stop()
1903 { 1936 {
1904 HTTPDRunning = false; 1937 HTTPDRunning = false;
1938
1939 StatsManager.DeregisterStat(m_requestsProcessedStat);
1940
1905 try 1941 try
1906 { 1942 {
1907// m_PollServiceManager.Stop(); 1943 m_PollServiceManager.Stop();
1908 1944
1909 m_httpListener2.ExceptionThrown -= httpServerException; 1945 m_httpListener2.ExceptionThrown -= httpServerException;
1910 //m_httpListener2.DisconnectHandler = null; 1946 //m_httpListener2.DisconnectHandler = null;
@@ -1931,6 +1967,7 @@ namespace OpenSim.Framework.Servers.HttpServer
1931 1967
1932 public void RemoveHTTPHandler(string httpMethod, string path) 1968 public void RemoveHTTPHandler(string httpMethod, string path)
1933 { 1969 {
1970 if (path == null) return; // Caps module isn't loaded, tries to remove handler where path = null
1934 lock (m_HTTPHandlers) 1971 lock (m_HTTPHandlers)
1935 { 1972 {
1936 if (httpMethod != null && httpMethod.Length == 0) 1973 if (httpMethod != null && httpMethod.Length == 0)
diff --git a/OpenSim/Framework/Servers/HttpServer/BaseOutputStreamHandler.cs b/OpenSim/Framework/Servers/HttpServer/BaseOutputStreamHandler.cs
new file mode 100644
index 0000000..72b3065
--- /dev/null
+++ b/OpenSim/Framework/Servers/HttpServer/BaseOutputStreamHandler.cs
@@ -0,0 +1,60 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System.IO;
29
30namespace OpenSim.Framework.Servers.HttpServer
31{
32 /// <summary>
33 /// Base handler for writing to an output stream
34 /// </summary>
35 /// <remarks>
36 /// Inheriting classes should override ProcessRequest() rather than Handle()
37 /// </remarks>
38 public abstract class BaseOutputStreamHandler : BaseRequestHandler, IRequestHandler
39 {
40 protected BaseOutputStreamHandler(string httpMethod, string path) : this(httpMethod, path, null, null) {}
41
42 protected BaseOutputStreamHandler(string httpMethod, string path, string name, string description)
43 : base(httpMethod, path, name, description) {}
44
45 public virtual void Handle(
46 string path, Stream request, Stream response, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
47 {
48 RequestsReceived++;
49
50 ProcessRequest(path, request, response, httpRequest, httpResponse);
51
52 RequestsHandled++;
53 }
54
55 protected virtual void ProcessRequest(
56 string path, Stream request, Stream response, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
57 {
58 }
59 }
60} \ No newline at end of file
diff --git a/OpenSim/Framework/Servers/HttpServer/BaseRequestHandler.cs b/OpenSim/Framework/Servers/HttpServer/BaseRequestHandler.cs
index ae7aaf2..bbac699 100644
--- a/OpenSim/Framework/Servers/HttpServer/BaseRequestHandler.cs
+++ b/OpenSim/Framework/Servers/HttpServer/BaseRequestHandler.cs
@@ -31,6 +31,10 @@ namespace OpenSim.Framework.Servers.HttpServer
31{ 31{
32 public abstract class BaseRequestHandler 32 public abstract class BaseRequestHandler
33 { 33 {
34 public int RequestsReceived { get; protected set; }
35
36 public int RequestsHandled { get; protected set; }
37
34 public virtual string ContentType 38 public virtual string ContentType
35 { 39 {
36 get { return "application/xml"; } 40 get { return "application/xml"; }
diff --git a/OpenSim/Framework/Servers/HttpServer/BaseStreamHandler.cs b/OpenSim/Framework/Servers/HttpServer/BaseStreamHandler.cs
index 6342983..252cc2a 100644
--- a/OpenSim/Framework/Servers/HttpServer/BaseStreamHandler.cs
+++ b/OpenSim/Framework/Servers/HttpServer/BaseStreamHandler.cs
@@ -29,14 +29,35 @@ using System.IO;
29 29
30namespace OpenSim.Framework.Servers.HttpServer 30namespace OpenSim.Framework.Servers.HttpServer
31{ 31{
32 /// <summary>
33 /// Base streamed request handler.
34 /// </summary>
35 /// <remarks>
36 /// Inheriting classes should override ProcessRequest() rather than Handle()
37 /// </remarks>
32 public abstract class BaseStreamHandler : BaseRequestHandler, IStreamedRequestHandler 38 public abstract class BaseStreamHandler : BaseRequestHandler, IStreamedRequestHandler
33 { 39 {
34 public abstract byte[] Handle(string path, Stream request,
35 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse);
36
37 protected BaseStreamHandler(string httpMethod, string path) : this(httpMethod, path, null, null) {} 40 protected BaseStreamHandler(string httpMethod, string path) : this(httpMethod, path, null, null) {}
38 41
39 protected BaseStreamHandler(string httpMethod, string path, string name, string description) 42 protected BaseStreamHandler(string httpMethod, string path, string name, string description)
40 : base(httpMethod, path, name, description) {} 43 : base(httpMethod, path, name, description) {}
44
45 public virtual byte[] Handle(
46 string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
47 {
48 RequestsReceived++;
49
50 byte[] result = ProcessRequest(path, request, httpRequest, httpResponse);
51
52 RequestsHandled++;
53
54 return result;
55 }
56
57 protected virtual byte[] ProcessRequest(
58 string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
59 {
60 return null;
61 }
41 } 62 }
42} \ No newline at end of file 63} \ No newline at end of file
diff --git a/OpenSim/Framework/Servers/HttpServer/BaseStreamHandlerBasicDOSProtector.cs b/OpenSim/Framework/Servers/HttpServer/BaseStreamHandlerBasicDOSProtector.cs
new file mode 100644
index 0000000..1b88545
--- /dev/null
+++ b/OpenSim/Framework/Servers/HttpServer/BaseStreamHandlerBasicDOSProtector.cs
@@ -0,0 +1,107 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27using OpenSim.Framework;
28using System.IO;
29
30namespace OpenSim.Framework.Servers.HttpServer
31{
32 /// <summary>
33 /// BaseStreamHandlerBasicDOSProtector Base streamed request handler.
34 /// </summary>
35 /// <remarks>
36 /// Inheriting classes should override ProcessRequest() rather than Handle()
37 /// </remarks>
38 public abstract class BaseStreamHandlerBasicDOSProtector : BaseRequestHandler, IStreamedRequestHandler
39 {
40
41 private readonly BasicDosProtectorOptions _options;
42 private readonly BasicDOSProtector _dosProtector;
43
44 protected BaseStreamHandlerBasicDOSProtector(string httpMethod, string path, BasicDosProtectorOptions options) : this(httpMethod, path, null, null, options) {}
45
46 protected BaseStreamHandlerBasicDOSProtector(string httpMethod, string path, string name, string description, BasicDosProtectorOptions options)
47 : base(httpMethod, path, name, description)
48 {
49 _options = options;
50 _dosProtector = new BasicDOSProtector(_options);
51 }
52
53 public virtual byte[] Handle(
54 string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
55 {
56 byte[] result;
57 RequestsReceived++;
58 string clientstring = GetClientString(httpRequest);
59 string endpoint = GetRemoteAddr(httpRequest);
60 if (_dosProtector.Process(clientstring, endpoint))
61 result = ProcessRequest(path, request, httpRequest, httpResponse);
62 else
63 result = ThrottledRequest(path, request, httpRequest, httpResponse);
64 if (_options.MaxConcurrentSessions > 0)
65 _dosProtector.ProcessEnd(clientstring, endpoint);
66
67 RequestsHandled++;
68
69 return result;
70 }
71
72 protected virtual byte[] ProcessRequest(
73 string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
74 {
75 return null;
76 }
77
78 protected virtual byte[] ThrottledRequest(
79 string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
80 {
81 return new byte[0];
82 }
83
84
85 private string GetRemoteAddr(IOSHttpRequest httpRequest)
86 {
87 string remoteaddr = string.Empty;
88 if (httpRequest.Headers["remote_addr"] != null)
89 remoteaddr = httpRequest.Headers["remote_addr"];
90
91 return remoteaddr;
92 }
93
94 private string GetClientString(IOSHttpRequest httpRequest)
95 {
96 string clientstring = string.Empty;
97
98 if (_options.AllowXForwardedFor && httpRequest.Headers["x-forwarded-for"] != null)
99 clientstring = httpRequest.Headers["x-forwarded-for"];
100 else
101 clientstring = GetRemoteAddr(httpRequest);
102
103 return clientstring;
104
105 }
106 }
107}
diff --git a/OpenSim/Framework/Servers/HttpServer/BinaryStreamHandler.cs b/OpenSim/Framework/Servers/HttpServer/BinaryStreamHandler.cs
index b94bfb4..1b03f54 100644
--- a/OpenSim/Framework/Servers/HttpServer/BinaryStreamHandler.cs
+++ b/OpenSim/Framework/Servers/HttpServer/BinaryStreamHandler.cs
@@ -45,7 +45,7 @@ namespace OpenSim.Framework.Servers.HttpServer
45 m_method = binaryMethod; 45 m_method = binaryMethod;
46 } 46 }
47 47
48 public override byte[] Handle(string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) 48 protected override byte[] ProcessRequest(string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
49 { 49 {
50 byte[] data = ReadFully(request); 50 byte[] data = ReadFully(request);
51 string param = GetParam(path); 51 string param = GetParam(path);
diff --git a/OpenSim/Framework/Servers/HttpServer/GenericHTTPBasicDOSProtector.cs b/OpenSim/Framework/Servers/HttpServer/GenericHTTPBasicDOSProtector.cs
new file mode 100644
index 0000000..cd4b8ff
--- /dev/null
+++ b/OpenSim/Framework/Servers/HttpServer/GenericHTTPBasicDOSProtector.cs
@@ -0,0 +1,119 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System.Collections;
29
30namespace OpenSim.Framework.Servers.HttpServer
31{
32 public class GenericHTTPDOSProtector
33 {
34 private readonly GenericHTTPMethod _normalMethod;
35 private readonly GenericHTTPMethod _throttledMethod;
36
37 private readonly BasicDosProtectorOptions _options;
38 private readonly BasicDOSProtector _dosProtector;
39
40 public GenericHTTPDOSProtector(GenericHTTPMethod normalMethod, GenericHTTPMethod throttledMethod, BasicDosProtectorOptions options)
41 {
42 _normalMethod = normalMethod;
43 _throttledMethod = throttledMethod;
44
45 _options = options;
46 _dosProtector = new BasicDOSProtector(_options);
47 }
48 public Hashtable Process(Hashtable request)
49 {
50 Hashtable process = null;
51 string clientstring= GetClientString(request);
52 string endpoint = GetRemoteAddr(request);
53 if (_dosProtector.Process(clientstring, endpoint))
54 process = _normalMethod(request);
55 else
56 process = _throttledMethod(request);
57
58 if (_options.MaxConcurrentSessions>0)
59 _dosProtector.ProcessEnd(clientstring, endpoint);
60
61 return process;
62 }
63
64 private string GetRemoteAddr(Hashtable request)
65 {
66 string remoteaddr = "";
67 if (!request.ContainsKey("headers"))
68 return remoteaddr;
69 Hashtable requestinfo = (Hashtable)request["headers"];
70 if (!requestinfo.ContainsKey("remote_addr"))
71 return remoteaddr;
72 object remote_addrobj = requestinfo["remote_addr"];
73 if (remote_addrobj != null)
74 {
75 if (!string.IsNullOrEmpty(remote_addrobj.ToString()))
76 {
77 remoteaddr = remote_addrobj.ToString();
78 }
79
80 }
81 return remoteaddr;
82 }
83
84 private string GetClientString(Hashtable request)
85 {
86 string clientstring = "";
87 if (!request.ContainsKey("headers"))
88 return clientstring;
89
90 Hashtable requestinfo = (Hashtable)request["headers"];
91 if (_options.AllowXForwardedFor && requestinfo.ContainsKey("x-forwarded-for"))
92 {
93 object str = requestinfo["x-forwarded-for"];
94 if (str != null)
95 {
96 if (!string.IsNullOrEmpty(str.ToString()))
97 {
98 return str.ToString();
99 }
100 }
101 }
102 if (!requestinfo.ContainsKey("remote_addr"))
103 return clientstring;
104
105 object remote_addrobj = requestinfo["remote_addr"];
106 if (remote_addrobj != null)
107 {
108 if (!string.IsNullOrEmpty(remote_addrobj.ToString()))
109 {
110 clientstring = remote_addrobj.ToString();
111 }
112 }
113
114 return clientstring;
115
116 }
117
118 }
119}
diff --git a/OpenSim/Framework/Servers/HttpServer/Interfaces/IStreamHandler.cs b/OpenSim/Framework/Servers/HttpServer/Interfaces/IStreamHandler.cs
index cb5cce5..b8541cb 100644
--- a/OpenSim/Framework/Servers/HttpServer/Interfaces/IStreamHandler.cs
+++ b/OpenSim/Framework/Servers/HttpServer/Interfaces/IStreamHandler.cs
@@ -32,7 +32,6 @@ namespace OpenSim.Framework.Servers.HttpServer
32{ 32{
33 public interface IRequestHandler 33 public interface IRequestHandler
34 { 34 {
35
36 /// <summary> 35 /// <summary>
37 /// Name for this handler. 36 /// Name for this handler.
38 /// </summary> 37 /// </summary>
@@ -59,6 +58,19 @@ namespace OpenSim.Framework.Servers.HttpServer
59 58
60 // Return path 59 // Return path
61 string Path { get; } 60 string Path { get; }
61
62 /// <summary>
63 /// Number of requests received by this handler
64 /// </summary>
65 int RequestsReceived { get; }
66
67 /// <summary>
68 /// Number of requests handled.
69 /// </summary>
70 /// <remarks>
71 /// Should be equal to RequestsReceived unless requested are being handled slowly or there is deadlock.
72 /// </remarks>
73 int RequestsHandled { get; }
62 } 74 }
63 75
64 public interface IStreamedRequestHandler : IRequestHandler 76 public interface IStreamedRequestHandler : IRequestHandler
@@ -69,7 +81,6 @@ namespace OpenSim.Framework.Servers.HttpServer
69 81
70 public interface IStreamHandler : IRequestHandler 82 public interface IStreamHandler : IRequestHandler
71 { 83 {
72 // Handle request stream, return byte array
73 void Handle(string path, Stream request, Stream response, IOSHttpRequest httpReqbuest, IOSHttpResponse httpResponse); 84 void Handle(string path, Stream request, Stream response, IOSHttpRequest httpReqbuest, IOSHttpResponse httpResponse);
74 } 85 }
75 86
diff --git a/OpenSim/Framework/Servers/HttpServer/PollServiceEventArgs.cs b/OpenSim/Framework/Servers/HttpServer/PollServiceEventArgs.cs
index c19ac32..3fd3bf7 100644
--- a/OpenSim/Framework/Servers/HttpServer/PollServiceEventArgs.cs
+++ b/OpenSim/Framework/Servers/HttpServer/PollServiceEventArgs.cs
@@ -50,25 +50,39 @@ namespace OpenSim.Framework.Servers.HttpServer
50 50
51 public enum EventType : int 51 public enum EventType : int
52 { 52 {
53 Normal = 0, 53 LongPoll = 0,
54 LslHttp = 1, 54 LslHttp = 1,
55 Inventory = 2, 55 Inventory = 2,
56 Texture = 3, 56 Texture = 3,
57 Mesh = 4 57 Mesh = 4
58 } 58 }
59 59
60 public string Url { get; set; }
61
62 /// <summary>
63 /// Number of requests received for this poll service.
64 /// </summary>
65 public int RequestsReceived { get; set; }
66
67 /// <summary>
68 /// Number of requests handled by this poll service.
69 /// </summary>
70 public int RequestsHandled { get; set; }
71
60 public PollServiceEventArgs( 72 public PollServiceEventArgs(
61 RequestMethod pRequest, 73 RequestMethod pRequest,
74 string pUrl,
62 HasEventsMethod pHasEvents, GetEventsMethod pGetEvents, NoEventsMethod pNoEvents, 75 HasEventsMethod pHasEvents, GetEventsMethod pGetEvents, NoEventsMethod pNoEvents,
63 UUID pId, int pTimeOutms) 76 UUID pId, int pTimeOutms)
64 { 77 {
65 Request = pRequest; 78 Request = pRequest;
79 Url = pUrl;
66 HasEvents = pHasEvents; 80 HasEvents = pHasEvents;
67 GetEvents = pGetEvents; 81 GetEvents = pGetEvents;
68 NoEvents = pNoEvents; 82 NoEvents = pNoEvents;
69 Id = pId; 83 Id = pId;
70 TimeOutms = pTimeOutms; 84 TimeOutms = pTimeOutms;
71 Type = EventType.Normal; 85 Type = EventType.LongPoll;
72 } 86 }
73 } 87 }
74} 88}
diff --git a/OpenSim/Framework/Servers/HttpServer/PollServiceHttpRequest.cs b/OpenSim/Framework/Servers/HttpServer/PollServiceHttpRequest.cs
index 723530a..6aa9479 100644
--- a/OpenSim/Framework/Servers/HttpServer/PollServiceHttpRequest.cs
+++ b/OpenSim/Framework/Servers/HttpServer/PollServiceHttpRequest.cs
@@ -26,13 +26,19 @@
26 */ 26 */
27 27
28using System; 28using System;
29using System.Collections;
30using System.Reflection;
31using System.Text;
29using HttpServer; 32using HttpServer;
33using log4net;
30using OpenMetaverse; 34using OpenMetaverse;
31 35
32namespace OpenSim.Framework.Servers.HttpServer 36namespace OpenSim.Framework.Servers.HttpServer
33{ 37{
34 public class PollServiceHttpRequest 38 public class PollServiceHttpRequest
35 { 39 {
40 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
41
36 public readonly PollServiceEventArgs PollServiceArgs; 42 public readonly PollServiceEventArgs PollServiceArgs;
37 public readonly IHttpClientContext HttpContext; 43 public readonly IHttpClientContext HttpContext;
38 public readonly IHttpRequest Request; 44 public readonly IHttpRequest Request;
@@ -48,5 +54,44 @@ namespace OpenSim.Framework.Servers.HttpServer
48 RequestTime = System.Environment.TickCount; 54 RequestTime = System.Environment.TickCount;
49 RequestID = UUID.Random(); 55 RequestID = UUID.Random();
50 } 56 }
57
58 internal void DoHTTPGruntWork(BaseHttpServer server, Hashtable responsedata)
59 {
60 OSHttpResponse response
61 = new OSHttpResponse(new HttpResponse(HttpContext, Request), HttpContext);
62
63 byte[] buffer = server.DoHTTPGruntWork(responsedata, response);
64
65 response.SendChunked = false;
66 response.ContentLength64 = buffer.Length;
67 response.ContentEncoding = Encoding.UTF8;
68
69 try
70 {
71 response.OutputStream.Write(buffer, 0, buffer.Length);
72 }
73 catch (Exception ex)
74 {
75 m_log.Warn(string.Format("[POLL SERVICE WORKER THREAD]: Error ", ex));
76 }
77 finally
78 {
79 //response.OutputStream.Close();
80 try
81 {
82 response.OutputStream.Flush();
83 response.Send();
84
85 //if (!response.KeepAlive && response.ReuseContext)
86 // response.FreeContext();
87 }
88 catch (Exception e)
89 {
90 m_log.Warn(String.Format("[POLL SERVICE WORKER THREAD]: Error ", e));
91 }
92
93 PollServiceArgs.RequestsHandled++;
94 }
95 }
51 } 96 }
52} \ No newline at end of file 97} \ No newline at end of file
diff --git a/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs b/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs
index 5406f00..4058229 100644
--- a/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs
+++ b/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs
@@ -64,14 +64,17 @@ namespace OpenSim.Framework.Servers.HttpServer
64 m_server = pSrv; 64 m_server = pSrv;
65 m_WorkerThreadCount = pWorkerThreadCount; 65 m_WorkerThreadCount = pWorkerThreadCount;
66 m_workerThreads = new Thread[m_WorkerThreadCount]; 66 m_workerThreads = new Thread[m_WorkerThreadCount];
67 }
67 68
69 public void Start()
70 {
68 //startup worker threads 71 //startup worker threads
69 for (uint i = 0; i < m_WorkerThreadCount; i++) 72 for (uint i = 0; i < m_WorkerThreadCount; i++)
70 { 73 {
71 m_workerThreads[i] 74 m_workerThreads[i]
72 = Watchdog.StartThread( 75 = Watchdog.StartThread(
73 PoolWorkerJob, 76 PoolWorkerJob,
74 String.Format("PollServiceWorkerThread{0}", i), 77 string.Format("PollServiceWorkerThread{0}:{1}", i, m_server.Port),
75 ThreadPriority.Normal, 78 ThreadPriority.Normal,
76 false, 79 false,
77 false, 80 false,
@@ -81,7 +84,7 @@ namespace OpenSim.Framework.Servers.HttpServer
81 84
82 m_retrysThread = Watchdog.StartThread( 85 m_retrysThread = Watchdog.StartThread(
83 this.CheckRetries, 86 this.CheckRetries,
84 "PollServiceWatcherThread", 87 string.Format("PollServiceWatcherThread:{0}", m_server.Port),
85 ThreadPriority.Normal, 88 ThreadPriority.Normal,
86 false, 89 false,
87 true, 90 true,
@@ -89,7 +92,6 @@ namespace OpenSim.Framework.Servers.HttpServer
89 1000 * 60 * 10); 92 1000 * 60 * 10);
90 } 93 }
91 94
92
93 private void ReQueueEvent(PollServiceHttpRequest req) 95 private void ReQueueEvent(PollServiceHttpRequest req)
94 { 96 {
95 if (m_running) 97 if (m_running)
@@ -103,7 +105,7 @@ namespace OpenSim.Framework.Servers.HttpServer
103 { 105 {
104 if (m_running) 106 if (m_running)
105 { 107 {
106 if (req.PollServiceArgs.Type != PollServiceEventArgs.EventType.Normal) 108 if (req.PollServiceArgs.Type != PollServiceEventArgs.EventType.LongPoll)
107 { 109 {
108 m_requests.Enqueue(req); 110 m_requests.Enqueue(req);
109 } 111 }
@@ -140,19 +142,19 @@ namespace OpenSim.Framework.Servers.HttpServer
140 } 142 }
141 } 143 }
142 144
143 ~PollServiceRequestManager() 145 public void Stop()
144 { 146 {
145 m_running = false; 147 m_running = false;
146 Thread.Sleep(1000); // let the world move 148 Thread.Sleep(1000); // let the world move
147 149
148 foreach (Thread t in m_workerThreads) 150 foreach (Thread t in m_workerThreads)
149 Watchdog.AbortThread(t.ManagedThreadId); 151 Watchdog.AbortThread(t.ManagedThreadId);
150 152
151 try 153 try
152 { 154 {
153 foreach (PollServiceHttpRequest req in m_retryRequests) 155 foreach (PollServiceHttpRequest req in m_retryRequests)
154 { 156 {
155 DoHTTPGruntWork(m_server,req, 157 req.DoHTTPGruntWork(m_server,
156 req.PollServiceArgs.NoEvents(req.RequestID, req.PollServiceArgs.Id)); 158 req.PollServiceArgs.NoEvents(req.RequestID, req.PollServiceArgs.Id));
157 } 159 }
158 } 160 }
@@ -174,7 +176,7 @@ namespace OpenSim.Framework.Servers.HttpServer
174 try 176 try
175 { 177 {
176 wreq = m_requests.Dequeue(0); 178 wreq = m_requests.Dequeue(0);
177 DoHTTPGruntWork(m_server,wreq, 179 wreq.DoHTTPGruntWork(m_server,
178 wreq.PollServiceArgs.NoEvents(wreq.RequestID, wreq.PollServiceArgs.Id)); 180 wreq.PollServiceArgs.NoEvents(wreq.RequestID, wreq.PollServiceArgs.Id));
179 } 181 }
180 catch 182 catch
@@ -202,14 +204,11 @@ namespace OpenSim.Framework.Servers.HttpServer
202 { 204 {
203 Hashtable responsedata = req.PollServiceArgs.GetEvents(req.RequestID, req.PollServiceArgs.Id); 205 Hashtable responsedata = req.PollServiceArgs.GetEvents(req.RequestID, req.PollServiceArgs.Id);
204 206
205 if (responsedata == null) 207 if (req.PollServiceArgs.Type == PollServiceEventArgs.EventType.LongPoll) // This is the event queue
206 continue;
207
208 if (req.PollServiceArgs.Type == PollServiceEventArgs.EventType.Normal) // This is the event queue
209 { 208 {
210 try 209 try
211 { 210 {
212 DoHTTPGruntWork(m_server, req, responsedata); 211 req.DoHTTPGruntWork(m_server, responsedata);
213 } 212 }
214 catch (ObjectDisposedException) // Browser aborted before we could read body, server closed the stream 213 catch (ObjectDisposedException) // Browser aborted before we could read body, server closed the stream
215 { 214 {
@@ -222,7 +221,7 @@ namespace OpenSim.Framework.Servers.HttpServer
222 { 221 {
223 try 222 try
224 { 223 {
225 DoHTTPGruntWork(m_server, req, responsedata); 224 req.DoHTTPGruntWork(m_server, responsedata);
226 } 225 }
227 catch (ObjectDisposedException) // Browser aborted before we could read body, server closed the stream 226 catch (ObjectDisposedException) // Browser aborted before we could read body, server closed the stream
228 { 227 {
@@ -237,7 +236,7 @@ namespace OpenSim.Framework.Servers.HttpServer
237 { 236 {
238 if ((Environment.TickCount - req.RequestTime) > req.PollServiceArgs.TimeOutms) 237 if ((Environment.TickCount - req.RequestTime) > req.PollServiceArgs.TimeOutms)
239 { 238 {
240 DoHTTPGruntWork(m_server, req, 239 req.DoHTTPGruntWork(m_server,
241 req.PollServiceArgs.NoEvents(req.RequestID, req.PollServiceArgs.Id)); 240 req.PollServiceArgs.NoEvents(req.RequestID, req.PollServiceArgs.Id));
242 } 241 }
243 else 242 else
@@ -254,41 +253,6 @@ namespace OpenSim.Framework.Servers.HttpServer
254 } 253 }
255 } 254 }
256 255
257 // DoHTTPGruntWork changed, not sending response
258 // do the same work around as core
259
260 internal static void DoHTTPGruntWork(BaseHttpServer server, PollServiceHttpRequest req, Hashtable responsedata)
261 {
262 OSHttpResponse response
263 = new OSHttpResponse(new HttpResponse(req.HttpContext, req.Request), req.HttpContext);
264
265 byte[] buffer = server.DoHTTPGruntWork(responsedata, response);
266
267 response.SendChunked = false;
268 response.ContentLength64 = buffer.Length;
269 response.ContentEncoding = Encoding.UTF8;
270
271 try
272 {
273 response.OutputStream.Write(buffer, 0, buffer.Length);
274 }
275 catch (Exception ex)
276 {
277 m_log.Warn(string.Format("[POLL SERVICE WORKER THREAD]: Error ", ex));
278 }
279 finally
280 {
281 try
282 {
283 response.OutputStream.Flush();
284 response.Send();
285 }
286 catch (Exception e)
287 {
288 m_log.Warn(String.Format("[POLL SERVICE WORKER THREAD]: Error ", e));
289 }
290 }
291 }
292 } 256 }
293} 257}
294 258
diff --git a/OpenSim/Framework/Servers/HttpServer/Properties/AssemblyInfo.cs b/OpenSim/Framework/Servers/HttpServer/Properties/AssemblyInfo.cs
index 8e592c1..f409667 100644
--- a/OpenSim/Framework/Servers/HttpServer/Properties/AssemblyInfo.cs
+++ b/OpenSim/Framework/Servers/HttpServer/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.6.*")] 32[assembly: AssemblyVersion("0.8.0.*")]
33 33
diff --git a/OpenSim/Framework/Servers/HttpServer/RestDeserialiseHandler.cs b/OpenSim/Framework/Servers/HttpServer/RestDeserialiseHandler.cs
index 07082a8..bd55657 100644
--- a/OpenSim/Framework/Servers/HttpServer/RestDeserialiseHandler.cs
+++ b/OpenSim/Framework/Servers/HttpServer/RestDeserialiseHandler.cs
@@ -33,7 +33,7 @@ namespace OpenSim.Framework.Servers.HttpServer
33{ 33{
34 public delegate TResponse RestDeserialiseMethod<TRequest, TResponse>(TRequest request); 34 public delegate TResponse RestDeserialiseMethod<TRequest, TResponse>(TRequest request);
35 35
36 public class RestDeserialiseHandler<TRequest, TResponse> : BaseRequestHandler, IStreamHandler 36 public class RestDeserialiseHandler<TRequest, TResponse> : BaseOutputStreamHandler, IStreamHandler
37 where TRequest : new() 37 where TRequest : new()
38 { 38 {
39 private RestDeserialiseMethod<TRequest, TResponse> m_method; 39 private RestDeserialiseMethod<TRequest, TResponse> m_method;
@@ -48,7 +48,7 @@ namespace OpenSim.Framework.Servers.HttpServer
48 m_method = method; 48 m_method = method;
49 } 49 }
50 50
51 public void Handle(string path, Stream request, Stream responseStream, 51 protected override void ProcessRequest(string path, Stream request, Stream responseStream,
52 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) 52 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
53 { 53 {
54 TRequest deserial; 54 TRequest deserial;
diff --git a/OpenSim/Framework/Servers/HttpServer/RestSessionService.cs b/OpenSim/Framework/Servers/HttpServer/RestSessionService.cs
index edcd134..83c9848 100644
--- a/OpenSim/Framework/Servers/HttpServer/RestSessionService.cs
+++ b/OpenSim/Framework/Servers/HttpServer/RestSessionService.cs
@@ -183,7 +183,7 @@ namespace OpenSim.Framework.Servers.HttpServer
183 183
184 public delegate bool CheckIdentityMethod(string sid, string aid); 184 public delegate bool CheckIdentityMethod(string sid, string aid);
185 185
186 public class RestDeserialiseSecureHandler<TRequest, TResponse> : BaseRequestHandler, IStreamHandler 186 public class RestDeserialiseSecureHandler<TRequest, TResponse> : BaseOutputStreamHandler, IStreamHandler
187 where TRequest : new() 187 where TRequest : new()
188 { 188 {
189 private static readonly ILog m_log 189 private static readonly ILog m_log
@@ -201,7 +201,7 @@ namespace OpenSim.Framework.Servers.HttpServer
201 m_method = method; 201 m_method = method;
202 } 202 }
203 203
204 public void Handle(string path, Stream request, Stream responseStream, 204 protected override void ProcessRequest(string path, Stream request, Stream responseStream,
205 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) 205 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
206 { 206 {
207 RestSessionObject<TRequest> deserial = default(RestSessionObject<TRequest>); 207 RestSessionObject<TRequest> deserial = default(RestSessionObject<TRequest>);
@@ -237,7 +237,7 @@ namespace OpenSim.Framework.Servers.HttpServer
237 237
238 public delegate bool CheckTrustedSourceMethod(IPEndPoint peer); 238 public delegate bool CheckTrustedSourceMethod(IPEndPoint peer);
239 239
240 public class RestDeserialiseTrustedHandler<TRequest, TResponse> : BaseRequestHandler, IStreamHandler 240 public class RestDeserialiseTrustedHandler<TRequest, TResponse> : BaseOutputStreamHandler, IStreamHandler
241 where TRequest : new() 241 where TRequest : new()
242 { 242 {
243 private static readonly ILog m_log 243 private static readonly ILog m_log
@@ -260,7 +260,7 @@ namespace OpenSim.Framework.Servers.HttpServer
260 m_method = method; 260 m_method = method;
261 } 261 }
262 262
263 public void Handle(string path, Stream request, Stream responseStream, 263 protected override void ProcessRequest(string path, Stream request, Stream responseStream,
264 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) 264 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
265 { 265 {
266 TRequest deserial = default(TRequest); 266 TRequest deserial = default(TRequest);
@@ -292,6 +292,5 @@ namespace OpenSim.Framework.Servers.HttpServer
292 serializer.Serialize(xmlWriter, response); 292 serializer.Serialize(xmlWriter, response);
293 } 293 }
294 } 294 }
295 } 295 }
296 296} \ No newline at end of file
297}
diff --git a/OpenSim/Framework/Servers/HttpServer/RestStreamHandler.cs b/OpenSim/Framework/Servers/HttpServer/RestStreamHandler.cs
index 1f17fee..0305dee 100644
--- a/OpenSim/Framework/Servers/HttpServer/RestStreamHandler.cs
+++ b/OpenSim/Framework/Servers/HttpServer/RestStreamHandler.cs
@@ -48,7 +48,7 @@ namespace OpenSim.Framework.Servers.HttpServer
48 m_restMethod = restMethod; 48 m_restMethod = restMethod;
49 } 49 }
50 50
51 public override byte[] Handle(string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) 51 protected override byte[] ProcessRequest(string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
52 { 52 {
53 Encoding encoding = Encoding.UTF8; 53 Encoding encoding = Encoding.UTF8;
54 StreamReader streamReader = new StreamReader(request, encoding); 54 StreamReader streamReader = new StreamReader(request, encoding);
diff --git a/OpenSim/Framework/Servers/HttpServer/WebsocketServerHandler.cs b/OpenSim/Framework/Servers/HttpServer/WebsocketServerHandler.cs
index ee96b47..c2925e3 100644
--- a/OpenSim/Framework/Servers/HttpServer/WebsocketServerHandler.cs
+++ b/OpenSim/Framework/Servers/HttpServer/WebsocketServerHandler.cs
@@ -28,8 +28,10 @@
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.IO; 30using System.IO;
31using System.Net;
31using System.Security.Cryptography; 32using System.Security.Cryptography;
32using System.Text; 33using System.Text;
34using System.Threading;
33using HttpServer; 35using HttpServer;
34 36
35namespace OpenSim.Framework.Servers.HttpServer 37namespace OpenSim.Framework.Servers.HttpServer
@@ -75,7 +77,7 @@ namespace OpenSim.Framework.Servers.HttpServer
75 /// <summary> 77 /// <summary>
76 /// This is a regular HTTP Request... This may be removed in the future. 78 /// This is a regular HTTP Request... This may be removed in the future.
77 /// </summary> 79 /// </summary>
78 public event RegularHttpRequestDelegate OnRegularHttpRequest; 80// public event RegularHttpRequestDelegate OnRegularHttpRequest;
79 81
80 /// <summary> 82 /// <summary>
81 /// When the upgrade from a HTTP request to a Websocket is completed, this will be fired 83 /// When the upgrade from a HTTP request to a Websocket is completed, this will be fired
@@ -98,6 +100,8 @@ namespace OpenSim.Framework.Servers.HttpServer
98 /// </summary> 100 /// </summary>
99 public ValidateHandshake HandshakeValidateMethodOverride = null; 101 public ValidateHandshake HandshakeValidateMethodOverride = null;
100 102
103 private ManualResetEvent _receiveDone = new ManualResetEvent(false);
104
101 private OSHttpRequest _request; 105 private OSHttpRequest _request;
102 private HTTPNetworkContext _networkContext; 106 private HTTPNetworkContext _networkContext;
103 private IHttpClientContext _clientContext; 107 private IHttpClientContext _clientContext;
@@ -109,6 +113,8 @@ namespace OpenSim.Framework.Servers.HttpServer
109 private bool _closing; 113 private bool _closing;
110 private bool _upgraded; 114 private bool _upgraded;
111 private int _maxPayloadBytes = 41943040; 115 private int _maxPayloadBytes = 41943040;
116 private int _initialMsgTimeout = 0;
117 private int _defaultReadTimeout = 10000;
112 118
113 private const string HandshakeAcceptText = 119 private const string HandshakeAcceptText =
114 "HTTP/1.1 101 Switching Protocols\r\n" + 120 "HTTP/1.1 101 Switching Protocols\r\n" +
@@ -131,6 +137,7 @@ namespace OpenSim.Framework.Servers.HttpServer
131 { 137 {
132 _request = preq; 138 _request = preq;
133 _networkContext = pContext.GiveMeTheNetworkStreamIKnowWhatImDoing(); 139 _networkContext = pContext.GiveMeTheNetworkStreamIKnowWhatImDoing();
140 _networkContext.Stream.ReadTimeout = _defaultReadTimeout;
134 _clientContext = pContext; 141 _clientContext = pContext;
135 _bufferLength = bufferlen; 142 _bufferLength = bufferlen;
136 _buffer = new byte[_bufferLength]; 143 _buffer = new byte[_bufferLength];
@@ -206,6 +213,16 @@ namespace OpenSim.Framework.Servers.HttpServer
206 } 213 }
207 214
208 /// <summary> 215 /// <summary>
216 /// Set this to the maximum amount of milliseconds to wait for the first complete message to be sent or received on the websocket after upgrading
217 /// Default, it waits forever. Use this when your Websocket consuming code opens a connection and waits for a message from the other side to avoid a Denial of Service vector.
218 /// </summary>
219 public int InitialMsgTimeout
220 {
221 get { return _initialMsgTimeout; }
222 set { _initialMsgTimeout = value; }
223 }
224
225 /// <summary>
209 /// This triggers the websocket start the upgrade process 226 /// This triggers the websocket start the upgrade process
210 /// </summary> 227 /// </summary>
211 public void HandshakeAndUpgrade() 228 public void HandshakeAndUpgrade()
@@ -245,6 +262,7 @@ namespace OpenSim.Framework.Servers.HttpServer
245 string rawaccept = string.Format(HandshakeAcceptText, acceptKey); 262 string rawaccept = string.Format(HandshakeAcceptText, acceptKey);
246 SendUpgradeSuccess(rawaccept); 263 SendUpgradeSuccess(rawaccept);
247 264
265
248 } 266 }
249 else 267 else
250 { 268 {
@@ -258,6 +276,10 @@ namespace OpenSim.Framework.Servers.HttpServer
258 SendUpgradeSuccess(rawaccept); 276 SendUpgradeSuccess(rawaccept);
259 } 277 }
260 } 278 }
279 public IPEndPoint GetRemoteIPEndpoint()
280 {
281 return _request.RemoteIPEndPoint;
282 }
261 283
262 /// <summary> 284 /// <summary>
263 /// Generates a handshake response key string based on the client's 285 /// Generates a handshake response key string based on the client's
@@ -290,9 +312,16 @@ namespace OpenSim.Framework.Servers.HttpServer
290 WebSocketState socketState = new WebSocketState() { ReceivedBytes = new List<byte>(), Header = WebsocketFrameHeader.HeaderDefault(), FrameComplete = true}; 312 WebSocketState socketState = new WebSocketState() { ReceivedBytes = new List<byte>(), Header = WebsocketFrameHeader.HeaderDefault(), FrameComplete = true};
291 313
292 byte[] bhandshakeResponse = Encoding.UTF8.GetBytes(pHandshakeResponse); 314 byte[] bhandshakeResponse = Encoding.UTF8.GetBytes(pHandshakeResponse);
315
316
317
318
293 try 319 try
294 { 320 {
295 321 if (_initialMsgTimeout > 0)
322 {
323 _receiveDone.Reset();
324 }
296 // Begin reading the TCP stream before writing the Upgrade success message to the other side of the stream. 325 // Begin reading the TCP stream before writing the Upgrade success message to the other side of the stream.
297 _networkContext.Stream.BeginRead(_buffer, 0, _bufferLength, OnReceive, socketState); 326 _networkContext.Stream.BeginRead(_buffer, 0, _bufferLength, OnReceive, socketState);
298 327
@@ -303,16 +332,20 @@ namespace OpenSim.Framework.Servers.HttpServer
303 UpgradeCompletedDelegate d = OnUpgradeCompleted; 332 UpgradeCompletedDelegate d = OnUpgradeCompleted;
304 if (d != null) 333 if (d != null)
305 d(this, new UpgradeCompletedEventArgs()); 334 d(this, new UpgradeCompletedEventArgs());
335 if (_initialMsgTimeout > 0)
336 {
337 if (!_receiveDone.WaitOne(TimeSpan.FromMilliseconds(_initialMsgTimeout)))
338 Close(string.Empty);
339 }
306 } 340 }
307 catch (IOException fail) 341 catch (IOException)
308 { 342 {
309 Close(string.Empty); 343 Close(string.Empty);
310 } 344 }
311 catch (ObjectDisposedException fail) 345 catch (ObjectDisposedException)
312 { 346 {
313 Close(string.Empty); 347 Close(string.Empty);
314 } 348 }
315
316 } 349 }
317 350
318 /// <summary> 351 /// <summary>
@@ -414,8 +447,6 @@ namespace OpenSim.Framework.Servers.HttpServer
414 _socketState.Header = pheader; 447 _socketState.Header = pheader;
415 } 448 }
416 449
417
418
419 if (_socketState.FrameComplete) 450 if (_socketState.FrameComplete)
420 { 451 {
421 ProcessFrame(_socketState); 452 ProcessFrame(_socketState);
@@ -424,7 +455,6 @@ namespace OpenSim.Framework.Servers.HttpServer
424 _socketState.ExpectedBytes = 0; 455 _socketState.ExpectedBytes = 0;
425 456
426 } 457 }
427
428 } 458 }
429 } 459 }
430 else 460 else
@@ -457,8 +487,7 @@ namespace OpenSim.Framework.Servers.HttpServer
457 _socketState.ReceivedBytes.Clear(); 487 _socketState.ReceivedBytes.Clear();
458 _socketState.ExpectedBytes = 0; 488 _socketState.ExpectedBytes = 0;
459 // do some processing 489 // do some processing
460 } 490 }
461
462 } 491 }
463 } 492 }
464 if (offset > 0) 493 if (offset > 0)
@@ -477,13 +506,12 @@ namespace OpenSim.Framework.Servers.HttpServer
477 { 506 {
478 // We can't read the stream anymore... 507 // We can't read the stream anymore...
479 } 508 }
480
481 } 509 }
482 catch (IOException fail) 510 catch (IOException)
483 { 511 {
484 Close(string.Empty); 512 Close(string.Empty);
485 } 513 }
486 catch (ObjectDisposedException fail) 514 catch (ObjectDisposedException)
487 { 515 {
488 Close(string.Empty); 516 Close(string.Empty);
489 } 517 }
@@ -495,6 +523,11 @@ namespace OpenSim.Framework.Servers.HttpServer
495 /// <param name="message">the string message that is to be sent</param> 523 /// <param name="message">the string message that is to be sent</param>
496 public void SendMessage(string message) 524 public void SendMessage(string message)
497 { 525 {
526 if (_initialMsgTimeout > 0)
527 {
528 _receiveDone.Set();
529 _initialMsgTimeout = 0;
530 }
498 byte[] messagedata = Encoding.UTF8.GetBytes(message); 531 byte[] messagedata = Encoding.UTF8.GetBytes(message);
499 WebSocketFrame textMessageFrame = new WebSocketFrame() { Header = WebsocketFrameHeader.HeaderDefault(), WebSocketPayload = messagedata }; 532 WebSocketFrame textMessageFrame = new WebSocketFrame() { Header = WebsocketFrameHeader.HeaderDefault(), WebSocketPayload = messagedata };
500 textMessageFrame.Header.Opcode = WebSocketReader.OpCode.Text; 533 textMessageFrame.Header.Opcode = WebSocketReader.OpCode.Text;
@@ -505,6 +538,11 @@ namespace OpenSim.Framework.Servers.HttpServer
505 538
506 public void SendData(byte[] data) 539 public void SendData(byte[] data)
507 { 540 {
541 if (_initialMsgTimeout > 0)
542 {
543 _receiveDone.Set();
544 _initialMsgTimeout = 0;
545 }
508 WebSocketFrame dataMessageFrame = new WebSocketFrame() { Header = WebsocketFrameHeader.HeaderDefault(), WebSocketPayload = data}; 546 WebSocketFrame dataMessageFrame = new WebSocketFrame() { Header = WebsocketFrameHeader.HeaderDefault(), WebSocketPayload = data};
509 dataMessageFrame.Header.IsEnd = true; 547 dataMessageFrame.Header.IsEnd = true;
510 dataMessageFrame.Header.Opcode = WebSocketReader.OpCode.Binary; 548 dataMessageFrame.Header.Opcode = WebSocketReader.OpCode.Binary;
@@ -537,6 +575,11 @@ namespace OpenSim.Framework.Servers.HttpServer
537 /// </summary> 575 /// </summary>
538 public void SendPingCheck() 576 public void SendPingCheck()
539 { 577 {
578 if (_initialMsgTimeout > 0)
579 {
580 _receiveDone.Set();
581 _initialMsgTimeout = 0;
582 }
540 WebSocketFrame pingFrame = new WebSocketFrame() { Header = WebsocketFrameHeader.HeaderDefault(), WebSocketPayload = new byte[0] }; 583 WebSocketFrame pingFrame = new WebSocketFrame() { Header = WebsocketFrameHeader.HeaderDefault(), WebSocketPayload = new byte[0] };
541 pingFrame.Header.Opcode = WebSocketReader.OpCode.Ping; 584 pingFrame.Header.Opcode = WebSocketReader.OpCode.Ping;
542 pingFrame.Header.IsEnd = true; 585 pingFrame.Header.IsEnd = true;
@@ -550,6 +593,11 @@ namespace OpenSim.Framework.Servers.HttpServer
550 /// <param name="message"></param> 593 /// <param name="message"></param>
551 public void Close(string message) 594 public void Close(string message)
552 { 595 {
596 if (_initialMsgTimeout > 0)
597 {
598 _receiveDone.Set();
599 _initialMsgTimeout = 0;
600 }
553 if (_networkContext == null) 601 if (_networkContext == null)
554 return; 602 return;
555 if (_networkContext.Stream != null) 603 if (_networkContext.Stream != null)
@@ -589,7 +637,11 @@ namespace OpenSim.Framework.Servers.HttpServer
589 WebSocketReader.Mask(psocketState.Header.Mask, unmask); 637 WebSocketReader.Mask(psocketState.Header.Mask, unmask);
590 psocketState.ReceivedBytes = new List<byte>(unmask); 638 psocketState.ReceivedBytes = new List<byte>(unmask);
591 } 639 }
592 640 if (psocketState.Header.Opcode != WebSocketReader.OpCode.Continue && _initialMsgTimeout > 0)
641 {
642 _receiveDone.Set();
643 _initialMsgTimeout = 0;
644 }
593 switch (psocketState.Header.Opcode) 645 switch (psocketState.Header.Opcode)
594 { 646 {
595 case WebSocketReader.OpCode.Ping: 647 case WebSocketReader.OpCode.Ping:
@@ -702,6 +754,11 @@ namespace OpenSim.Framework.Servers.HttpServer
702 } 754 }
703 public void Dispose() 755 public void Dispose()
704 { 756 {
757 if (_initialMsgTimeout > 0)
758 {
759 _receiveDone.Set();
760 _initialMsgTimeout = 0;
761 }
705 if (_networkContext != null && _networkContext.Stream != null) 762 if (_networkContext != null && _networkContext.Stream != null)
706 { 763 {
707 if (_networkContext.Stream.CanWrite) 764 if (_networkContext.Stream.CanWrite)
diff --git a/OpenSim/Framework/Servers/HttpServer/XmlRpcBasicDOSProtector.cs b/OpenSim/Framework/Servers/HttpServer/XmlRpcBasicDOSProtector.cs
new file mode 100644
index 0000000..f212208
--- /dev/null
+++ b/OpenSim/Framework/Servers/HttpServer/XmlRpcBasicDOSProtector.cs
@@ -0,0 +1,91 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System.Net;
29using Nwc.XmlRpc;
30using OpenSim.Framework;
31
32
33namespace OpenSim.Framework.Servers.HttpServer
34{
35 public class XmlRpcBasicDOSProtector
36 {
37 private readonly XmlRpcMethod _normalMethod;
38 private readonly XmlRpcMethod _throttledMethod;
39
40 private readonly BasicDosProtectorOptions _options;
41 private readonly BasicDOSProtector _dosProtector;
42
43 public XmlRpcBasicDOSProtector(XmlRpcMethod normalMethod, XmlRpcMethod throttledMethod,BasicDosProtectorOptions options)
44 {
45 _normalMethod = normalMethod;
46 _throttledMethod = throttledMethod;
47
48 _options = options;
49 _dosProtector = new BasicDOSProtector(_options);
50
51 }
52 public XmlRpcResponse Process(XmlRpcRequest request, IPEndPoint client)
53 {
54
55 XmlRpcResponse resp = null;
56 string clientstring = GetClientString(request, client);
57 string endpoint = GetEndPoint(request, client);
58 if (_dosProtector.Process(clientstring, endpoint))
59 resp = _normalMethod(request, client);
60 else
61 resp = _throttledMethod(request, client);
62 if (_options.MaxConcurrentSessions > 0)
63 _dosProtector.ProcessEnd(clientstring, endpoint);
64 return resp;
65 }
66
67 private string GetClientString(XmlRpcRequest request, IPEndPoint client)
68 {
69 string clientstring;
70 if (_options.AllowXForwardedFor && request.Params.Count > 3)
71 {
72 object headerstr = request.Params[3];
73 if (headerstr != null && !string.IsNullOrEmpty(headerstr.ToString()))
74 clientstring = request.Params[3].ToString();
75 else
76 clientstring = client.Address.ToString();
77 }
78 else
79 clientstring = client.Address.ToString();
80 return clientstring;
81 }
82
83 private string GetEndPoint(XmlRpcRequest request, IPEndPoint client)
84 {
85 return client.Address.ToString();
86 }
87
88 }
89
90
91}
diff --git a/OpenSim/Framework/Servers/MainServer.cs b/OpenSim/Framework/Servers/MainServer.cs
index cfd34bb..57931d4 100644
--- a/OpenSim/Framework/Servers/MainServer.cs
+++ b/OpenSim/Framework/Servers/MainServer.cs
@@ -121,12 +121,14 @@ namespace OpenSim.Framework.Servers
121 + " level >= 2 then long warnings are logged when receiving bad input data.\n" 121 + " level >= 2 then long warnings are logged when receiving bad input data.\n"
122 + " level >= 3 then short notices about all incoming non-poll HTTP requests are logged.\n" 122 + " level >= 3 then short notices about all incoming non-poll HTTP requests are logged.\n"
123 + " level >= 4 then the time taken to fulfill the request is logged.\n" 123 + " level >= 4 then the time taken to fulfill the request is logged.\n"
124 + " level >= 5 then a sample from the beginning of the incoming data is logged.\n" 124 + " level >= 5 then a sample from the beginning of the data is logged.\n"
125 + " level >= 6 then the entire incoming data is logged.\n" 125 + " level >= 6 then the entire data is logged.\n"
126 + " no level is specified then the current level is returned.\n\n" 126 + " no level is specified then the current level is returned.\n\n"
127 + "If out or all and\n" 127 + "If out or all and\n"
128 + " level >= 3 then short notices about all outgoing requests going through WebUtil are logged.\n" 128 + " level >= 3 then short notices about all outgoing requests going through WebUtil are logged.\n"
129 + " level >= 4 then the time taken to fulfill the request is logged.\n", 129 + " level >= 4 then the time taken to fulfill the request is logged.\n"
130 + " level >= 5 then a sample from the beginning of the data is logged.\n"
131 + " level >= 6 then the entire data is logged.\n",
130 HandleDebugHttpCommand); 132 HandleDebugHttpCommand);
131 } 133 }
132 134
@@ -283,7 +285,12 @@ namespace OpenSim.Framework.Servers
283 public static bool RemoveHttpServer(uint port) 285 public static bool RemoveHttpServer(uint port)
284 { 286 {
285 lock (m_Servers) 287 lock (m_Servers)
288 {
289 if (instance != null && instance.Port == port)
290 instance = null;
291
286 return m_Servers.Remove(port); 292 return m_Servers.Remove(port);
293 }
287 } 294 }
288 295
289 /// <summary> 296 /// <summary>
diff --git a/OpenSim/Framework/Servers/ServerBase.cs b/OpenSim/Framework/Servers/ServerBase.cs
index 1ff8aca..7108314 100644
--- a/OpenSim/Framework/Servers/ServerBase.cs
+++ b/OpenSim/Framework/Servers/ServerBase.cs
@@ -62,6 +62,8 @@ namespace OpenSim.Framework.Servers
62 62
63 protected string m_pidFile = String.Empty; 63 protected string m_pidFile = String.Empty;
64 64
65 protected ServerStatsCollector m_serverStatsCollector;
66
65 /// <summary> 67 /// <summary>
66 /// Server version information. Usually VersionInfo + information about git commit, operating system, etc. 68 /// Server version information. Usually VersionInfo + information about git commit, operating system, etc.
67 /// </summary> 69 /// </summary>
@@ -76,6 +78,11 @@ namespace OpenSim.Framework.Servers
76 78
77 protected void CreatePIDFile(string path) 79 protected void CreatePIDFile(string path)
78 { 80 {
81 if (File.Exists(path))
82 m_log.ErrorFormat(
83 "[SERVER BASE]: Previous pid file {0} still exists on startup. Possibly previously unclean shutdown.",
84 path);
85
79 try 86 try
80 { 87 {
81 string pidstring = System.Diagnostics.Process.GetCurrentProcess().Id.ToString(); 88 string pidstring = System.Diagnostics.Process.GetCurrentProcess().Id.ToString();
@@ -239,7 +246,7 @@ namespace OpenSim.Framework.Servers
239 "Show thread status", HandleShow); 246 "Show thread status", HandleShow);
240 247
241 m_console.Commands.AddCommand( 248 m_console.Commands.AddCommand(
242 "General", false, "threads abort", 249 "Debug", false, "threads abort",
243 "threads abort <thread-id>", 250 "threads abort <thread-id>",
244 "Abort a managed thread. Use \"show threads\" to find possible threads.", HandleThreadsAbort); 251 "Abort a managed thread. Use \"show threads\" to find possible threads.", HandleThreadsAbort);
245 252
@@ -249,11 +256,180 @@ namespace OpenSim.Framework.Servers
249 "Show thread status. Synonym for \"show threads\"", 256 "Show thread status. Synonym for \"show threads\"",
250 (string module, string[] args) => Notice(GetThreadsReport())); 257 (string module, string[] args) => Notice(GetThreadsReport()));
251 258
259 m_console.Commands.AddCommand (
260 "Debug", false, "debug comms set",
261 "debug comms set serialosdreq true|false",
262 "Set comms parameters. For debug purposes.",
263 HandleDebugCommsSet);
264
265 m_console.Commands.AddCommand (
266 "Debug", false, "debug comms status",
267 "debug comms status",
268 "Show current debug comms parameters.",
269 HandleDebugCommsStatus);
270
271 m_console.Commands.AddCommand (
272 "Debug", false, "debug threadpool set",
273 "debug threadpool set worker|iocp min|max <n>",
274 "Set threadpool parameters. For debug purposes.",
275 HandleDebugThreadpoolSet);
276
277 m_console.Commands.AddCommand (
278 "Debug", false, "debug threadpool status",
279 "debug threadpool status",
280 "Show current debug threadpool parameters.",
281 HandleDebugThreadpoolStatus);
282
252 m_console.Commands.AddCommand( 283 m_console.Commands.AddCommand(
253 "General", false, "force gc", 284 "Debug", false, "force gc",
254 "force gc", 285 "force gc",
255 "Manually invoke runtime garbage collection. For debugging purposes", 286 "Manually invoke runtime garbage collection. For debugging purposes",
256 HandleForceGc); 287 HandleForceGc);
288
289 m_console.Commands.AddCommand(
290 "General", false, "quit",
291 "quit",
292 "Quit the application", (mod, args) => Shutdown());
293
294 m_console.Commands.AddCommand(
295 "General", false, "shutdown",
296 "shutdown",
297 "Quit the application", (mod, args) => Shutdown());
298
299 ChecksManager.RegisterConsoleCommands(m_console);
300 StatsManager.RegisterConsoleCommands(m_console);
301 }
302
303 public void RegisterCommonComponents(IConfigSource configSource)
304 {
305 IConfig networkConfig = configSource.Configs["Network"];
306
307 if (networkConfig != null)
308 {
309 WebUtil.SerializeOSDRequestsPerEndpoint = networkConfig.GetBoolean("SerializeOSDRequests", false);
310 }
311
312 m_serverStatsCollector = new ServerStatsCollector();
313 m_serverStatsCollector.Initialise(configSource);
314 m_serverStatsCollector.Start();
315 }
316
317 private void HandleDebugCommsStatus(string module, string[] args)
318 {
319 Notice("serialosdreq is {0}", WebUtil.SerializeOSDRequestsPerEndpoint);
320 }
321
322 private void HandleDebugCommsSet(string module, string[] args)
323 {
324 if (args.Length != 5)
325 {
326 Notice("Usage: debug comms set serialosdreq true|false");
327 return;
328 }
329
330 if (args[3] != "serialosdreq")
331 {
332 Notice("Usage: debug comms set serialosdreq true|false");
333 return;
334 }
335
336 bool setSerializeOsdRequests;
337
338 if (!ConsoleUtil.TryParseConsoleBool(m_console, args[4], out setSerializeOsdRequests))
339 return;
340
341 WebUtil.SerializeOSDRequestsPerEndpoint = setSerializeOsdRequests;
342
343 Notice("serialosdreq is now {0}", setSerializeOsdRequests);
344 }
345
346 private void HandleDebugThreadpoolStatus(string module, string[] args)
347 {
348 int workerThreads, iocpThreads;
349
350 ThreadPool.GetMinThreads(out workerThreads, out iocpThreads);
351 Notice("Min worker threads: {0}", workerThreads);
352 Notice("Min IOCP threads: {0}", iocpThreads);
353
354 ThreadPool.GetMaxThreads(out workerThreads, out iocpThreads);
355 Notice("Max worker threads: {0}", workerThreads);
356 Notice("Max IOCP threads: {0}", iocpThreads);
357
358 ThreadPool.GetAvailableThreads(out workerThreads, out iocpThreads);
359 Notice("Available worker threads: {0}", workerThreads);
360 Notice("Available IOCP threads: {0}", iocpThreads);
361 }
362
363 private void HandleDebugThreadpoolSet(string module, string[] args)
364 {
365 if (args.Length != 6)
366 {
367 Notice("Usage: debug threadpool set worker|iocp min|max <n>");
368 return;
369 }
370
371 int newThreads;
372
373 if (!ConsoleUtil.TryParseConsoleInt(m_console, args[5], out newThreads))
374 return;
375
376 string poolType = args[3];
377 string bound = args[4];
378
379 bool fail = false;
380 int workerThreads, iocpThreads;
381
382 if (poolType == "worker")
383 {
384 if (bound == "min")
385 {
386 ThreadPool.GetMinThreads(out workerThreads, out iocpThreads);
387
388 if (!ThreadPool.SetMinThreads(newThreads, iocpThreads))
389 fail = true;
390 }
391 else
392 {
393 ThreadPool.GetMaxThreads(out workerThreads, out iocpThreads);
394
395 if (!ThreadPool.SetMaxThreads(newThreads, iocpThreads))
396 fail = true;
397 }
398 }
399 else
400 {
401 if (bound == "min")
402 {
403 ThreadPool.GetMinThreads(out workerThreads, out iocpThreads);
404
405 if (!ThreadPool.SetMinThreads(workerThreads, newThreads))
406 fail = true;
407 }
408 else
409 {
410 ThreadPool.GetMaxThreads(out workerThreads, out iocpThreads);
411
412 if (!ThreadPool.SetMaxThreads(workerThreads, newThreads))
413 fail = true;
414 }
415 }
416
417 if (fail)
418 {
419 Notice("ERROR: Could not set {0} {1} threads to {2}", poolType, bound, newThreads);
420 }
421 else
422 {
423 int minWorkerThreads, maxWorkerThreads, minIocpThreads, maxIocpThreads;
424
425 ThreadPool.GetMinThreads(out minWorkerThreads, out minIocpThreads);
426 ThreadPool.GetMaxThreads(out maxWorkerThreads, out maxIocpThreads);
427
428 Notice("Min worker threads now {0}", minWorkerThreads);
429 Notice("Min IOCP threads now {0}", minIocpThreads);
430 Notice("Max worker threads now {0}", maxWorkerThreads);
431 Notice("Max IOCP threads now {0}", maxIocpThreads);
432 }
257 } 433 }
258 434
259 private void HandleForceGc(string module, string[] args) 435 private void HandleForceGc(string module, string[] args)
@@ -641,7 +817,68 @@ namespace OpenSim.Framework.Servers
641 sb.AppendFormat("Total threads active: {0}\n\n", totalThreads); 817 sb.AppendFormat("Total threads active: {0}\n\n", totalThreads);
642 818
643 sb.Append("Main threadpool (excluding script engine pools)\n"); 819 sb.Append("Main threadpool (excluding script engine pools)\n");
644 sb.Append(Util.GetThreadPoolReport()); 820 sb.Append(GetThreadPoolReport());
821
822 return sb.ToString();
823 }
824
825 /// <summary>
826 /// Get a thread pool report.
827 /// </summary>
828 /// <returns></returns>
829 public static string GetThreadPoolReport()
830 {
831 string threadPoolUsed = null;
832 int maxThreads = 0;
833 int minThreads = 0;
834 int allocatedThreads = 0;
835 int inUseThreads = 0;
836 int waitingCallbacks = 0;
837 int completionPortThreads = 0;
838
839 StringBuilder sb = new StringBuilder();
840 if (Util.FireAndForgetMethod == FireAndForgetMethod.SmartThreadPool)
841 {
842 STPInfo stpi = Util.GetSmartThreadPoolInfo();
843
844 // ROBUST currently leaves this the FireAndForgetMethod but never actually initializes the threadpool.
845 if (stpi != null)
846 {
847 threadPoolUsed = "SmartThreadPool";
848 maxThreads = stpi.MaxThreads;
849 minThreads = stpi.MinThreads;
850 inUseThreads = stpi.InUseThreads;
851 allocatedThreads = stpi.ActiveThreads;
852 waitingCallbacks = stpi.WaitingCallbacks;
853 }
854 }
855 else if (
856 Util.FireAndForgetMethod == FireAndForgetMethod.QueueUserWorkItem
857 || Util.FireAndForgetMethod == FireAndForgetMethod.UnsafeQueueUserWorkItem)
858 {
859 threadPoolUsed = "BuiltInThreadPool";
860 ThreadPool.GetMaxThreads(out maxThreads, out completionPortThreads);
861 ThreadPool.GetMinThreads(out minThreads, out completionPortThreads);
862 int availableThreads;
863 ThreadPool.GetAvailableThreads(out availableThreads, out completionPortThreads);
864 inUseThreads = maxThreads - availableThreads;
865 allocatedThreads = -1;
866 waitingCallbacks = -1;
867 }
868
869 if (threadPoolUsed != null)
870 {
871 sb.AppendFormat("Thread pool used : {0}\n", threadPoolUsed);
872 sb.AppendFormat("Max threads : {0}\n", maxThreads);
873 sb.AppendFormat("Min threads : {0}\n", minThreads);
874 sb.AppendFormat("Allocated threads : {0}\n", allocatedThreads < 0 ? "not applicable" : allocatedThreads.ToString());
875 sb.AppendFormat("In use threads : {0}\n", inUseThreads);
876 sb.AppendFormat("Work items waiting : {0}\n", waitingCallbacks < 0 ? "not available" : waitingCallbacks.ToString());
877 }
878 else
879 {
880 sb.AppendFormat("Thread pool not used\n");
881 }
645 882
646 return sb.ToString(); 883 return sb.ToString();
647 } 884 }
@@ -693,5 +930,16 @@ namespace OpenSim.Framework.Servers
693 if (m_console != null) 930 if (m_console != null)
694 m_console.OutputFormat(format, components); 931 m_console.OutputFormat(format, components);
695 } 932 }
933
934 public virtual void Shutdown()
935 {
936 m_serverStatsCollector.Close();
937 ShutdownSpecific();
938 }
939
940 /// <summary>
941 /// Should be overriden and referenced by descendents if they need to perform extra shutdown processing
942 /// </summary>
943 protected virtual void ShutdownSpecific() {}
696 } 944 }
697} 945}
diff --git a/OpenSim/Framework/Servers/VersionInfo.cs b/OpenSim/Framework/Servers/VersionInfo.cs
index 737c14d..33b1366 100644
--- a/OpenSim/Framework/Servers/VersionInfo.cs
+++ b/OpenSim/Framework/Servers/VersionInfo.cs
@@ -29,7 +29,7 @@ namespace OpenSim
29{ 29{
30 public class VersionInfo 30 public class VersionInfo
31 { 31 {
32 private const string VERSION_NUMBER = "0.7.6CM"; 32 private const string VERSION_NUMBER = "0.8.0CM";
33 private const Flavour VERSION_FLAVOUR = Flavour.Dev; 33 private const Flavour VERSION_FLAVOUR = Flavour.Dev;
34 34
35 public enum Flavour 35 public enum Flavour