diff options
Diffstat (limited to '')
8 files changed, 681 insertions, 214 deletions
diff --git a/OpenSim/Framework/Servers/BaseOpenSimServer.cs b/OpenSim/Framework/Servers/BaseOpenSimServer.cs index 828a852..3426d10 100644 --- a/OpenSim/Framework/Servers/BaseOpenSimServer.cs +++ b/OpenSim/Framework/Servers/BaseOpenSimServer.cs | |||
@@ -65,6 +65,7 @@ namespace OpenSim.Framework.Servers | |||
65 | /// This will control a periodic log printout of the current 'show stats' (if they are active) for this | 65 | /// This will control a periodic log printout of the current 'show stats' (if they are active) for this |
66 | /// server. | 66 | /// server. |
67 | /// </summary> | 67 | /// </summary> |
68 | |||
68 | private int m_periodDiagnosticTimerMS = 60 * 60 * 1000; | 69 | private int m_periodDiagnosticTimerMS = 60 * 60 * 1000; |
69 | private Timer m_periodicDiagnosticsTimer = new Timer(60 * 60 * 1000); | 70 | private Timer m_periodicDiagnosticsTimer = new Timer(60 * 60 * 1000); |
70 | 71 | ||
@@ -83,7 +84,6 @@ namespace OpenSim.Framework.Servers | |||
83 | { | 84 | { |
84 | // Random uuid for private data | 85 | // Random uuid for private data |
85 | m_osSecret = UUID.Random().ToString(); | 86 | m_osSecret = UUID.Random().ToString(); |
86 | |||
87 | } | 87 | } |
88 | 88 | ||
89 | /// <summary> | 89 | /// <summary> |
@@ -146,14 +146,24 @@ namespace OpenSim.Framework.Servers | |||
146 | /// Performs initialisation of the scene, such as loading configuration from disk. | 146 | /// Performs initialisation of the scene, such as loading configuration from disk. |
147 | /// </summary> | 147 | /// </summary> |
148 | public virtual void Startup() | 148 | public virtual void Startup() |
149 | { | 149 | { |
150 | m_log.Info("[STARTUP]: Beginning startup processing"); | ||
151 | |||
152 | m_log.Info("[STARTUP]: version: " + m_version + Environment.NewLine); | ||
153 | // clr version potentially is more confusing than helpful, since it doesn't tell us if we're running under Mono/MS .NET and | ||
154 | // the clr version number doesn't match the project version number under Mono. | ||
155 | //m_log.Info("[STARTUP]: Virtual machine runtime version: " + Environment.Version + Environment.NewLine); | ||
156 | m_log.InfoFormat( | ||
157 | "[STARTUP]: Operating system version: {0}, .NET platform {1}, {2}-bit\n", | ||
158 | Environment.OSVersion, Environment.OSVersion.Platform, Util.Is64BitProcess() ? "64" : "32"); | ||
159 | |||
150 | StartupSpecific(); | 160 | StartupSpecific(); |
151 | 161 | ||
152 | TimeSpan timeTaken = DateTime.Now - m_startuptime; | 162 | TimeSpan timeTaken = DateTime.Now - m_startuptime; |
153 | 163 | ||
154 | MainConsole.Instance.OutputFormat( | 164 | // MainConsole.Instance.OutputFormat( |
155 | "PLEASE WAIT FOR LOGINS TO BE ENABLED ON REGIONS ONCE SCRIPTS HAVE STARTED. Non-script portion of startup took {0}m {1}s.", | 165 | // "PLEASE WAIT FOR LOGINS TO BE ENABLED ON REGIONS ONCE SCRIPTS HAVE STARTED. Non-script portion of startup took {0}m {1}s.", |
156 | timeTaken.Minutes, timeTaken.Seconds); | 166 | // timeTaken.Minutes, timeTaken.Seconds); |
157 | } | 167 | } |
158 | 168 | ||
159 | public string osSecret | 169 | public string osSecret |
@@ -175,4 +185,4 @@ namespace OpenSim.Framework.Servers | |||
175 | } | 185 | } |
176 | } | 186 | } |
177 | } | 187 | } |
178 | } \ No newline at end of file | 188 | } |
diff --git a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs index f252bd5..cd14212 100644 --- a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs +++ b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs | |||
@@ -403,6 +403,7 @@ namespace OpenSim.Framework.Servers.HttpServer | |||
403 | StreamReader reader = new StreamReader(requestStream, encoding); | 403 | StreamReader reader = new StreamReader(requestStream, encoding); |
404 | 404 | ||
405 | string requestBody = reader.ReadToEnd(); | 405 | string requestBody = reader.ReadToEnd(); |
406 | reader.Close(); | ||
406 | 407 | ||
407 | Hashtable keysvals = new Hashtable(); | 408 | Hashtable keysvals = new Hashtable(); |
408 | Hashtable headervals = new Hashtable(); | 409 | Hashtable headervals = new Hashtable(); |
@@ -460,7 +461,7 @@ namespace OpenSim.Framework.Servers.HttpServer | |||
460 | } | 461 | } |
461 | 462 | ||
462 | OSHttpResponse resp = new OSHttpResponse(new HttpResponse(context, request),context); | 463 | OSHttpResponse resp = new OSHttpResponse(new HttpResponse(context, request),context); |
463 | resp.ReuseContext = true; | 464 | resp.ReuseContext = false; |
464 | HandleRequest(req, resp); | 465 | HandleRequest(req, resp); |
465 | 466 | ||
466 | // !!!HACK ALERT!!! | 467 | // !!!HACK ALERT!!! |
@@ -759,7 +760,7 @@ namespace OpenSim.Framework.Servers.HttpServer | |||
759 | // Every month or so this will wrap and give bad numbers, not really a problem | 760 | // Every month or so this will wrap and give bad numbers, not really a problem |
760 | // since its just for reporting | 761 | // since its just for reporting |
761 | int tickdiff = requestEndTick - requestStartTick; | 762 | int tickdiff = requestEndTick - requestStartTick; |
762 | if (tickdiff > 3000 && requestHandler != null && requestHandler.Name != "GetTexture") | 763 | if (tickdiff > 3000 && (requestHandler == null || requestHandler.Name == null || requestHandler.Name != "GetTexture")) |
763 | { | 764 | { |
764 | m_log.InfoFormat( | 765 | m_log.InfoFormat( |
765 | "[LOGHTTP] Slow handling of {0} {1} {2} {3} {4} from {5} took {6}ms", | 766 | "[LOGHTTP] Slow handling of {0} {1} {2} {3} {4} from {5} took {6}ms", |
@@ -1024,6 +1025,19 @@ namespace OpenSim.Framework.Servers.HttpServer | |||
1024 | string responseString = String.Empty; | 1025 | string responseString = String.Empty; |
1025 | XmlRpcRequest xmlRprcRequest = null; | 1026 | XmlRpcRequest xmlRprcRequest = null; |
1026 | 1027 | ||
1028 | bool gridproxy = false; | ||
1029 | if (requestBody.Contains("encoding=\"utf-8")) | ||
1030 | { | ||
1031 | int channelindx = -1; | ||
1032 | int optionsindx = requestBody.IndexOf(">options<"); | ||
1033 | if(optionsindx >0) | ||
1034 | { | ||
1035 | channelindx = requestBody.IndexOf(">channel<"); | ||
1036 | if (optionsindx < channelindx) | ||
1037 | gridproxy = true; | ||
1038 | } | ||
1039 | } | ||
1040 | |||
1027 | try | 1041 | try |
1028 | { | 1042 | { |
1029 | xmlRprcRequest = (XmlRpcRequest) (new XmlRpcRequestDeserializer()).Deserialize(requestBody); | 1043 | xmlRprcRequest = (XmlRpcRequest) (new XmlRpcRequestDeserializer()).Deserialize(requestBody); |
@@ -1081,6 +1095,8 @@ namespace OpenSim.Framework.Servers.HttpServer | |||
1081 | } | 1095 | } |
1082 | xmlRprcRequest.Params.Add(request.Headers.Get(xff)); // Param[3] | 1096 | xmlRprcRequest.Params.Add(request.Headers.Get(xff)); // Param[3] |
1083 | 1097 | ||
1098 | if (gridproxy) | ||
1099 | xmlRprcRequest.Params.Add("gridproxy"); // Param[4] | ||
1084 | try | 1100 | try |
1085 | { | 1101 | { |
1086 | xmlRpcResponse = method(xmlRprcRequest, request.RemoteIPEndPoint); | 1102 | xmlRpcResponse = method(xmlRprcRequest, request.RemoteIPEndPoint); |
@@ -1254,7 +1270,8 @@ namespace OpenSim.Framework.Servers.HttpServer | |||
1254 | requestStream.Close(); | 1270 | requestStream.Close(); |
1255 | 1271 | ||
1256 | //m_log.DebugFormat("[OGP]: {0}:{1}", request.RawUrl, requestBody); | 1272 | //m_log.DebugFormat("[OGP]: {0}:{1}", request.RawUrl, requestBody); |
1257 | response.KeepAlive = true; | 1273 | // response.KeepAlive = true; |
1274 | response.KeepAlive = false; | ||
1258 | 1275 | ||
1259 | OSD llsdRequest = null; | 1276 | OSD llsdRequest = null; |
1260 | OSD llsdResponse = null; | 1277 | OSD llsdResponse = null; |
@@ -1732,10 +1749,40 @@ namespace OpenSim.Framework.Servers.HttpServer | |||
1732 | 1749 | ||
1733 | internal byte[] DoHTTPGruntWork(Hashtable responsedata, OSHttpResponse response) | 1750 | internal byte[] DoHTTPGruntWork(Hashtable responsedata, OSHttpResponse response) |
1734 | { | 1751 | { |
1735 | //m_log.Info("[BASE HTTP SERVER]: Doing HTTP Grunt work with response"); | 1752 | int responsecode; |
1736 | int responsecode = (int)responsedata["int_response_code"]; | 1753 | string responseString = String.Empty; |
1737 | string responseString = (string)responsedata["str_response_string"]; | 1754 | byte[] responseData = null; |
1738 | string contentType = (string)responsedata["content_type"]; | 1755 | string contentType; |
1756 | |||
1757 | if (responsedata == null) | ||
1758 | { | ||
1759 | responsecode = 500; | ||
1760 | responseString = "No response could be obtained"; | ||
1761 | contentType = "text/plain"; | ||
1762 | responsedata = new Hashtable(); | ||
1763 | } | ||
1764 | else | ||
1765 | { | ||
1766 | try | ||
1767 | { | ||
1768 | //m_log.Info("[BASE HTTP SERVER]: Doing HTTP Grunt work with response"); | ||
1769 | responsecode = (int)responsedata["int_response_code"]; | ||
1770 | if (responsedata["bin_response_data"] != null) | ||
1771 | responseData = (byte[])responsedata["bin_response_data"]; | ||
1772 | else | ||
1773 | responseString = (string)responsedata["str_response_string"]; | ||
1774 | contentType = (string)responsedata["content_type"]; | ||
1775 | if (responseString == null) | ||
1776 | responseString = String.Empty; | ||
1777 | } | ||
1778 | catch | ||
1779 | { | ||
1780 | responsecode = 500; | ||
1781 | responseString = "No response could be obtained"; | ||
1782 | contentType = "text/plain"; | ||
1783 | responsedata = new Hashtable(); | ||
1784 | } | ||
1785 | } | ||
1739 | 1786 | ||
1740 | if (responsedata.ContainsKey("error_status_text")) | 1787 | if (responsedata.ContainsKey("error_status_text")) |
1741 | { | 1788 | { |
@@ -1745,16 +1792,19 @@ namespace OpenSim.Framework.Servers.HttpServer | |||
1745 | { | 1792 | { |
1746 | response.ProtocolVersion = (string)responsedata["http_protocol_version"]; | 1793 | response.ProtocolVersion = (string)responsedata["http_protocol_version"]; |
1747 | } | 1794 | } |
1748 | 1795 | /* | |
1749 | if (responsedata.ContainsKey("keepalive")) | 1796 | if (responsedata.ContainsKey("keepalive")) |
1750 | { | 1797 | { |
1751 | bool keepalive = (bool)responsedata["keepalive"]; | 1798 | bool keepalive = (bool)responsedata["keepalive"]; |
1752 | response.KeepAlive = keepalive; | 1799 | response.KeepAlive = keepalive; |
1753 | |||
1754 | } | 1800 | } |
1755 | 1801 | ||
1756 | if (responsedata.ContainsKey("reusecontext")) | 1802 | if (responsedata.ContainsKey("reusecontext")) |
1757 | response.ReuseContext = (bool) responsedata["reusecontext"]; | 1803 | response.ReuseContext = (bool) responsedata["reusecontext"]; |
1804 | */ | ||
1805 | // disable this things | ||
1806 | response.KeepAlive = false; | ||
1807 | response.ReuseContext = false; | ||
1758 | 1808 | ||
1759 | // Cross-Origin Resource Sharing with simple requests | 1809 | // Cross-Origin Resource Sharing with simple requests |
1760 | if (responsedata.ContainsKey("access_control_allow_origin")) | 1810 | if (responsedata.ContainsKey("access_control_allow_origin")) |
@@ -1768,8 +1818,11 @@ namespace OpenSim.Framework.Servers.HttpServer | |||
1768 | contentType = "text/html"; | 1818 | contentType = "text/html"; |
1769 | } | 1819 | } |
1770 | 1820 | ||
1821 | |||
1822 | |||
1771 | // The client ignores anything but 200 here for web login, so ensure that this is 200 for that | 1823 | // The client ignores anything but 200 here for web login, so ensure that this is 200 for that |
1772 | 1824 | ||
1825 | |||
1773 | response.StatusCode = responsecode; | 1826 | response.StatusCode = responsecode; |
1774 | 1827 | ||
1775 | if (responsecode == (int)OSHttpStatusCode.RedirectMovedPermanently) | 1828 | if (responsecode == (int)OSHttpStatusCode.RedirectMovedPermanently) |
@@ -1780,25 +1833,40 @@ namespace OpenSim.Framework.Servers.HttpServer | |||
1780 | 1833 | ||
1781 | response.AddHeader("Content-Type", contentType); | 1834 | response.AddHeader("Content-Type", contentType); |
1782 | 1835 | ||
1836 | if (responsedata.ContainsKey("headers")) | ||
1837 | { | ||
1838 | Hashtable headerdata = (Hashtable)responsedata["headers"]; | ||
1839 | |||
1840 | foreach (string header in headerdata.Keys) | ||
1841 | response.AddHeader(header, (string)headerdata[header]); | ||
1842 | } | ||
1843 | |||
1783 | byte[] buffer; | 1844 | byte[] buffer; |
1784 | 1845 | ||
1785 | if (!(contentType.Contains("image") | 1846 | if (responseData != null) |
1786 | || contentType.Contains("x-shockwave-flash") | ||
1787 | || contentType.Contains("application/x-oar") | ||
1788 | || contentType.Contains("application/vnd.ll.mesh"))) | ||
1789 | { | 1847 | { |
1790 | // Text | 1848 | buffer = responseData; |
1791 | buffer = Encoding.UTF8.GetBytes(responseString); | ||
1792 | } | 1849 | } |
1793 | else | 1850 | else |
1794 | { | 1851 | { |
1795 | // Binary! | 1852 | if (!(contentType.Contains("image") |
1796 | buffer = Convert.FromBase64String(responseString); | 1853 | || contentType.Contains("x-shockwave-flash") |
1797 | } | 1854 | || contentType.Contains("application/x-oar") |
1855 | || contentType.Contains("application/vnd.ll.mesh"))) | ||
1856 | { | ||
1857 | // Text | ||
1858 | buffer = Encoding.UTF8.GetBytes(responseString); | ||
1859 | } | ||
1860 | else | ||
1861 | { | ||
1862 | // Binary! | ||
1863 | buffer = Convert.FromBase64String(responseString); | ||
1864 | } | ||
1798 | 1865 | ||
1799 | response.SendChunked = false; | 1866 | response.SendChunked = false; |
1800 | response.ContentLength64 = buffer.Length; | 1867 | response.ContentLength64 = buffer.Length; |
1801 | response.ContentEncoding = Encoding.UTF8; | 1868 | response.ContentEncoding = Encoding.UTF8; |
1869 | } | ||
1802 | 1870 | ||
1803 | return buffer; | 1871 | return buffer; |
1804 | } | 1872 | } |
@@ -1886,6 +1954,7 @@ namespace OpenSim.Framework.Servers.HttpServer | |||
1886 | m_httpListener2.Start(64); | 1954 | m_httpListener2.Start(64); |
1887 | 1955 | ||
1888 | // Long Poll Service Manager with 3 worker threads a 25 second timeout for no events | 1956 | // Long Poll Service Manager with 3 worker threads a 25 second timeout for no events |
1957 | |||
1889 | PollServiceRequestManager = new PollServiceRequestManager(this, performPollResponsesAsync, 3, 25000); | 1958 | PollServiceRequestManager = new PollServiceRequestManager(this, performPollResponsesAsync, 3, 25000); |
1890 | PollServiceRequestManager.Start(); | 1959 | PollServiceRequestManager.Start(); |
1891 | 1960 | ||
@@ -1937,7 +2006,9 @@ namespace OpenSim.Framework.Servers.HttpServer | |||
1937 | 2006 | ||
1938 | public void httpServerException(object source, Exception exception) | 2007 | public void httpServerException(object source, Exception exception) |
1939 | { | 2008 | { |
1940 | m_log.Error(String.Format("[BASE HTTP SERVER]: {0} had an exception: {1} ", source.ToString(), exception.Message), exception); | 2009 | if (source.ToString() == "HttpServer.HttpListener" && exception.ToString().StartsWith("Mono.Security.Protocol.Tls.TlsException")) |
2010 | return; | ||
2011 | m_log.ErrorFormat("[BASE HTTP SERVER]: {0} had an exception {1}", source.ToString(), exception.ToString()); | ||
1941 | /* | 2012 | /* |
1942 | if (HTTPDRunning)// && NotSocketErrors > 5) | 2013 | if (HTTPDRunning)// && NotSocketErrors > 5) |
1943 | { | 2014 | { |
@@ -1984,6 +2055,7 @@ namespace OpenSim.Framework.Servers.HttpServer | |||
1984 | 2055 | ||
1985 | public void RemoveHTTPHandler(string httpMethod, string path) | 2056 | public void RemoveHTTPHandler(string httpMethod, string path) |
1986 | { | 2057 | { |
2058 | if (path == null) return; // Caps module isn't loaded, tries to remove handler where path = null | ||
1987 | lock (m_HTTPHandlers) | 2059 | lock (m_HTTPHandlers) |
1988 | { | 2060 | { |
1989 | if (httpMethod != null && httpMethod.Length == 0) | 2061 | if (httpMethod != null && httpMethod.Length == 0) |
diff --git a/OpenSim/Framework/Servers/HttpServer/OSHttpResponse.cs b/OpenSim/Framework/Servers/HttpServer/OSHttpResponse.cs index 89fb5d4..17e9dc2 100644 --- a/OpenSim/Framework/Servers/HttpServer/OSHttpResponse.cs +++ b/OpenSim/Framework/Servers/HttpServer/OSHttpResponse.cs | |||
@@ -148,6 +148,7 @@ namespace OpenSim.Framework.Servers.HttpServer | |||
148 | _httpResponse.Connection = ConnectionType.Close; | 148 | _httpResponse.Connection = ConnectionType.Close; |
149 | _httpResponse.KeepAlive = 0; | 149 | _httpResponse.KeepAlive = 0; |
150 | } | 150 | } |
151 | |||
151 | else | 152 | else |
152 | { | 153 | { |
153 | _httpResponse.Connection = ConnectionType.KeepAlive; | 154 | _httpResponse.Connection = ConnectionType.KeepAlive; |
@@ -320,6 +321,11 @@ namespace OpenSim.Framework.Servers.HttpServer | |||
320 | public void Send() | 321 | public void Send() |
321 | { | 322 | { |
322 | _httpResponse.Body.Flush(); | 323 | _httpResponse.Body.Flush(); |
324 | |||
325 | // disable this till they are safe to use | ||
326 | _httpResponse.Connection = ConnectionType.Close; | ||
327 | _httpResponse.Chunked = false; | ||
328 | |||
323 | _httpResponse.Send(); | 329 | _httpResponse.Send(); |
324 | } | 330 | } |
325 | 331 | ||
diff --git a/OpenSim/Framework/Servers/HttpServer/PollServiceEventArgs.cs b/OpenSim/Framework/Servers/HttpServer/PollServiceEventArgs.cs index 9477100..3fd3bf7 100644 --- a/OpenSim/Framework/Servers/HttpServer/PollServiceEventArgs.cs +++ b/OpenSim/Framework/Servers/HttpServer/PollServiceEventArgs.cs | |||
@@ -52,7 +52,9 @@ namespace OpenSim.Framework.Servers.HttpServer | |||
52 | { | 52 | { |
53 | LongPoll = 0, | 53 | LongPoll = 0, |
54 | LslHttp = 1, | 54 | LslHttp = 1, |
55 | Inventory = 2 | 55 | Inventory = 2, |
56 | Texture = 3, | ||
57 | Mesh = 4 | ||
56 | } | 58 | } |
57 | 59 | ||
58 | public string Url { get; set; } | 60 | public string Url { get; set; } |
diff --git a/OpenSim/Framework/Servers/HttpServer/PollServiceHttpRequest.cs b/OpenSim/Framework/Servers/HttpServer/PollServiceHttpRequest.cs index caf0e98..49cd110 100644 --- a/OpenSim/Framework/Servers/HttpServer/PollServiceHttpRequest.cs +++ b/OpenSim/Framework/Servers/HttpServer/PollServiceHttpRequest.cs | |||
@@ -27,6 +27,7 @@ | |||
27 | 27 | ||
28 | using System; | 28 | using System; |
29 | using System.Collections; | 29 | using System.Collections; |
30 | using System.Collections.Generic; | ||
30 | using System.Reflection; | 31 | using System.Reflection; |
31 | using System.Text; | 32 | using System.Text; |
32 | using HttpServer; | 33 | using HttpServer; |
@@ -44,6 +45,24 @@ namespace OpenSim.Framework.Servers.HttpServer | |||
44 | public readonly IHttpRequest Request; | 45 | public readonly IHttpRequest Request; |
45 | public readonly int RequestTime; | 46 | public readonly int RequestTime; |
46 | public readonly UUID RequestID; | 47 | public readonly UUID RequestID; |
48 | public int contextHash; | ||
49 | |||
50 | private void GenContextHash() | ||
51 | { | ||
52 | Random rnd = new Random(); | ||
53 | contextHash = 0; | ||
54 | if (Request.Headers["remote_addr"] != null) | ||
55 | contextHash = (Request.Headers["remote_addr"]).GetHashCode() << 16; | ||
56 | else | ||
57 | contextHash = rnd.Next() << 16; | ||
58 | if (Request.Headers["remote_port"] != null) | ||
59 | { | ||
60 | string[] strPorts = Request.Headers["remote_port"].Split(new char[] { ',' }); | ||
61 | contextHash += Int32.Parse(strPorts[0]); | ||
62 | } | ||
63 | else | ||
64 | contextHash += rnd.Next() & 0xffff; | ||
65 | } | ||
47 | 66 | ||
48 | public PollServiceHttpRequest( | 67 | public PollServiceHttpRequest( |
49 | PollServiceEventArgs pPollServiceArgs, IHttpClientContext pHttpContext, IHttpRequest pRequest) | 68 | PollServiceEventArgs pPollServiceArgs, IHttpClientContext pHttpContext, IHttpRequest pRequest) |
@@ -53,6 +72,7 @@ namespace OpenSim.Framework.Servers.HttpServer | |||
53 | Request = pRequest; | 72 | Request = pRequest; |
54 | RequestTime = System.Environment.TickCount; | 73 | RequestTime = System.Environment.TickCount; |
55 | RequestID = UUID.Random(); | 74 | RequestID = UUID.Random(); |
75 | GenContextHash(); | ||
56 | } | 76 | } |
57 | 77 | ||
58 | internal void DoHTTPGruntWork(BaseHttpServer server, Hashtable responsedata) | 78 | internal void DoHTTPGruntWork(BaseHttpServer server, Hashtable responsedata) |
@@ -65,6 +85,7 @@ namespace OpenSim.Framework.Servers.HttpServer | |||
65 | response.SendChunked = false; | 85 | response.SendChunked = false; |
66 | response.ContentLength64 = buffer.Length; | 86 | response.ContentLength64 = buffer.Length; |
67 | response.ContentEncoding = Encoding.UTF8; | 87 | response.ContentEncoding = Encoding.UTF8; |
88 | response.ReuseContext = false; | ||
68 | 89 | ||
69 | try | 90 | try |
70 | { | 91 | { |
@@ -93,5 +114,44 @@ namespace OpenSim.Framework.Servers.HttpServer | |||
93 | PollServiceArgs.RequestsHandled++; | 114 | PollServiceArgs.RequestsHandled++; |
94 | } | 115 | } |
95 | } | 116 | } |
117 | |||
118 | internal void DoHTTPstop(BaseHttpServer server) | ||
119 | { | ||
120 | OSHttpResponse response | ||
121 | = new OSHttpResponse(new HttpResponse(HttpContext, Request), HttpContext); | ||
122 | |||
123 | response.SendChunked = false; | ||
124 | response.ContentLength64 = 0; | ||
125 | response.ContentEncoding = Encoding.UTF8; | ||
126 | response.ReuseContext = false; | ||
127 | response.KeepAlive = false; | ||
128 | response.SendChunked = false; | ||
129 | response.StatusCode = 503; | ||
130 | |||
131 | try | ||
132 | { | ||
133 | response.OutputStream.Flush(); | ||
134 | response.Send(); | ||
135 | } | ||
136 | catch (Exception e) | ||
137 | { | ||
138 | } | ||
139 | } | ||
140 | } | ||
141 | |||
142 | class PollServiceHttpRequestComparer : IEqualityComparer<PollServiceHttpRequest> | ||
143 | { | ||
144 | public bool Equals(PollServiceHttpRequest b1, PollServiceHttpRequest b2) | ||
145 | { | ||
146 | if (b1.contextHash != b2.contextHash) | ||
147 | return false; | ||
148 | bool b = Object.ReferenceEquals(b1.HttpContext, b2.HttpContext); | ||
149 | return b; | ||
150 | } | ||
151 | |||
152 | public int GetHashCode(PollServiceHttpRequest b2) | ||
153 | { | ||
154 | return (int)b2.contextHash; | ||
155 | } | ||
96 | } | 156 | } |
97 | } \ No newline at end of file | 157 | } \ No newline at end of file |
diff --git a/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs b/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs index 28bba70..0e4323a 100644 --- a/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs +++ b/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs | |||
@@ -44,183 +44,199 @@ namespace OpenSim.Framework.Servers.HttpServer | |||
44 | { | 44 | { |
45 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 45 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
46 | 46 | ||
47 | /// <summary> | ||
48 | /// Is the poll service request manager running? | ||
49 | /// </summary> | ||
50 | /// <remarks> | ||
51 | /// Can be running either synchronously or asynchronously | ||
52 | /// </remarks> | ||
53 | public bool IsRunning { get; private set; } | ||
54 | |||
55 | /// <summary> | ||
56 | /// Is the poll service performing responses asynchronously (with its own threads) or synchronously (via | ||
57 | /// external calls)? | ||
58 | /// </summary> | ||
59 | public bool PerformResponsesAsync { get; private set; } | ||
60 | |||
61 | /// <summary> | ||
62 | /// Number of responses actually processed and sent to viewer (or aborted due to error). | ||
63 | /// </summary> | ||
64 | public int ResponsesProcessed { get; private set; } | ||
65 | |||
66 | private readonly BaseHttpServer m_server; | 47 | private readonly BaseHttpServer m_server; |
67 | 48 | ||
49 | private Dictionary<PollServiceHttpRequest, Queue<PollServiceHttpRequest>> m_bycontext; | ||
68 | private BlockingQueue<PollServiceHttpRequest> m_requests = new BlockingQueue<PollServiceHttpRequest>(); | 50 | private BlockingQueue<PollServiceHttpRequest> m_requests = new BlockingQueue<PollServiceHttpRequest>(); |
69 | private static List<PollServiceHttpRequest> m_longPollRequests = new List<PollServiceHttpRequest>(); | 51 | private static Queue<PollServiceHttpRequest> m_slowRequests = new Queue<PollServiceHttpRequest>(); |
52 | private static Queue<PollServiceHttpRequest> m_retryRequests = new Queue<PollServiceHttpRequest>(); | ||
70 | 53 | ||
71 | private uint m_WorkerThreadCount = 0; | 54 | private uint m_WorkerThreadCount = 0; |
72 | private Thread[] m_workerThreads; | 55 | private Thread[] m_workerThreads; |
56 | private Thread m_retrysThread; | ||
57 | |||
58 | private bool m_running = false; | ||
59 | private int slowCount = 0; | ||
73 | 60 | ||
74 | private SmartThreadPool m_threadPool = new SmartThreadPool(20000, 12, 2); | 61 | private SmartThreadPool m_threadPool; |
75 | 62 | ||
76 | // private int m_timeout = 1000; // increase timeout 250; now use the event one | ||
77 | 63 | ||
78 | public PollServiceRequestManager( | 64 | public PollServiceRequestManager( |
79 | BaseHttpServer pSrv, bool performResponsesAsync, uint pWorkerThreadCount, int pTimeout) | 65 | BaseHttpServer pSrv, bool performResponsesAsync, uint pWorkerThreadCount, int pTimeout) |
80 | { | 66 | { |
81 | m_server = pSrv; | 67 | m_server = pSrv; |
82 | PerformResponsesAsync = performResponsesAsync; | ||
83 | m_WorkerThreadCount = pWorkerThreadCount; | 68 | m_WorkerThreadCount = pWorkerThreadCount; |
84 | m_workerThreads = new Thread[m_WorkerThreadCount]; | 69 | m_workerThreads = new Thread[m_WorkerThreadCount]; |
85 | 70 | ||
86 | StatsManager.RegisterStat( | 71 | PollServiceHttpRequestComparer preqCp = new PollServiceHttpRequestComparer(); |
87 | new Stat( | 72 | m_bycontext = new Dictionary<PollServiceHttpRequest, Queue<PollServiceHttpRequest>>(preqCp); |
88 | "QueuedPollResponses", | 73 | |
89 | "Number of poll responses queued for processing.", | 74 | STPStartInfo startInfo = new STPStartInfo(); |
90 | "", | 75 | startInfo.IdleTimeout = 30000; |
91 | "", | 76 | startInfo.MaxWorkerThreads = 15; |
92 | "httpserver", | 77 | startInfo.MinWorkerThreads = 1; |
93 | m_server.Port.ToString(), | 78 | startInfo.ThreadPriority = ThreadPriority.Normal; |
94 | StatType.Pull, | 79 | startInfo.StartSuspended = true; |
95 | MeasuresOfInterest.AverageChangeOverTime, | 80 | startInfo.ThreadPoolName = "PoolService"; |
96 | stat => stat.Value = m_requests.Count(), | 81 | |
97 | StatVerbosity.Debug)); | 82 | m_threadPool = new SmartThreadPool(startInfo); |
98 | 83 | ||
99 | StatsManager.RegisterStat( | ||
100 | new Stat( | ||
101 | "ProcessedPollResponses", | ||
102 | "Number of poll responses processed.", | ||
103 | "", | ||
104 | "", | ||
105 | "httpserver", | ||
106 | m_server.Port.ToString(), | ||
107 | StatType.Pull, | ||
108 | MeasuresOfInterest.AverageChangeOverTime, | ||
109 | stat => stat.Value = ResponsesProcessed, | ||
110 | StatVerbosity.Debug)); | ||
111 | } | 84 | } |
112 | 85 | ||
113 | public void Start() | 86 | public void Start() |
114 | { | 87 | { |
115 | IsRunning = true; | 88 | m_running = true; |
116 | 89 | m_threadPool.Start(); | |
117 | if (PerformResponsesAsync) | 90 | //startup worker threads |
91 | for (uint i = 0; i < m_WorkerThreadCount; i++) | ||
118 | { | 92 | { |
119 | //startup worker threads | 93 | m_workerThreads[i] |
120 | for (uint i = 0; i < m_WorkerThreadCount; i++) | 94 | = WorkManager.StartThread( |
121 | { | 95 | PoolWorkerJob, |
122 | m_workerThreads[i] | 96 | string.Format("PollServiceWorkerThread {0}:{1}", i, m_server.Port), |
123 | = WorkManager.StartThread( | 97 | ThreadPriority.Normal, |
124 | PoolWorkerJob, | 98 | false, |
125 | string.Format("PollServiceWorkerThread{0}:{1}", i, m_server.Port), | 99 | false, |
126 | ThreadPriority.Normal, | 100 | null, |
127 | false, | 101 | int.MaxValue); |
128 | false, | ||
129 | null, | ||
130 | int.MaxValue); | ||
131 | } | ||
132 | |||
133 | WorkManager.StartThread( | ||
134 | this.CheckLongPollThreads, | ||
135 | string.Format("LongPollServiceWatcherThread:{0}", m_server.Port), | ||
136 | ThreadPriority.Normal, | ||
137 | false, | ||
138 | true, | ||
139 | null, | ||
140 | 1000 * 60 * 10); | ||
141 | } | 102 | } |
103 | |||
104 | m_retrysThread = WorkManager.StartThread( | ||
105 | this.CheckRetries, | ||
106 | string.Format("PollServiceWatcherThread:{0}", m_server.Port), | ||
107 | ThreadPriority.Normal, | ||
108 | false, | ||
109 | true, | ||
110 | null, | ||
111 | 1000 * 60 * 10); | ||
112 | |||
113 | |||
142 | } | 114 | } |
143 | 115 | ||
144 | private void ReQueueEvent(PollServiceHttpRequest req) | 116 | private void ReQueueEvent(PollServiceHttpRequest req) |
145 | { | 117 | { |
146 | if (IsRunning) | 118 | if (m_running) |
147 | { | 119 | { |
148 | // delay the enqueueing for 100ms. There's no need to have the event | 120 | lock (m_retryRequests) |
149 | // actively on the queue | 121 | m_retryRequests.Enqueue(req); |
150 | Timer t = new Timer(self => { | ||
151 | ((Timer)self).Dispose(); | ||
152 | m_requests.Enqueue(req); | ||
153 | }); | ||
154 | |||
155 | t.Change(100, Timeout.Infinite); | ||
156 | |||
157 | } | 122 | } |
158 | } | 123 | } |
159 | 124 | ||
160 | public void Enqueue(PollServiceHttpRequest req) | 125 | public void Enqueue(PollServiceHttpRequest req) |
161 | { | 126 | { |
162 | if (IsRunning) | 127 | lock (m_bycontext) |
163 | { | 128 | { |
164 | if (req.PollServiceArgs.Type == PollServiceEventArgs.EventType.LongPoll) | 129 | Queue<PollServiceHttpRequest> ctxQeueue; |
130 | if (m_bycontext.TryGetValue(req, out ctxQeueue)) | ||
165 | { | 131 | { |
166 | lock (m_longPollRequests) | 132 | ctxQeueue.Enqueue(req); |
167 | m_longPollRequests.Add(req); | ||
168 | } | 133 | } |
169 | else | 134 | else |
170 | m_requests.Enqueue(req); | 135 | { |
136 | ctxQeueue = new Queue<PollServiceHttpRequest>(); | ||
137 | m_bycontext[req] = ctxQeueue; | ||
138 | EnqueueInt(req); | ||
139 | } | ||
171 | } | 140 | } |
172 | } | 141 | } |
173 | 142 | ||
174 | private void CheckLongPollThreads() | 143 | public void byContextDequeue(PollServiceHttpRequest req) |
175 | { | 144 | { |
176 | // The only purpose of this thread is to check the EQs for events. | 145 | Queue<PollServiceHttpRequest> ctxQeueue; |
177 | // If there are events, that thread will be placed in the "ready-to-serve" queue, m_requests. | 146 | lock (m_bycontext) |
178 | // If there are no events, that thread will be back to its "waiting" queue, m_longPollRequests. | ||
179 | // All other types of tasks (Inventory handlers, http-in, etc) don't have the long-poll nature, | ||
180 | // so if they aren't ready to be served by a worker thread (no events), they are placed | ||
181 | // directly back in the "ready-to-serve" queue by the worker thread. | ||
182 | while (IsRunning) | ||
183 | { | 147 | { |
184 | Thread.Sleep(500); | 148 | if (m_bycontext.TryGetValue(req, out ctxQeueue)) |
185 | Watchdog.UpdateThread(); | ||
186 | |||
187 | // List<PollServiceHttpRequest> not_ready = new List<PollServiceHttpRequest>(); | ||
188 | lock (m_longPollRequests) | ||
189 | { | 149 | { |
190 | if (m_longPollRequests.Count > 0 && IsRunning) | 150 | if (ctxQeueue.Count > 0) |
191 | { | 151 | { |
192 | List<PollServiceHttpRequest> ready = m_longPollRequests.FindAll(req => | 152 | PollServiceHttpRequest newreq = ctxQeueue.Dequeue(); |
193 | (req.PollServiceArgs.HasEvents(req.RequestID, req.PollServiceArgs.Id) || // there are events in this EQ | 153 | EnqueueInt(newreq); |
194 | (Environment.TickCount - req.RequestTime) > req.PollServiceArgs.TimeOutms) // no events, but timeout | 154 | } |
195 | ); | 155 | else |
156 | { | ||
157 | m_bycontext.Remove(req); | ||
158 | } | ||
159 | } | ||
160 | } | ||
161 | } | ||
196 | 162 | ||
197 | ready.ForEach(req => | ||
198 | { | ||
199 | m_requests.Enqueue(req); | ||
200 | m_longPollRequests.Remove(req); | ||
201 | }); | ||
202 | 163 | ||
203 | } | 164 | public void EnqueueInt(PollServiceHttpRequest req) |
165 | { | ||
166 | if (m_running) | ||
167 | { | ||
168 | if (req.PollServiceArgs.Type != PollServiceEventArgs.EventType.LongPoll) | ||
169 | { | ||
170 | m_requests.Enqueue(req); | ||
171 | } | ||
172 | else | ||
173 | { | ||
174 | lock (m_slowRequests) | ||
175 | m_slowRequests.Enqueue(req); | ||
176 | } | ||
177 | } | ||
178 | } | ||
179 | |||
180 | private void CheckRetries() | ||
181 | { | ||
182 | while (m_running) | ||
183 | |||
184 | { | ||
185 | Thread.Sleep(100); // let the world move .. back to faster rate | ||
186 | Watchdog.UpdateThread(); | ||
187 | lock (m_retryRequests) | ||
188 | { | ||
189 | while (m_retryRequests.Count > 0 && m_running) | ||
190 | m_requests.Enqueue(m_retryRequests.Dequeue()); | ||
191 | } | ||
192 | slowCount++; | ||
193 | if (slowCount >= 10) | ||
194 | { | ||
195 | slowCount = 0; | ||
204 | 196 | ||
197 | lock (m_slowRequests) | ||
198 | { | ||
199 | while (m_slowRequests.Count > 0 && m_running) | ||
200 | m_requests.Enqueue(m_slowRequests.Dequeue()); | ||
201 | } | ||
205 | } | 202 | } |
206 | } | 203 | } |
207 | } | 204 | } |
208 | 205 | ||
209 | public void Stop() | 206 | public void Stop() |
210 | { | 207 | { |
211 | IsRunning = false; | 208 | m_running = false; |
212 | // m_timeout = -10000; // cause all to expire | 209 | |
213 | Thread.Sleep(1000); // let the world move | 210 | Thread.Sleep(1000); // let the world move |
214 | 211 | ||
215 | foreach (Thread t in m_workerThreads) | 212 | foreach (Thread t in m_workerThreads) |
216 | Watchdog.AbortThread(t.ManagedThreadId); | 213 | Watchdog.AbortThread(t.ManagedThreadId); |
217 | 214 | ||
215 | // any entry in m_bycontext should have a active request on the other queues | ||
216 | // so just delete contents to easy GC | ||
217 | foreach (Queue<PollServiceHttpRequest> qu in m_bycontext.Values) | ||
218 | qu.Clear(); | ||
219 | m_bycontext.Clear(); | ||
220 | |||
221 | try | ||
222 | { | ||
223 | foreach (PollServiceHttpRequest req in m_retryRequests) | ||
224 | { | ||
225 | req.DoHTTPstop(m_server); | ||
226 | } | ||
227 | } | ||
228 | catch | ||
229 | { | ||
230 | } | ||
231 | |||
218 | PollServiceHttpRequest wreq; | 232 | PollServiceHttpRequest wreq; |
233 | m_retryRequests.Clear(); | ||
219 | 234 | ||
220 | lock (m_longPollRequests) | 235 | lock (m_slowRequests) |
221 | { | 236 | { |
222 | if (m_longPollRequests.Count > 0 && IsRunning) | 237 | while (m_slowRequests.Count > 0) |
223 | m_longPollRequests.ForEach(req => m_requests.Enqueue(req)); | 238 | m_requests.Enqueue(m_slowRequests.Dequeue()); |
239 | |||
224 | } | 240 | } |
225 | 241 | ||
226 | while (m_requests.Count() > 0) | 242 | while (m_requests.Count() > 0) |
@@ -228,16 +244,14 @@ namespace OpenSim.Framework.Servers.HttpServer | |||
228 | try | 244 | try |
229 | { | 245 | { |
230 | wreq = m_requests.Dequeue(0); | 246 | wreq = m_requests.Dequeue(0); |
231 | ResponsesProcessed++; | 247 | wreq.DoHTTPstop(m_server); |
232 | wreq.DoHTTPGruntWork( | 248 | |
233 | m_server, wreq.PollServiceArgs.NoEvents(wreq.RequestID, wreq.PollServiceArgs.Id)); | ||
234 | } | 249 | } |
235 | catch | 250 | catch |
236 | { | 251 | { |
237 | } | 252 | } |
238 | } | 253 | } |
239 | 254 | ||
240 | m_longPollRequests.Clear(); | ||
241 | m_requests.Clear(); | 255 | m_requests.Clear(); |
242 | } | 256 | } |
243 | 257 | ||
@@ -245,87 +259,70 @@ namespace OpenSim.Framework.Servers.HttpServer | |||
245 | 259 | ||
246 | private void PoolWorkerJob() | 260 | private void PoolWorkerJob() |
247 | { | 261 | { |
248 | while (IsRunning) | 262 | while (m_running) |
249 | { | 263 | { |
250 | Watchdog.UpdateThread(); | 264 | PollServiceHttpRequest req = m_requests.Dequeue(5000); |
251 | WaitPerformResponse(); | ||
252 | } | ||
253 | } | ||
254 | |||
255 | public void WaitPerformResponse() | ||
256 | { | ||
257 | PollServiceHttpRequest req = m_requests.Dequeue(5000); | ||
258 | // m_log.DebugFormat("[YYY]: Dequeued {0}", (req == null ? "null" : req.PollServiceArgs.Type.ToString())); | ||
259 | 265 | ||
260 | if (req != null) | 266 | Watchdog.UpdateThread(); |
261 | { | 267 | if (req != null) |
262 | try | ||
263 | { | 268 | { |
264 | if (req.PollServiceArgs.HasEvents(req.RequestID, req.PollServiceArgs.Id)) | 269 | try |
265 | { | 270 | { |
266 | Hashtable responsedata = req.PollServiceArgs.GetEvents(req.RequestID, req.PollServiceArgs.Id); | 271 | if (req.PollServiceArgs.HasEvents(req.RequestID, req.PollServiceArgs.Id)) |
267 | |||
268 | if (responsedata == null) | ||
269 | return; | ||
270 | |||
271 | // This is the event queue. | ||
272 | // Even if we're not running we can still perform responses by explicit request. | ||
273 | if (req.PollServiceArgs.Type == PollServiceEventArgs.EventType.LongPoll | ||
274 | || !PerformResponsesAsync) | ||
275 | { | 272 | { |
276 | try | 273 | Hashtable responsedata = req.PollServiceArgs.GetEvents(req.RequestID, req.PollServiceArgs.Id); |
277 | { | 274 | |
278 | ResponsesProcessed++; | 275 | if (req.PollServiceArgs.Type == PollServiceEventArgs.EventType.LongPoll) // This is the event queue |
279 | req.DoHTTPGruntWork(m_server, responsedata); | ||
280 | } | ||
281 | catch (ObjectDisposedException e) // Browser aborted before we could read body, server closed the stream | ||
282 | { | ||
283 | // Ignore it, no need to reply | ||
284 | m_log.Error(e); | ||
285 | } | ||
286 | } | ||
287 | else | ||
288 | { | ||
289 | m_threadPool.QueueWorkItem(x => | ||
290 | { | 276 | { |
291 | try | 277 | try |
292 | { | 278 | { |
293 | ResponsesProcessed++; | ||
294 | req.DoHTTPGruntWork(m_server, responsedata); | 279 | req.DoHTTPGruntWork(m_server, responsedata); |
280 | byContextDequeue(req); | ||
295 | } | 281 | } |
296 | catch (ObjectDisposedException e) // Browser aborted before we could read body, server closed the stream | 282 | catch (ObjectDisposedException) // Browser aborted before we could read body, server closed the stream |
297 | { | 283 | { |
298 | // Ignore it, no need to reply | 284 | // Ignore it, no need to reply |
299 | m_log.Error(e); | ||
300 | } | 285 | } |
301 | catch (Exception e) | 286 | } |
287 | else | ||
288 | { | ||
289 | m_threadPool.QueueWorkItem(x => | ||
302 | { | 290 | { |
303 | m_log.Error(e); | 291 | try |
304 | } | 292 | { |
305 | 293 | req.DoHTTPGruntWork(m_server, responsedata); | |
306 | return null; | 294 | byContextDequeue(req); |
307 | }, null); | 295 | } |
308 | } | 296 | catch (ObjectDisposedException) // Browser aborted before we could read body, server closed the stream |
309 | } | 297 | { |
310 | else | 298 | // Ignore it, no need to reply |
311 | { | 299 | } |
312 | if ((Environment.TickCount - req.RequestTime) > req.PollServiceArgs.TimeOutms) | 300 | |
313 | { | 301 | return null; |
314 | ResponsesProcessed++; | 302 | }, null); |
315 | req.DoHTTPGruntWork( | 303 | } |
316 | m_server, req.PollServiceArgs.NoEvents(req.RequestID, req.PollServiceArgs.Id)); | ||
317 | } | 304 | } |
318 | else | 305 | else |
319 | { | 306 | { |
320 | ReQueueEvent(req); | 307 | if ((Environment.TickCount - req.RequestTime) > req.PollServiceArgs.TimeOutms) |
308 | { | ||
309 | req.DoHTTPGruntWork(m_server, | ||
310 | req.PollServiceArgs.NoEvents(req.RequestID, req.PollServiceArgs.Id)); | ||
311 | byContextDequeue(req); | ||
312 | } | ||
313 | else | ||
314 | { | ||
315 | ReQueueEvent(req); | ||
316 | } | ||
321 | } | 317 | } |
322 | } | 318 | } |
323 | } | 319 | catch (Exception e) |
324 | catch (Exception e) | 320 | { |
325 | { | 321 | m_log.ErrorFormat("Exception in poll service thread: " + e.ToString()); |
326 | m_log.ErrorFormat("Exception in poll service thread: " + e.ToString()); | 322 | } |
327 | } | 323 | } |
328 | } | 324 | } |
329 | } | 325 | } |
326 | |||
330 | } | 327 | } |
331 | } \ No newline at end of file | 328 | } |
diff --git a/OpenSim/Framework/Servers/ServerBase.cs b/OpenSim/Framework/Servers/ServerBase.cs index 07a09e6..b330384 100644 --- a/OpenSim/Framework/Servers/ServerBase.cs +++ b/OpenSim/Framework/Servers/ServerBase.cs | |||
@@ -871,7 +871,7 @@ namespace OpenSim.Framework.Servers | |||
871 | } | 871 | } |
872 | } | 872 | } |
873 | 873 | ||
874 | protected string GetVersionText() | 874 | public string GetVersionText() |
875 | { | 875 | { |
876 | return String.Format("Version: {0} (SIMULATION/{1} - SIMULATION/{2})", | 876 | return String.Format("Version: {0} (SIMULATION/{1} - SIMULATION/{2})", |
877 | m_version, VersionInfo.SimulationServiceVersionSupportedMin, VersionInfo.SimulationServiceVersionSupportedMax); | 877 | m_version, VersionInfo.SimulationServiceVersionSupportedMin, VersionInfo.SimulationServiceVersionSupportedMax); |
diff --git a/OpenSim/Framework/Servers/Tests/OSHttpTests.cs b/OpenSim/Framework/Servers/Tests/OSHttpTests.cs index 5c0e0df..1b47cc6 100644 --- a/OpenSim/Framework/Servers/Tests/OSHttpTests.cs +++ b/OpenSim/Framework/Servers/Tests/OSHttpTests.cs | |||
@@ -41,7 +41,327 @@ namespace OpenSim.Framework.Servers.Tests | |||
41 | { | 41 | { |
42 | [TestFixture] | 42 | [TestFixture] |
43 | public class OSHttpTests : OpenSimTestCase | 43 | public class OSHttpTests : OpenSimTestCase |
44 | { | 44 | { |
45 | // we need an IHttpClientContext for our tests | ||
46 | public class TestHttpClientContext: IHttpClientContext | ||
47 | { | ||
48 | private bool _secured; | ||
49 | public bool IsSecured | ||
50 | { | ||
51 | get { return _secured; } | ||
52 | } | ||
53 | public bool Secured | ||
54 | { | ||
55 | get { return _secured; } | ||
56 | } | ||
57 | |||
58 | public TestHttpClientContext(bool secured) | ||
59 | { | ||
60 | _secured = secured; | ||
61 | } | ||
62 | |||
63 | public void Disconnect(SocketError error) {} | ||
64 | public void Respond(string httpVersion, HttpStatusCode statusCode, string reason, string body) {} | ||
65 | public void Respond(string httpVersion, HttpStatusCode statusCode, string reason) {} | ||
66 | public void Respond(string body) {} | ||
67 | public void Send(byte[] buffer) {} | ||
68 | public void Send(byte[] buffer, int offset, int size) {} | ||
69 | public void Respond(string httpVersion, HttpStatusCode statusCode, string reason, string body, string contentType) {} | ||
70 | public void Close() { } | ||
71 | public bool EndWhenDone { get { return false;} set { return;}} | ||
72 | |||
73 | public HTTPNetworkContext GiveMeTheNetworkStreamIKnowWhatImDoing() | ||
74 | { | ||
75 | return new HTTPNetworkContext(); | ||
76 | } | ||
77 | |||
78 | public event EventHandler<DisconnectedEventArgs> Disconnected = delegate { }; | ||
79 | /// <summary> | ||
80 | /// A request have been received in the context. | ||
81 | /// </summary> | ||
82 | public event EventHandler<RequestEventArgs> RequestReceived = delegate { }; | ||
83 | |||
84 | public bool CanSend { get { return true; } } | ||
85 | public string RemoteEndPoint { get { return ""; } } | ||
86 | public string RemoteEndPointAddress { get { return ""; } } | ||
87 | public string RemoteEndPointPort { get { return ""; } } | ||
88 | } | ||
89 | |||
90 | public class TestHttpRequest: IHttpRequest | ||
91 | { | ||
92 | private string _uriPath; | ||
93 | public bool BodyIsComplete | ||
94 | { | ||
95 | get { return true; } | ||
96 | } | ||
97 | public string[] AcceptTypes | ||
98 | { | ||
99 | get {return _acceptTypes; } | ||
100 | } | ||
101 | private string[] _acceptTypes; | ||
102 | public Stream Body | ||
103 | { | ||
104 | get { return _body; } | ||
105 | set { _body = value;} | ||
106 | } | ||
107 | private Stream _body; | ||
108 | public ConnectionType Connection | ||
109 | { | ||
110 | get { return _connection; } | ||
111 | set { _connection = value; } | ||
112 | } | ||
113 | private ConnectionType _connection; | ||
114 | public int ContentLength | ||
115 | { | ||
116 | get { return _contentLength; } | ||
117 | set { _contentLength = value; } | ||
118 | } | ||
119 | private int _contentLength; | ||
120 | public NameValueCollection Headers | ||
121 | { | ||
122 | get { return _headers; } | ||
123 | } | ||
124 | private NameValueCollection _headers = new NameValueCollection(); | ||
125 | public string HttpVersion | ||
126 | { | ||
127 | get { return _httpVersion; } | ||
128 | set { _httpVersion = value; } | ||
129 | } | ||
130 | private string _httpVersion = null; | ||
131 | public string Method | ||
132 | { | ||
133 | get { return _method; } | ||
134 | set { _method = value; } | ||
135 | } | ||
136 | private string _method = null; | ||
137 | public HttpInput QueryString | ||
138 | { | ||
139 | get { return _queryString; } | ||
140 | } | ||
141 | private HttpInput _queryString = null; | ||
142 | public Uri Uri | ||
143 | { | ||
144 | get { return _uri; } | ||
145 | set { _uri = value; } | ||
146 | } | ||
147 | private Uri _uri = null; | ||
148 | public string[] UriParts | ||
149 | { | ||
150 | get { return _uri.Segments; } | ||
151 | } | ||
152 | public HttpParam Param | ||
153 | { | ||
154 | get { return null; } | ||
155 | } | ||
156 | public HttpForm Form | ||
157 | { | ||
158 | get { return null; } | ||
159 | } | ||
160 | public bool IsAjax | ||
161 | { | ||
162 | get { return false; } | ||
163 | } | ||
164 | public RequestCookies Cookies | ||
165 | { | ||
166 | get { return null; } | ||
167 | } | ||
168 | |||
169 | public TestHttpRequest() {} | ||
170 | |||
171 | public TestHttpRequest(string contentEncoding, string contentType, string userAgent, | ||
172 | string remoteAddr, string remotePort, string[] acceptTypes, | ||
173 | ConnectionType connectionType, int contentLength, Uri uri) | ||
174 | { | ||
175 | _headers["content-encoding"] = contentEncoding; | ||
176 | _headers["content-type"] = contentType; | ||
177 | _headers["user-agent"] = userAgent; | ||
178 | _headers["remote_addr"] = remoteAddr; | ||
179 | _headers["remote_port"] = remotePort; | ||
180 | |||
181 | _acceptTypes = acceptTypes; | ||
182 | _connection = connectionType; | ||
183 | _contentLength = contentLength; | ||
184 | _uri = uri; | ||
185 | } | ||
186 | |||
187 | public void DecodeBody(FormDecoderProvider providers) {} | ||
188 | public void SetCookies(RequestCookies cookies) {} | ||
189 | public void AddHeader(string name, string value) | ||
190 | { | ||
191 | _headers.Add(name, value); | ||
192 | } | ||
193 | public int AddToBody(byte[] bytes, int offset, int length) | ||
194 | { | ||
195 | return 0; | ||
196 | } | ||
197 | public void Clear() {} | ||
198 | |||
199 | public object Clone() | ||
200 | { | ||
201 | TestHttpRequest clone = new TestHttpRequest(); | ||
202 | clone._acceptTypes = _acceptTypes; | ||
203 | clone._connection = _connection; | ||
204 | clone._contentLength = _contentLength; | ||
205 | clone._uri = _uri; | ||
206 | clone._headers = new NameValueCollection(_headers); | ||
207 | |||
208 | return clone; | ||
209 | } | ||
210 | public IHttpResponse CreateResponse(IHttpClientContext context) | ||
211 | { | ||
212 | return new HttpResponse(context, this); | ||
213 | } | ||
214 | /// <summary> | ||
215 | /// Path and query (will be merged with the host header) and put in Uri | ||
216 | /// </summary> | ||
217 | /// <see cref="Uri"/> | ||
218 | public string UriPath | ||
219 | { | ||
220 | get { return _uriPath; } | ||
221 | set | ||
222 | { | ||
223 | _uriPath = value; | ||
224 | |||
225 | } | ||
226 | } | ||
227 | |||
228 | } | ||
229 | |||
230 | public class TestHttpResponse: IHttpResponse | ||
231 | { | ||
232 | public Stream Body | ||
233 | { | ||
234 | get { return _body; } | ||
235 | |||
236 | set { _body = value; } | ||
237 | } | ||
238 | private Stream _body; | ||
239 | |||
240 | public string ProtocolVersion | ||
241 | { | ||
242 | get { return _protocolVersion; } | ||
243 | set { _protocolVersion = value; } | ||
244 | } | ||
245 | private string _protocolVersion; | ||
246 | |||
247 | public bool Chunked | ||
248 | { | ||
249 | get { return _chunked; } | ||
250 | |||
251 | set { _chunked = value; } | ||
252 | } | ||
253 | private bool _chunked; | ||
254 | |||
255 | public ConnectionType Connection | ||
256 | { | ||
257 | get { return _connection; } | ||
258 | |||
259 | set { _connection = value; } | ||
260 | } | ||
261 | private ConnectionType _connection; | ||
262 | |||
263 | public Encoding Encoding | ||
264 | { | ||
265 | get { return _encoding; } | ||
266 | |||
267 | set { _encoding = value; } | ||
268 | } | ||
269 | private Encoding _encoding; | ||
270 | |||
271 | public int KeepAlive | ||
272 | { | ||
273 | get { return _keepAlive; } | ||
274 | |||
275 | set { _keepAlive = value; } | ||
276 | } | ||
277 | private int _keepAlive; | ||
278 | |||
279 | public HttpStatusCode Status | ||
280 | { | ||
281 | get { return _status; } | ||
282 | |||
283 | set { _status = value; } | ||
284 | } | ||
285 | private HttpStatusCode _status; | ||
286 | |||
287 | public string Reason | ||
288 | { | ||
289 | get { return _reason; } | ||
290 | |||
291 | set { _reason = value; } | ||
292 | } | ||
293 | private string _reason; | ||
294 | |||
295 | public long ContentLength | ||
296 | { | ||
297 | get { return _contentLength; } | ||
298 | |||
299 | set { _contentLength = value; } | ||
300 | } | ||
301 | private long _contentLength; | ||
302 | |||
303 | public string ContentType | ||
304 | { | ||
305 | get { return _contentType; } | ||
306 | |||
307 | set { _contentType = value; } | ||
308 | } | ||
309 | private string _contentType; | ||
310 | |||
311 | public bool HeadersSent | ||
312 | { | ||
313 | get { return _headersSent; } | ||
314 | } | ||
315 | private bool _headersSent; | ||
316 | |||
317 | public bool Sent | ||
318 | { | ||
319 | get { return _sent; } | ||
320 | } | ||
321 | private bool _sent; | ||
322 | |||
323 | public ResponseCookies Cookies | ||
324 | { | ||
325 | get { return _cookies; } | ||
326 | } | ||
327 | private ResponseCookies _cookies = null; | ||
328 | |||
329 | public TestHttpResponse() | ||
330 | { | ||
331 | _headersSent = false; | ||
332 | _sent = false; | ||
333 | } | ||
334 | |||
335 | public void AddHeader(string name, string value) {} | ||
336 | public void Send() | ||
337 | { | ||
338 | if (!_headersSent) SendHeaders(); | ||
339 | if (_sent) throw new InvalidOperationException("stuff already sent"); | ||
340 | _sent = true; | ||
341 | } | ||
342 | |||
343 | public void SendBody(byte[] buffer, int offset, int count) | ||
344 | { | ||
345 | if (!_headersSent) SendHeaders(); | ||
346 | _sent = true; | ||
347 | } | ||
348 | public void SendBody(byte[] buffer) | ||
349 | { | ||
350 | if (!_headersSent) SendHeaders(); | ||
351 | _sent = true; | ||
352 | } | ||
353 | |||
354 | public void SendHeaders() | ||
355 | { | ||
356 | if (_headersSent) throw new InvalidOperationException("headers already sent"); | ||
357 | _headersSent = true; | ||
358 | } | ||
359 | |||
360 | public void Redirect(Uri uri) {} | ||
361 | public void Redirect(string url) {} | ||
362 | } | ||
363 | |||
364 | |||
45 | public OSHttpRequest req0; | 365 | public OSHttpRequest req0; |
46 | public OSHttpRequest req1; | 366 | public OSHttpRequest req1; |
47 | 367 | ||
@@ -113,4 +433,4 @@ namespace OpenSim.Framework.Servers.Tests | |||
113 | Assert.That(rsp0.ContentType, Is.EqualTo("text/xml")); | 433 | Assert.That(rsp0.ContentType, Is.EqualTo("text/xml")); |
114 | } | 434 | } |
115 | } | 435 | } |
116 | } \ No newline at end of file | 436 | } |