aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Framework/Servers
diff options
context:
space:
mode:
authorMelanie2018-09-12 13:22:17 +0100
committerMelanie2018-09-12 13:22:17 +0100
commite874e3a2ad47af6a045dbe3f4dd91364cd92750a (patch)
treea92dc21f85d01e421842cb2fbfa4ecdf3430334a /OpenSim/Framework/Servers
parentSquelch "connection reset by peer" exceptions (diff)
parentoooops (diff)
downloadopensim-SC-e874e3a2ad47af6a045dbe3f4dd91364cd92750a.zip
opensim-SC-e874e3a2ad47af6a045dbe3f4dd91364cd92750a.tar.gz
opensim-SC-e874e3a2ad47af6a045dbe3f4dd91364cd92750a.tar.bz2
opensim-SC-e874e3a2ad47af6a045dbe3f4dd91364cd92750a.tar.xz
Merge branch 'master' of opensimulator.org:/var/git/opensim
Diffstat (limited to 'OpenSim/Framework/Servers')
-rw-r--r--OpenSim/Framework/Servers/BaseOpenSimServer.cs45
-rw-r--r--OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs295
-rw-r--r--OpenSim/Framework/Servers/HttpServer/Interfaces/IOSHttpResponse.cs2
-rw-r--r--OpenSim/Framework/Servers/HttpServer/OSHttpResponse.cs19
-rw-r--r--OpenSim/Framework/Servers/HttpServer/PollServiceEventArgs.cs9
-rw-r--r--OpenSim/Framework/Servers/HttpServer/PollServiceHttpRequest.cs18
-rw-r--r--OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs216
-rw-r--r--OpenSim/Framework/Servers/HttpServer/RestStreamHandler.cs7
-rw-r--r--OpenSim/Framework/Servers/MainServer.cs28
-rw-r--r--OpenSim/Framework/Servers/ServerBase.cs109
-rw-r--r--OpenSim/Framework/Servers/Tests/VersionInfoTests.cs9
11 files changed, 449 insertions, 308 deletions
diff --git a/OpenSim/Framework/Servers/BaseOpenSimServer.cs b/OpenSim/Framework/Servers/BaseOpenSimServer.cs
index f761813..f832f81 100644
--- a/OpenSim/Framework/Servers/BaseOpenSimServer.cs
+++ b/OpenSim/Framework/Servers/BaseOpenSimServer.cs
@@ -33,6 +33,9 @@ using System.Text;
33using System.Text.RegularExpressions; 33using System.Text.RegularExpressions;
34using System.Threading; 34using System.Threading;
35using System.Timers; 35using System.Timers;
36using System.Net;
37using System.Net.Security;
38using System.Security.Cryptography.X509Certificates;
36using log4net; 39using log4net;
37using log4net.Appender; 40using log4net.Appender;
38using log4net.Core; 41using log4net.Core;
@@ -86,6 +89,26 @@ namespace OpenSim.Framework.Servers
86 m_osSecret = UUID.Random().ToString(); 89 m_osSecret = UUID.Random().ToString();
87 } 90 }
88 91
92 private static bool m_NoVerifyCertChain = false;
93 private static bool m_NoVerifyCertHostname = false;
94
95 public static bool ValidateServerCertificate(
96 object sender,
97 X509Certificate certificate,
98 X509Chain chain,
99 SslPolicyErrors sslPolicyErrors)
100 {
101 if (m_NoVerifyCertChain)
102 sslPolicyErrors &= ~SslPolicyErrors.RemoteCertificateChainErrors;
103
104 if (m_NoVerifyCertHostname)
105 sslPolicyErrors &= ~SslPolicyErrors.RemoteCertificateNameMismatch;
106
107 if (sslPolicyErrors == SslPolicyErrors.None)
108 return true;
109
110 return false;
111 }
89 /// <summary> 112 /// <summary>
90 /// Must be overriden by child classes for their own server specific startup behaviour. 113 /// Must be overriden by child classes for their own server specific startup behaviour.
91 /// </summary> 114 /// </summary>
@@ -96,6 +119,11 @@ namespace OpenSim.Framework.Servers
96 RegisterCommonComponents(Config); 119 RegisterCommonComponents(Config);
97 120
98 IConfig startupConfig = Config.Configs["Startup"]; 121 IConfig startupConfig = Config.Configs["Startup"];
122
123 m_NoVerifyCertChain = startupConfig.GetBoolean("NoVerifyCertChain", m_NoVerifyCertChain);
124 m_NoVerifyCertHostname = startupConfig.GetBoolean("NoVerifyCertHostname", m_NoVerifyCertHostname);
125 ServicePointManager.ServerCertificateValidationCallback = ValidateServerCertificate;
126
99 int logShowStatsSeconds = startupConfig.GetInt("LogShowStatsSeconds", m_periodDiagnosticTimerMS / 1000); 127 int logShowStatsSeconds = startupConfig.GetInt("LogShowStatsSeconds", m_periodDiagnosticTimerMS / 1000);
100 m_periodDiagnosticTimerMS = logShowStatsSeconds * 1000; 128 m_periodDiagnosticTimerMS = logShowStatsSeconds * 1000;
101 m_periodicDiagnosticsTimer.Elapsed += new ElapsedEventHandler(LogDiagnostics); 129 m_periodicDiagnosticsTimer.Elapsed += new ElapsedEventHandler(LogDiagnostics);
@@ -108,13 +136,21 @@ namespace OpenSim.Framework.Servers
108 136
109 protected override void ShutdownSpecific() 137 protected override void ShutdownSpecific()
110 { 138 {
111 m_log.Info("[SHUTDOWN]: Shutdown processing on main thread complete. Exiting..."); 139 Watchdog.Enabled = false;
140 base.ShutdownSpecific();
141
142 MainServer.Stop();
143
144 Thread.Sleep(5000);
145 Util.StopThreadPool();
146 WorkManager.Stop();
112 147
148 Thread.Sleep(1000);
113 RemovePIDFile(); 149 RemovePIDFile();
114 150
115 base.ShutdownSpecific(); 151 m_log.Info("[SHUTDOWN]: Shutdown processing on main thread complete. Exiting...");
116 152
117 if (!SuppressExit) 153 if (!SuppressExit)
118 Environment.Exit(0); 154 Environment.Exit(0);
119 } 155 }
120 156
@@ -163,8 +199,7 @@ namespace OpenSim.Framework.Servers
163 } 199 }
164 catch(Exception e) 200 catch(Exception e)
165 { 201 {
166 m_log.FatalFormat("Fatal error: {0}", 202 m_log.Fatal("Fatal error: " + e.ToString());
167 (e.Message == null || e.Message == String.Empty) ? "Unknown reason":e.Message );
168 Environment.Exit(1); 203 Environment.Exit(1);
169 } 204 }
170 205
diff --git a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs
index fb92b92..2819bc9 100644
--- a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs
+++ b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs
@@ -32,6 +32,7 @@ using System.Collections.Specialized;
32using System.IO; 32using System.IO;
33using System.Net; 33using System.Net;
34using System.Net.Sockets; 34using System.Net.Sockets;
35using System.Net.Security;
35using System.Security.Cryptography.X509Certificates; 36using System.Security.Cryptography.X509Certificates;
36using System.Reflection; 37using System.Reflection;
37using System.Globalization; 38using System.Globalization;
@@ -43,10 +44,11 @@ using log4net;
43using Nwc.XmlRpc; 44using Nwc.XmlRpc;
44using OpenMetaverse.StructuredData; 45using OpenMetaverse.StructuredData;
45using CoolHTTPListener = HttpServer.HttpListener; 46using CoolHTTPListener = HttpServer.HttpListener;
46using HttpListener=System.Net.HttpListener; 47using HttpListener = System.Net.HttpListener;
47using LogPrio=HttpServer.LogPrio; 48using LogPrio = HttpServer.LogPrio;
48using OpenSim.Framework.Monitoring; 49using OpenSim.Framework.Monitoring;
49using System.IO.Compression; 50using System.IO.Compression;
51using System.Security.Cryptography;
50 52
51namespace OpenSim.Framework.Servers.HttpServer 53namespace OpenSim.Framework.Servers.HttpServer
52{ 54{
@@ -107,19 +109,26 @@ namespace OpenSim.Framework.Servers.HttpServer
107 new Dictionary<string, WebSocketRequestDelegate>(); 109 new Dictionary<string, WebSocketRequestDelegate>();
108 110
109 protected uint m_port; 111 protected uint m_port;
110 protected uint m_sslport;
111 protected bool m_ssl; 112 protected bool m_ssl;
112 private X509Certificate2 m_cert; 113 private X509Certificate2 m_cert;
113 protected bool m_firstcaps = true;
114 protected string m_SSLCommonName = ""; 114 protected string m_SSLCommonName = "";
115 protected List<string> m_certNames = new List<string>();
116 protected List<string> m_certIPs = new List<string>();
117 protected string m_certCN= "";
118 protected RemoteCertificateValidationCallback m_certificateValidationCallback = null;
115 119
116 protected IPAddress m_listenIPAddress = IPAddress.Any; 120 protected IPAddress m_listenIPAddress = IPAddress.Any;
117 121
118 public PollServiceRequestManager PollServiceRequestManager { get; private set; } 122 public PollServiceRequestManager PollServiceRequestManager { get; private set; }
119 123
124 public string Protocol
125 {
126 get { return m_ssl ? "https://" : "http://"; }
127 }
128
120 public uint SSLPort 129 public uint SSLPort
121 { 130 {
122 get { return m_sslport; } 131 get { return m_port; }
123 } 132 }
124 133
125 public string SSLCommonName 134 public string SSLCommonName
@@ -148,27 +157,166 @@ namespace OpenSim.Framework.Servers.HttpServer
148 m_port = port; 157 m_port = port;
149 } 158 }
150 159
151 public BaseHttpServer(uint port, bool ssl) : this (port) 160 private void load_cert(string CPath, string CPass)
152 { 161 {
153 m_ssl = ssl; 162 try
163 {
164 m_cert = new X509Certificate2(CPath, CPass);
165 X509Extension ext = m_cert.Extensions["2.5.29.17"];
166 if(ext != null)
167 {
168 AsnEncodedData asndata = new AsnEncodedData(ext.Oid, ext.RawData);
169 string datastr = asndata.Format(true);
170 string[] lines = datastr.Split(new char[] {'\n','\r'});
171 foreach(string s in lines)
172 {
173 if(String.IsNullOrEmpty(s))
174 continue;
175 string[] parts = s.Split(new char[] {'='});
176 if(String.IsNullOrEmpty(parts[0]))
177 continue;
178 string entryName = parts[0].Replace(" ","");
179 if(entryName == "DNSName")
180 m_certNames.Add(parts[1]);
181 else if(entryName == "IPAddress")
182 m_certIPs.Add(parts[1]);
183 else if(entryName == "Unknown(135)") // stupid mono
184 {
185 try
186 {
187 if(parts[1].Length == 8)
188 {
189 long tmp = long.Parse(parts[1], NumberStyles.AllowHexSpecifier);
190 tmp = IPAddress.HostToNetworkOrder(tmp);
191 tmp = (long)((ulong) tmp >> 32);
192 IPAddress ia = new IPAddress(tmp);
193 m_certIPs.Add(ia.ToString());
194 }
195 }
196 catch {}
197 }
198 }
199 }
200 m_certCN = m_cert.GetNameInfo(X509NameType.SimpleName, false);
201 }
202 catch
203 {
204 throw new Exception("SSL cert load error");
205 }
154 } 206 }
155 207
156 public BaseHttpServer(uint port, bool ssl, uint sslport, string CN) : this (port, ssl) 208 public BaseHttpServer(uint port, bool ssl, string CN, string CPath, string CPass)
157 { 209 {
158 if (m_ssl) 210 m_port = port;
211 if (ssl)
159 { 212 {
160 m_sslport = sslport; 213 if(string.IsNullOrEmpty(CPath))
214 throw new Exception("invalid main http server cert path");
215
216 if(Uri.CheckHostName(CN) == UriHostNameType.Unknown)
217 throw new Exception("invalid main http server CN (ExternalHostName)");
218
219 m_certNames.Clear();
220 m_certIPs.Clear();
221 m_certCN= "";
222
223 m_ssl = true;
224 load_cert(CPath, CPass);
225
226 if(!CheckSSLCertHost(CN))
227 throw new Exception("invalid main http server CN (ExternalHostName)");
228
229 m_SSLCommonName = CN;
230
231 if(m_cert.Issuer == m_cert.Subject )
232 m_log.Warn("Self signed certificate. Clients need to allow this (some viewers debug option NoVerifySSLcert must be set to true");
161 } 233 }
234 else
235 m_ssl = false;
162 } 236 }
163 237
164 public BaseHttpServer(uint port, bool ssl, string CPath, string CPass) : this (port, ssl) 238 public BaseHttpServer(uint port, bool ssl, string CPath, string CPass)
165 { 239 {
166 if (m_ssl) 240 m_port = port;
241 if (ssl)
167 { 242 {
168 m_cert = new X509Certificate2(CPath, CPass); 243 load_cert(CPath, CPass);
244 if(m_cert.Issuer == m_cert.Subject )
245 m_log.Warn("Self signed certificate. Http clients need to allow this");
246 m_ssl = true;
247 }
248 else
249 m_ssl = false;
250 }
251
252 static bool MatchDNS (string hostname, string dns)
253 {
254 int indx = dns.IndexOf ('*');
255 if (indx == -1)
256 return (String.Compare(hostname, dns, true, CultureInfo.InvariantCulture) == 0);
257
258 int dnslen = dns.Length;
259 dnslen--;
260 if(indx == dnslen)
261 return true; // just * ?
262
263 if(indx > dnslen - 2)
264 return false; // 2 short ?
265
266 if (dns[indx + 1] != '.')
267 return false;
268
269 int indx2 = dns.IndexOf ('*', indx + 1);
270 if (indx2 != -1)
271 return false; // there can only be one;
272
273 string end = dns.Substring(indx + 1);
274 int hostlen = hostname.Length;
275 int endlen = end.Length;
276 int length = hostlen - endlen;
277 if (length <= 0)
278 return false;
279
280 if (String.Compare(hostname, length, end, 0, endlen, true, CultureInfo.InvariantCulture) != 0)
281 return false;
282
283 if (indx == 0)
284 {
285 indx2 = hostname.IndexOf ('.');
286 return ((indx2 == -1) || (indx2 >= length));
287 }
288
289 string start = dns.Substring (0, indx);
290 return (String.Compare (hostname, 0, start, 0, start.Length, true, CultureInfo.InvariantCulture) == 0);
291 }
292
293 public bool CheckSSLCertHost(string hostname)
294 {
295 UriHostNameType htype = Uri.CheckHostName(hostname);
296
297 if(htype == UriHostNameType.Unknown || htype == UriHostNameType.Basic)
298 return false;
299 if(htype == UriHostNameType.Dns)
300 {
301 foreach(string name in m_certNames)
302 {
303 if(MatchDNS(hostname, name))
304 return true;
305 }
306 if(MatchDNS(hostname, m_certCN))
307 return true;
308 }
309 else
310 {
311 foreach(string ip in m_certIPs)
312 {
313 if (String.Compare(hostname, ip, true, CultureInfo.InvariantCulture) == 0)
314 return true;
315 }
169 } 316 }
170 }
171 317
318 return false;
319 }
172 /// <summary> 320 /// <summary>
173 /// Add a stream handler to the http server. If the handler already exists, then nothing happens. 321 /// Add a stream handler to the http server. If the handler already exists, then nothing happens.
174 /// </summary> 322 /// </summary>
@@ -396,14 +544,10 @@ namespace OpenSim.Framework.Servers.HttpServer
396 if (psEvArgs.Request != null) 544 if (psEvArgs.Request != null)
397 { 545 {
398 OSHttpRequest req = new OSHttpRequest(context, request); 546 OSHttpRequest req = new OSHttpRequest(context, request);
399 547 string requestBody;
400 Stream requestStream = req.InputStream;
401
402 Encoding encoding = Encoding.UTF8; 548 Encoding encoding = Encoding.UTF8;
403 StreamReader reader = new StreamReader(requestStream, encoding); 549 using(StreamReader reader = new StreamReader(req.InputStream, encoding))
404 550 requestBody = reader.ReadToEnd();
405 string requestBody = reader.ReadToEnd();
406 reader.Close();
407 551
408 Hashtable keysvals = new Hashtable(); 552 Hashtable keysvals = new Hashtable();
409 Hashtable headervals = new Hashtable(); 553 Hashtable headervals = new Hashtable();
@@ -461,8 +605,7 @@ namespace OpenSim.Framework.Servers.HttpServer
461 } 605 }
462 606
463 OSHttpResponse resp = new OSHttpResponse(new HttpResponse(context, request),context); 607 OSHttpResponse resp = new OSHttpResponse(new HttpResponse(context, request),context);
464 resp.ReuseContext = true; 608
465// resp.ReuseContext = false;
466 HandleRequest(req, resp); 609 HandleRequest(req, resp);
467 610
468 // !!!HACK ALERT!!! 611 // !!!HACK ALERT!!!
@@ -494,6 +637,8 @@ namespace OpenSim.Framework.Servers.HttpServer
494 { 637 {
495 try 638 try
496 { 639 {
640 if(request.InputStream != null && request.InputStream.CanRead)
641 request.InputStream.Close();
497 byte[] buffer500 = SendHTML500(response); 642 byte[] buffer500 = SendHTML500(response);
498 response.OutputStream.Write(buffer500, 0, buffer500.Length); 643 response.OutputStream.Write(buffer500, 0, buffer500.Length);
499 response.Send(); 644 response.Send();
@@ -541,7 +686,6 @@ namespace OpenSim.Framework.Servers.HttpServer
541// } 686// }
542// } 687// }
543 688
544 //response.KeepAlive = true;
545 response.SendChunked = false; 689 response.SendChunked = false;
546 690
547 string path = request.RawUrl; 691 string path = request.RawUrl;
@@ -565,15 +709,11 @@ namespace OpenSim.Framework.Servers.HttpServer
565 { 709 {
566 //m_log.Debug("[BASE HTTP SERVER]: Found Caps based HTTP Handler"); 710 //m_log.Debug("[BASE HTTP SERVER]: Found Caps based HTTP Handler");
567 IGenericHTTPHandler HTTPRequestHandler = requestHandler as IGenericHTTPHandler; 711 IGenericHTTPHandler HTTPRequestHandler = requestHandler as IGenericHTTPHandler;
568 Stream requestStream = request.InputStream;
569 712
713 string requestBody;
570 Encoding encoding = Encoding.UTF8; 714 Encoding encoding = Encoding.UTF8;
571 StreamReader reader = new StreamReader(requestStream, encoding); 715 using(StreamReader reader = new StreamReader(request.InputStream, encoding))
572 716 requestBody = reader.ReadToEnd();
573 string requestBody = reader.ReadToEnd();
574
575 reader.Close();
576 //requestStream.Close();
577 717
578 Hashtable keysvals = new Hashtable(); 718 Hashtable keysvals = new Hashtable();
579 Hashtable headervals = new Hashtable(); 719 Hashtable headervals = new Hashtable();
@@ -613,7 +753,6 @@ namespace OpenSim.Framework.Servers.HttpServer
613 else 753 else
614 { 754 {
615 IStreamHandler streamHandler = (IStreamHandler)requestHandler; 755 IStreamHandler streamHandler = (IStreamHandler)requestHandler;
616
617 using (MemoryStream memoryStream = new MemoryStream()) 756 using (MemoryStream memoryStream = new MemoryStream())
618 { 757 {
619 streamHandler.Handle(path, request.InputStream, memoryStream, request, response); 758 streamHandler.Handle(path, request.InputStream, memoryStream, request, response);
@@ -690,7 +829,8 @@ namespace OpenSim.Framework.Servers.HttpServer
690 } 829 }
691 } 830 }
692 831
693 request.InputStream.Close(); 832 if(request.InputStream != null && request.InputStream.CanRead)
833 request.InputStream.Dispose();
694 834
695 if (buffer != null) 835 if (buffer != null)
696 { 836 {
@@ -723,10 +863,6 @@ namespace OpenSim.Framework.Servers.HttpServer
723 requestEndTick = Environment.TickCount; 863 requestEndTick = Environment.TickCount;
724 864
725 response.Send(); 865 response.Send();
726
727 //response.OutputStream.Close();
728
729 //response.FreeContext();
730 } 866 }
731 catch (SocketException e) 867 catch (SocketException e)
732 { 868 {
@@ -758,6 +894,9 @@ namespace OpenSim.Framework.Servers.HttpServer
758 } 894 }
759 finally 895 finally
760 { 896 {
897 if(request.InputStream != null && request.InputStream.CanRead)
898 request.InputStream.Close();
899
761 // Every month or so this will wrap and give bad numbers, not really a problem 900 // Every month or so this will wrap and give bad numbers, not really a problem
762 // since its just for reporting 901 // since its just for reporting
763 int tickdiff = requestEndTick - requestStartTick; 902 int tickdiff = requestEndTick - requestStartTick;
@@ -998,7 +1137,7 @@ namespace OpenSim.Framework.Servers.HttpServer
998 { 1137 {
999 String requestBody; 1138 String requestBody;
1000 1139
1001 Stream requestStream = request.InputStream; 1140 Stream requestStream = Util.Copy(request.InputStream);
1002 Stream innerStream = null; 1141 Stream innerStream = null;
1003 try 1142 try
1004 { 1143 {
@@ -1009,15 +1148,15 @@ namespace OpenSim.Framework.Servers.HttpServer
1009 } 1148 }
1010 1149
1011 using (StreamReader reader = new StreamReader(requestStream, Encoding.UTF8)) 1150 using (StreamReader reader = new StreamReader(requestStream, Encoding.UTF8))
1012 {
1013 requestBody = reader.ReadToEnd(); 1151 requestBody = reader.ReadToEnd();
1152
1014 } 1153 }
1015 }
1016 finally 1154 finally
1017 { 1155 {
1018 if (innerStream != null) 1156 if (innerStream != null && innerStream.CanRead)
1019 innerStream.Dispose(); 1157 innerStream.Dispose();
1020 requestStream.Dispose(); 1158 if (requestStream.CanRead)
1159 requestStream.Dispose();
1021 } 1160 }
1022 1161
1023 //m_log.Debug(requestBody); 1162 //m_log.Debug(requestBody);
@@ -1098,6 +1237,17 @@ namespace OpenSim.Framework.Servers.HttpServer
1098 1237
1099 if (gridproxy) 1238 if (gridproxy)
1100 xmlRprcRequest.Params.Add("gridproxy"); // Param[4] 1239 xmlRprcRequest.Params.Add("gridproxy"); // Param[4]
1240
1241 // reserve this for
1242 // ... by Fumi.Iseki for DTLNSLMoneyServer
1243 // BUT make its presence possible to detect/parse
1244 string rcn = request.IHttpClientContext.SSLCommonName;
1245 if(!string.IsNullOrWhiteSpace(rcn))
1246 {
1247 rcn = "SSLCN:" + rcn;
1248 xmlRprcRequest.Params.Add(rcn); // Param[4] or Param[5]
1249 }
1250
1101 try 1251 try
1102 { 1252 {
1103 xmlRpcResponse = method(xmlRprcRequest, request.RemoteIPEndPoint); 1253 xmlRpcResponse = method(xmlRprcRequest, request.RemoteIPEndPoint);
@@ -1263,15 +1413,12 @@ namespace OpenSim.Framework.Servers.HttpServer
1263 //m_log.Warn("[BASE HTTP SERVER]: We've figured out it's a LLSD Request"); 1413 //m_log.Warn("[BASE HTTP SERVER]: We've figured out it's a LLSD Request");
1264 Stream requestStream = request.InputStream; 1414 Stream requestStream = request.InputStream;
1265 1415
1416 string requestBody;
1266 Encoding encoding = Encoding.UTF8; 1417 Encoding encoding = Encoding.UTF8;
1267 StreamReader reader = new StreamReader(requestStream, encoding); 1418 using(StreamReader reader = new StreamReader(requestStream, encoding))
1268 1419 requestBody= reader.ReadToEnd();
1269 string requestBody = reader.ReadToEnd();
1270 reader.Close();
1271 requestStream.Close();
1272 1420
1273 //m_log.DebugFormat("[OGP]: {0}:{1}", request.RawUrl, requestBody); 1421 //m_log.DebugFormat("[OGP]: {0}:{1}", request.RawUrl, requestBody);
1274 response.KeepAlive = true;
1275 1422
1276 OSD llsdRequest = null; 1423 OSD llsdRequest = null;
1277 OSD llsdResponse = null; 1424 OSD llsdResponse = null;
@@ -1592,15 +1739,10 @@ namespace OpenSim.Framework.Servers.HttpServer
1592 byte[] buffer; 1739 byte[] buffer;
1593 1740
1594 Stream requestStream = request.InputStream; 1741 Stream requestStream = request.InputStream;
1595 1742 string requestBody;
1596 Encoding encoding = Encoding.UTF8; 1743 Encoding encoding = Encoding.UTF8;
1597 StreamReader reader = new StreamReader(requestStream, encoding); 1744 using(StreamReader reader = new StreamReader(requestStream, encoding))
1598 1745 requestBody = reader.ReadToEnd();
1599 string requestBody = reader.ReadToEnd();
1600 // avoid warning for now
1601 reader.ReadToEnd();
1602 reader.Close();
1603 requestStream.Close();
1604 1746
1605 Hashtable keysvals = new Hashtable(); 1747 Hashtable keysvals = new Hashtable();
1606 Hashtable headervals = new Hashtable(); 1748 Hashtable headervals = new Hashtable();
@@ -1792,20 +1934,13 @@ namespace OpenSim.Framework.Servers.HttpServer
1792 { 1934 {
1793 response.ProtocolVersion = (string)responsedata["http_protocol_version"]; 1935 response.ProtocolVersion = (string)responsedata["http_protocol_version"];
1794 } 1936 }
1795/* 1937
1796 if (responsedata.ContainsKey("keepalive")) 1938 if (responsedata.ContainsKey("keepalive"))
1797 { 1939 {
1798 bool keepalive = (bool)responsedata["keepalive"]; 1940 bool keepalive = (bool)responsedata["keepalive"];
1799 response.KeepAlive = keepalive; 1941 response.KeepAlive = keepalive;
1800 } 1942 }
1801 1943
1802 if (responsedata.ContainsKey("reusecontext"))
1803 response.ReuseContext = (bool) responsedata["reusecontext"];
1804*/
1805 // disable this things
1806 response.KeepAlive = false;
1807 response.ReuseContext = false;
1808
1809 // Cross-Origin Resource Sharing with simple requests 1944 // Cross-Origin Resource Sharing with simple requests
1810 if (responsedata.ContainsKey("access_control_allow_origin")) 1945 if (responsedata.ContainsKey("access_control_allow_origin"))
1811 response.AddHeader("Access-Control-Allow-Origin", (string)responsedata["access_control_allow_origin"]); 1946 response.AddHeader("Access-Control-Allow-Origin", (string)responsedata["access_control_allow_origin"]);
@@ -1818,11 +1953,8 @@ namespace OpenSim.Framework.Servers.HttpServer
1818 contentType = "text/html"; 1953 contentType = "text/html";
1819 } 1954 }
1820 1955
1821
1822
1823 // The client ignores anything but 200 here for web login, so ensure that this is 200 for that 1956 // The client ignores anything but 200 here for web login, so ensure that this is 200 for that
1824 1957
1825
1826 response.StatusCode = responsecode; 1958 response.StatusCode = responsecode;
1827 1959
1828 if (responsecode == (int)OSHttpStatusCode.RedirectMovedPermanently) 1960 if (responsecode == (int)OSHttpStatusCode.RedirectMovedPermanently)
@@ -1832,13 +1964,12 @@ namespace OpenSim.Framework.Servers.HttpServer
1832 } 1964 }
1833 1965
1834 response.AddHeader("Content-Type", contentType); 1966 response.AddHeader("Content-Type", contentType);
1835
1836 if (responsedata.ContainsKey("headers")) 1967 if (responsedata.ContainsKey("headers"))
1837 { 1968 {
1838 Hashtable headerdata = (Hashtable)responsedata["headers"]; 1969 Hashtable headerdata = (Hashtable)responsedata["headers"];
1839 1970
1840 foreach (string header in headerdata.Keys) 1971 foreach (string header in headerdata.Keys)
1841 response.AddHeader(header, (string)headerdata[header]); 1972 response.AddHeader(header, headerdata[header].ToString());
1842 } 1973 }
1843 1974
1844 byte[] buffer; 1975 byte[] buffer;
@@ -1906,7 +2037,7 @@ namespace OpenSim.Framework.Servers.HttpServer
1906 2037
1907 public void Start() 2038 public void Start()
1908 { 2039 {
1909 Start(true); 2040 Start(true,true);
1910 } 2041 }
1911 2042
1912 /// <summary> 2043 /// <summary>
@@ -1916,7 +2047,7 @@ namespace OpenSim.Framework.Servers.HttpServer
1916 /// If true then poll responses are performed asynchronsly. 2047 /// If true then poll responses are performed asynchronsly.
1917 /// Option exists to allow regression tests to perform processing synchronously. 2048 /// Option exists to allow regression tests to perform processing synchronously.
1918 /// </param> 2049 /// </param>
1919 public void Start(bool performPollResponsesAsync) 2050 public void Start(bool performPollResponsesAsync, bool runPool)
1920 { 2051 {
1921 m_log.InfoFormat( 2052 m_log.InfoFormat(
1922 "[BASE HTTP SERVER]: Starting {0} server on port {1}", UseSSL ? "HTTPS" : "HTTP", Port); 2053 "[BASE HTTP SERVER]: Starting {0} server on port {1}", UseSSL ? "HTTPS" : "HTTP", Port);
@@ -1945,6 +2076,8 @@ namespace OpenSim.Framework.Servers.HttpServer
1945 //m_httpListener.Prefixes.Add("https://+:" + (m_sslport) + "/"); 2076 //m_httpListener.Prefixes.Add("https://+:" + (m_sslport) + "/");
1946 //m_httpListener.Prefixes.Add("http://+:" + m_port + "/"); 2077 //m_httpListener.Prefixes.Add("http://+:" + m_port + "/");
1947 m_httpListener2 = CoolHTTPListener.Create(IPAddress.Any, (int)m_port, m_cert); 2078 m_httpListener2 = CoolHTTPListener.Create(IPAddress.Any, (int)m_port, m_cert);
2079 if(m_certificateValidationCallback != null)
2080 m_httpListener2.CertificateValidationCallback = m_certificateValidationCallback;
1948 m_httpListener2.ExceptionThrown += httpServerException; 2081 m_httpListener2.ExceptionThrown += httpServerException;
1949 m_httpListener2.LogWriter = httpserverlog; 2082 m_httpListener2.LogWriter = httpserverlog;
1950 } 2083 }
@@ -1954,9 +2087,11 @@ namespace OpenSim.Framework.Servers.HttpServer
1954 m_httpListener2.Start(64); 2087 m_httpListener2.Start(64);
1955 2088
1956 // Long Poll Service Manager with 3 worker threads a 25 second timeout for no events 2089 // Long Poll Service Manager with 3 worker threads a 25 second timeout for no events
1957 2090 if(runPool)
1958 PollServiceRequestManager = new PollServiceRequestManager(this, performPollResponsesAsync, 2, 25000); 2091 {
1959 PollServiceRequestManager.Start(); 2092 PollServiceRequestManager = new PollServiceRequestManager(this, performPollResponsesAsync, 2, 25000);
2093 PollServiceRequestManager.Start();
2094 }
1960 2095
1961 HTTPDRunning = true; 2096 HTTPDRunning = true;
1962 2097
@@ -1970,7 +2105,7 @@ namespace OpenSim.Framework.Servers.HttpServer
1970 catch (Exception e) 2105 catch (Exception e)
1971 { 2106 {
1972 m_log.Error("[BASE HTTP SERVER]: Error - " + e.Message); 2107 m_log.Error("[BASE HTTP SERVER]: Error - " + e.Message);
1973 m_log.Error("[BASE HTTP SERVER]: Tip: Do you have permission to listen on port " + m_port + ", " + m_sslport + "?"); 2108 m_log.Error("[BASE HTTP SERVER]: Tip: Do you have permission to listen on port " + m_port + "?");
1974 2109
1975 // We want this exception to halt the entire server since in current configurations we aren't too 2110 // We want this exception to halt the entire server since in current configurations we aren't too
1976 // useful without inbound HTTP. 2111 // useful without inbound HTTP.
@@ -2028,7 +2163,8 @@ namespace OpenSim.Framework.Servers.HttpServer
2028 2163
2029 try 2164 try
2030 { 2165 {
2031 PollServiceRequestManager.Stop(); 2166 if(PollServiceRequestManager != null)
2167 PollServiceRequestManager.Stop();
2032 2168
2033 m_httpListener2.ExceptionThrown -= httpServerException; 2169 m_httpListener2.ExceptionThrown -= httpServerException;
2034 //m_httpListener2.DisconnectHandler = null; 2170 //m_httpListener2.DisconnectHandler = null;
@@ -2135,10 +2271,9 @@ namespace OpenSim.Framework.Servers.HttpServer
2135 string file = Path.Combine(".", "http_500.html"); 2271 string file = Path.Combine(".", "http_500.html");
2136 if (!File.Exists(file)) 2272 if (!File.Exists(file))
2137 return getDefaultHTTP500(); 2273 return getDefaultHTTP500();
2138 2274 string result;
2139 StreamReader sr = File.OpenText(file); 2275 using(StreamReader sr = File.OpenText(file))
2140 string result = sr.ReadToEnd(); 2276 result = sr.ReadToEnd();
2141 sr.Close();
2142 return result; 2277 return result;
2143 } 2278 }
2144 2279
diff --git a/OpenSim/Framework/Servers/HttpServer/Interfaces/IOSHttpResponse.cs b/OpenSim/Framework/Servers/HttpServer/Interfaces/IOSHttpResponse.cs
index f61b090..d26b68a 100644
--- a/OpenSim/Framework/Servers/HttpServer/Interfaces/IOSHttpResponse.cs
+++ b/OpenSim/Framework/Servers/HttpServer/Interfaces/IOSHttpResponse.cs
@@ -118,7 +118,7 @@ namespace OpenSim.Framework.Servers.HttpServer
118 /// </summary> 118 /// </summary>
119 string StatusDescription { get; set; } 119 string StatusDescription { get; set; }
120 120
121 bool ReuseContext { get; set; } 121// bool ReuseContext { get; set; }
122 122
123 /// <summary> 123 /// <summary>
124 /// Add a header field and content to the response. 124 /// Add a header field and content to the response.
diff --git a/OpenSim/Framework/Servers/HttpServer/OSHttpResponse.cs b/OpenSim/Framework/Servers/HttpServer/OSHttpResponse.cs
index d7744fc..a107ced 100644
--- a/OpenSim/Framework/Servers/HttpServer/OSHttpResponse.cs
+++ b/OpenSim/Framework/Servers/HttpServer/OSHttpResponse.cs
@@ -257,25 +257,6 @@ namespace OpenSim.Framework.Servers.HttpServer
257 } 257 }
258 } 258 }
259 259
260 public bool ReuseContext
261 {
262 get
263 {
264 if (_httpClientContext != null)
265 {
266 return !_httpClientContext.EndWhenDone;
267 }
268 return true;
269 }
270 set
271 {
272 if (_httpClientContext != null)
273 {
274 _httpClientContext.EndWhenDone = !value;
275 }
276 }
277 }
278
279 protected IHttpResponse _httpResponse; 260 protected IHttpResponse _httpResponse;
280 private IHttpClientContext _httpClientContext; 261 private IHttpClientContext _httpClientContext;
281 262
diff --git a/OpenSim/Framework/Servers/HttpServer/PollServiceEventArgs.cs b/OpenSim/Framework/Servers/HttpServer/PollServiceEventArgs.cs
index 8ace7a9..7c7d08d 100644
--- a/OpenSim/Framework/Servers/HttpServer/PollServiceEventArgs.cs
+++ b/OpenSim/Framework/Servers/HttpServer/PollServiceEventArgs.cs
@@ -37,6 +37,7 @@ namespace OpenSim.Framework.Servers.HttpServer
37 public delegate Hashtable GetEventsMethod(UUID requestID, UUID pId); 37 public delegate Hashtable GetEventsMethod(UUID requestID, UUID pId);
38 38
39 public delegate Hashtable NoEventsMethod(UUID requestID, UUID pId); 39 public delegate Hashtable NoEventsMethod(UUID requestID, UUID pId);
40 public delegate void DropMethod(UUID requestID, UUID pId);
40 41
41 public class PollServiceEventArgs : EventArgs 42 public class PollServiceEventArgs : EventArgs
42 { 43 {
@@ -44,13 +45,14 @@ namespace OpenSim.Framework.Servers.HttpServer
44 public GetEventsMethod GetEvents; 45 public GetEventsMethod GetEvents;
45 public NoEventsMethod NoEvents; 46 public NoEventsMethod NoEvents;
46 public RequestMethod Request; 47 public RequestMethod Request;
48 public DropMethod Drop;
47 public UUID Id; 49 public UUID Id;
48 public int TimeOutms; 50 public int TimeOutms;
49 public EventType Type; 51 public EventType Type;
50 52
51 public enum EventType : int 53 public enum EventType : int
52 { 54 {
53 LongPoll = 0, 55 Poll = 0,
54 LslHttp = 1, 56 LslHttp = 1,
55 Inventory = 2, 57 Inventory = 2,
56 Texture = 3, 58 Texture = 3,
@@ -73,16 +75,17 @@ namespace OpenSim.Framework.Servers.HttpServer
73 RequestMethod pRequest, 75 RequestMethod pRequest,
74 string pUrl, 76 string pUrl,
75 HasEventsMethod pHasEvents, GetEventsMethod pGetEvents, NoEventsMethod pNoEvents, 77 HasEventsMethod pHasEvents, GetEventsMethod pGetEvents, NoEventsMethod pNoEvents,
76 UUID pId, int pTimeOutms) 78 DropMethod pDrop, UUID pId, int pTimeOutms)
77 { 79 {
78 Request = pRequest; 80 Request = pRequest;
79 Url = pUrl; 81 Url = pUrl;
80 HasEvents = pHasEvents; 82 HasEvents = pHasEvents;
81 GetEvents = pGetEvents; 83 GetEvents = pGetEvents;
82 NoEvents = pNoEvents; 84 NoEvents = pNoEvents;
85 Drop = pDrop;
83 Id = pId; 86 Id = pId;
84 TimeOutms = pTimeOutms; 87 TimeOutms = pTimeOutms;
85 Type = EventType.LongPoll; 88 Type = EventType.Poll;
86 } 89 }
87 } 90 }
88} 91}
diff --git a/OpenSim/Framework/Servers/HttpServer/PollServiceHttpRequest.cs b/OpenSim/Framework/Servers/HttpServer/PollServiceHttpRequest.cs
index 3eb330a..4fd69f3 100644
--- a/OpenSim/Framework/Servers/HttpServer/PollServiceHttpRequest.cs
+++ b/OpenSim/Framework/Servers/HttpServer/PollServiceHttpRequest.cs
@@ -47,8 +47,10 @@ namespace OpenSim.Framework.Servers.HttpServer
47 public readonly UUID RequestID; 47 public readonly UUID RequestID;
48 public int contextHash; 48 public int contextHash;
49 49
50/*
50 private void GenContextHash() 51 private void GenContextHash()
51 { 52 {
53
52 Random rnd = new Random(); 54 Random rnd = new Random();
53 contextHash = 0; 55 contextHash = 0;
54 if (Request.Headers["remote_addr"] != null) 56 if (Request.Headers["remote_addr"] != null)
@@ -62,8 +64,9 @@ namespace OpenSim.Framework.Servers.HttpServer
62 } 64 }
63 else 65 else
64 contextHash += rnd.Next() & 0xffff; 66 contextHash += rnd.Next() & 0xffff;
65 }
66 67
68 }
69*/
67 public PollServiceHttpRequest( 70 public PollServiceHttpRequest(
68 PollServiceEventArgs pPollServiceArgs, IHttpClientContext pHttpContext, IHttpRequest pRequest) 71 PollServiceEventArgs pPollServiceArgs, IHttpClientContext pHttpContext, IHttpRequest pRequest)
69 { 72 {
@@ -72,7 +75,8 @@ namespace OpenSim.Framework.Servers.HttpServer
72 Request = pRequest; 75 Request = pRequest;
73 RequestTime = System.Environment.TickCount; 76 RequestTime = System.Environment.TickCount;
74 RequestID = UUID.Random(); 77 RequestID = UUID.Random();
75 GenContextHash(); 78// GenContextHash();
79 contextHash = HttpContext.contextID;
76 } 80 }
77 81
78 internal void DoHTTPGruntWork(BaseHttpServer server, Hashtable responsedata) 82 internal void DoHTTPGruntWork(BaseHttpServer server, Hashtable responsedata)
@@ -82,10 +86,12 @@ namespace OpenSim.Framework.Servers.HttpServer
82 86
83 byte[] buffer = server.DoHTTPGruntWork(responsedata, response); 87 byte[] buffer = server.DoHTTPGruntWork(responsedata, response);
84 88
89 if(Request.Body.CanRead)
90 Request.Body.Dispose();
91
85 response.SendChunked = false; 92 response.SendChunked = false;
86 response.ContentLength64 = buffer.Length; 93 response.ContentLength64 = buffer.Length;
87 response.ContentEncoding = Encoding.UTF8; 94 response.ContentEncoding = Encoding.UTF8;
88 response.ReuseContext = false;
89 95
90 try 96 try
91 { 97 {
@@ -114,10 +120,12 @@ namespace OpenSim.Framework.Servers.HttpServer
114 OSHttpResponse response 120 OSHttpResponse response
115 = new OSHttpResponse(new HttpResponse(HttpContext, Request), HttpContext); 121 = new OSHttpResponse(new HttpResponse(HttpContext, Request), HttpContext);
116 122
123 if(Request.Body.CanRead)
124 Request.Body.Dispose();
125
117 response.SendChunked = false; 126 response.SendChunked = false;
118 response.ContentLength64 = 0; 127 response.ContentLength64 = 0;
119 response.ContentEncoding = Encoding.UTF8; 128 response.ContentEncoding = Encoding.UTF8;
120 response.ReuseContext = false;
121 response.KeepAlive = false; 129 response.KeepAlive = false;
122 response.SendChunked = false; 130 response.SendChunked = false;
123 response.StatusCode = 503; 131 response.StatusCode = 503;
@@ -127,7 +135,7 @@ namespace OpenSim.Framework.Servers.HttpServer
127 response.OutputStream.Flush(); 135 response.OutputStream.Flush();
128 response.Send(); 136 response.Send();
129 } 137 }
130 catch (Exception e) 138 catch
131 { 139 {
132 } 140 }
133 } 141 }
diff --git a/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs b/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs
index 936146d..a2f6a11 100644
--- a/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs
+++ b/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs
@@ -30,13 +30,10 @@ using System.Collections;
30using System.Threading; 30using System.Threading;
31using System.Reflection; 31using System.Reflection;
32using log4net; 32using log4net;
33using HttpServer;
34using OpenSim.Framework;
35using OpenSim.Framework.Monitoring; 33using OpenSim.Framework.Monitoring;
36using Amib.Threading; 34using Amib.Threading;
37using System.IO;
38using System.Text;
39using System.Collections.Generic; 35using System.Collections.Generic;
36using System.Collections.Concurrent;
40 37
41namespace OpenSim.Framework.Servers.HttpServer 38namespace OpenSim.Framework.Servers.HttpServer
42{ 39{
@@ -46,21 +43,18 @@ namespace OpenSim.Framework.Servers.HttpServer
46 43
47 private readonly BaseHttpServer m_server; 44 private readonly BaseHttpServer m_server;
48 45
49 private Dictionary<PollServiceHttpRequest, Queue<PollServiceHttpRequest>> m_bycontext; 46 private Dictionary<int, Queue<PollServiceHttpRequest>> m_bycontext;
50 private BlockingQueue<PollServiceHttpRequest> m_requests = new BlockingQueue<PollServiceHttpRequest>(); 47 private BlockingCollection<PollServiceHttpRequest> m_requests = new BlockingCollection<PollServiceHttpRequest>();
51 private static Queue<PollServiceHttpRequest> m_slowRequests = new Queue<PollServiceHttpRequest>(); 48 private static ConcurrentQueue<PollServiceHttpRequest> m_retryRequests = new ConcurrentQueue<PollServiceHttpRequest>();
52 private static Queue<PollServiceHttpRequest> m_retryRequests = new Queue<PollServiceHttpRequest>();
53 49
54 private uint m_WorkerThreadCount = 0; 50 private uint m_WorkerThreadCount = 0;
55 private Thread[] m_workerThreads; 51 private Thread[] m_workerThreads;
56 private Thread m_retrysThread; 52 private Thread m_retrysThread;
57 53
58 private bool m_running = false; 54 private bool m_running = false;
59 private int slowCount = 0;
60 55
61 private SmartThreadPool m_threadPool; 56 private SmartThreadPool m_threadPool;
62 57
63
64 public PollServiceRequestManager( 58 public PollServiceRequestManager(
65 BaseHttpServer pSrv, bool performResponsesAsync, uint pWorkerThreadCount, int pTimeout) 59 BaseHttpServer pSrv, bool performResponsesAsync, uint pWorkerThreadCount, int pTimeout)
66 { 60 {
@@ -68,8 +62,7 @@ namespace OpenSim.Framework.Servers.HttpServer
68 m_WorkerThreadCount = pWorkerThreadCount; 62 m_WorkerThreadCount = pWorkerThreadCount;
69 m_workerThreads = new Thread[m_WorkerThreadCount]; 63 m_workerThreads = new Thread[m_WorkerThreadCount];
70 64
71 PollServiceHttpRequestComparer preqCp = new PollServiceHttpRequestComparer(); 65 m_bycontext = new Dictionary<int, Queue<PollServiceHttpRequest>>(256);
72 m_bycontext = new Dictionary<PollServiceHttpRequest, Queue<PollServiceHttpRequest>>(preqCp);
73 66
74 STPStartInfo startInfo = new STPStartInfo(); 67 STPStartInfo startInfo = new STPStartInfo();
75 startInfo.IdleTimeout = 30000; 68 startInfo.IdleTimeout = 30000;
@@ -80,7 +73,6 @@ namespace OpenSim.Framework.Servers.HttpServer
80 startInfo.ThreadPoolName = "PoolService"; 73 startInfo.ThreadPoolName = "PoolService";
81 74
82 m_threadPool = new SmartThreadPool(startInfo); 75 m_threadPool = new SmartThreadPool(startInfo);
83
84 } 76 }
85 77
86 public void Start() 78 public void Start()
@@ -95,7 +87,7 @@ namespace OpenSim.Framework.Servers.HttpServer
95 PoolWorkerJob, 87 PoolWorkerJob,
96 string.Format("PollServiceWorkerThread {0}:{1}", i, m_server.Port), 88 string.Format("PollServiceWorkerThread {0}:{1}", i, m_server.Port),
97 ThreadPriority.Normal, 89 ThreadPriority.Normal,
98 false, 90 true,
99 false, 91 false,
100 null, 92 null,
101 int.MaxValue); 93 int.MaxValue);
@@ -105,36 +97,32 @@ namespace OpenSim.Framework.Servers.HttpServer
105 this.CheckRetries, 97 this.CheckRetries,
106 string.Format("PollServiceWatcherThread:{0}", m_server.Port), 98 string.Format("PollServiceWatcherThread:{0}", m_server.Port),
107 ThreadPriority.Normal, 99 ThreadPriority.Normal,
108 false, 100 true,
109 true, 101 true,
110 null, 102 null,
111 1000 * 60 * 10); 103 1000 * 60 * 10);
112
113
114 } 104 }
115 105
116 private void ReQueueEvent(PollServiceHttpRequest req) 106 private void ReQueueEvent(PollServiceHttpRequest req)
117 { 107 {
118 if (m_running) 108 if (m_running)
119 { 109 m_retryRequests.Enqueue(req);
120 lock (m_retryRequests)
121 m_retryRequests.Enqueue(req);
122 }
123 } 110 }
124 111
125 public void Enqueue(PollServiceHttpRequest req) 112 public void Enqueue(PollServiceHttpRequest req)
126 { 113 {
114 Queue<PollServiceHttpRequest> ctxQeueue;
115 int rhash = req.contextHash;
127 lock (m_bycontext) 116 lock (m_bycontext)
128 { 117 {
129 Queue<PollServiceHttpRequest> ctxQeueue; 118 if (m_bycontext.TryGetValue(rhash, out ctxQeueue))
130 if (m_bycontext.TryGetValue(req, out ctxQeueue))
131 { 119 {
132 ctxQeueue.Enqueue(req); 120 ctxQeueue.Enqueue(req);
133 } 121 }
134 else 122 else
135 { 123 {
136 ctxQeueue = new Queue<PollServiceHttpRequest>(); 124 ctxQeueue = new Queue<PollServiceHttpRequest>();
137 m_bycontext[req] = ctxQeueue; 125 m_bycontext[rhash] = ctxQeueue;
138 EnqueueInt(req); 126 EnqueueInt(req);
139 } 127 }
140 } 128 }
@@ -143,9 +131,10 @@ namespace OpenSim.Framework.Servers.HttpServer
143 public void byContextDequeue(PollServiceHttpRequest req) 131 public void byContextDequeue(PollServiceHttpRequest req)
144 { 132 {
145 Queue<PollServiceHttpRequest> ctxQeueue; 133 Queue<PollServiceHttpRequest> ctxQeueue;
134 int rhash = req.contextHash;
146 lock (m_bycontext) 135 lock (m_bycontext)
147 { 136 {
148 if (m_bycontext.TryGetValue(req, out ctxQeueue)) 137 if (m_bycontext.TryGetValue(rhash, out ctxQeueue))
149 { 138 {
150 if (ctxQeueue.Count > 0) 139 if (ctxQeueue.Count > 0)
151 { 140 {
@@ -154,51 +143,41 @@ namespace OpenSim.Framework.Servers.HttpServer
154 } 143 }
155 else 144 else
156 { 145 {
157 m_bycontext.Remove(req); 146 m_bycontext.Remove(rhash);
158 } 147 }
159 } 148 }
160 } 149 }
161 } 150 }
162 151
163 public void EnqueueInt(PollServiceHttpRequest req) 152 public void DropByContext(PollServiceHttpRequest req)
164 { 153 {
165 if (m_running) 154 Queue<PollServiceHttpRequest> ctxQeueue;
155 int rhash = req.contextHash;
156 lock (m_bycontext)
166 { 157 {
167 if (req.PollServiceArgs.Type != PollServiceEventArgs.EventType.LongPoll) 158 if (m_bycontext.TryGetValue(rhash, out ctxQeueue))
168 { 159 {
169 m_requests.Enqueue(req); 160 ctxQeueue.Clear();
170 } 161 m_bycontext.Remove(rhash);
171 else
172 {
173 lock (m_slowRequests)
174 m_slowRequests.Enqueue(req);
175 } 162 }
176 } 163 }
177 } 164 }
178 165
166 public void EnqueueInt(PollServiceHttpRequest req)
167 {
168 if (m_running)
169 m_requests.Add(req);
170 }
171
179 private void CheckRetries() 172 private void CheckRetries()
180 { 173 {
174 PollServiceHttpRequest preq;
181 while (m_running) 175 while (m_running)
182
183 { 176 {
184 Thread.Sleep(100); // let the world move .. back to faster rate 177 Thread.Sleep(100);
185 Watchdog.UpdateThread(); 178 Watchdog.UpdateThread();
186 lock (m_retryRequests) 179 while (m_running && m_retryRequests.TryDequeue(out preq))
187 { 180 m_requests.Add(preq);
188 while (m_retryRequests.Count > 0 && m_running)
189 m_requests.Enqueue(m_retryRequests.Dequeue());
190 }
191 slowCount++;
192 if (slowCount >= 10)
193 {
194 slowCount = 0;
195
196 lock (m_slowRequests)
197 {
198 while (m_slowRequests.Count > 0 && m_running)
199 m_requests.Enqueue(m_slowRequests.Dequeue());
200 }
201 }
202 } 181 }
203 } 182 }
204 183
@@ -206,117 +185,130 @@ namespace OpenSim.Framework.Servers.HttpServer
206 { 185 {
207 m_running = false; 186 m_running = false;
208 187
209 Thread.Sleep(1000); // let the world move 188 Thread.Sleep(100); // let the world move
210 189
211 foreach (Thread t in m_workerThreads) 190 foreach (Thread t in m_workerThreads)
212 Watchdog.AbortThread(t.ManagedThreadId); 191 Watchdog.AbortThread(t.ManagedThreadId);
213 192
193 m_threadPool.Shutdown();
194
214 // any entry in m_bycontext should have a active request on the other queues 195 // any entry in m_bycontext should have a active request on the other queues
215 // so just delete contents to easy GC 196 // so just delete contents to easy GC
216 foreach (Queue<PollServiceHttpRequest> qu in m_bycontext.Values) 197 foreach (Queue<PollServiceHttpRequest> qu in m_bycontext.Values)
217 qu.Clear(); 198 qu.Clear();
218 m_bycontext.Clear(); 199 m_bycontext.Clear();
219 200
201 PollServiceHttpRequest req;
220 try 202 try
221 { 203 {
222 foreach (PollServiceHttpRequest req in m_retryRequests) 204 while(m_retryRequests.TryDequeue(out req))
223 {
224 req.DoHTTPstop(m_server); 205 req.DoHTTPstop(m_server);
225 }
226 } 206 }
227 catch 207 catch
228 { 208 {
229 } 209 }
230 210
231 PollServiceHttpRequest wreq; 211 try
232 m_retryRequests.Clear();
233
234 lock (m_slowRequests)
235 { 212 {
236 while (m_slowRequests.Count > 0) 213 while(m_requests.TryTake(out req, 0))
237 m_requests.Enqueue(m_slowRequests.Dequeue()); 214 req.DoHTTPstop(m_server);
238
239 } 215 }
240 216 catch
241 while (m_requests.Count() > 0)
242 { 217 {
243 try
244 {
245 wreq = m_requests.Dequeue(0);
246 wreq.DoHTTPstop(m_server);
247
248 }
249 catch
250 {
251 }
252 } 218 }
253 219
254 m_requests.Clear(); 220 m_requests.Dispose();
221
255 } 222 }
256 223
257 // work threads 224 // work threads
258 225
259 private void PoolWorkerJob() 226 private void PoolWorkerJob()
260 { 227 {
228 PollServiceHttpRequest req;
261 while (m_running) 229 while (m_running)
262 { 230 {
263 PollServiceHttpRequest req = m_requests.Dequeue(5000); 231 req = null;
232 if(!m_requests.TryTake(out req, 4500) || req == null)
233 {
234 Watchdog.UpdateThread();
235 continue;
236 }
264 237
265 Watchdog.UpdateThread(); 238 Watchdog.UpdateThread();
266 if (req != null) 239
240 try
267 { 241 {
268 try 242 if(!req.HttpContext.CanSend())
243 {
244 req.PollServiceArgs.Drop(req.RequestID, req.PollServiceArgs.Id);
245 byContextDequeue(req);
246 continue;
247 }
248
249 if(req.HttpContext.IsSending())
269 { 250 {
270 if (req.PollServiceArgs.HasEvents(req.RequestID, req.PollServiceArgs.Id)) 251 if ((Environment.TickCount - req.RequestTime) > req.PollServiceArgs.TimeOutms)
271 { 252 {
272 Hashtable responsedata = req.PollServiceArgs.GetEvents(req.RequestID, req.PollServiceArgs.Id); 253 req.PollServiceArgs.Drop(req.RequestID, req.PollServiceArgs.Id);
254 byContextDequeue(req);
255 }
256 else
257 ReQueueEvent(req);
258 continue;
259 }
273 260
261 if (req.PollServiceArgs.HasEvents(req.RequestID, req.PollServiceArgs.Id))
262 {
263 PollServiceHttpRequest nreq = req;
264 m_threadPool.QueueWorkItem(x =>
265 {
266 try
267 {
268 Hashtable responsedata = nreq.PollServiceArgs.GetEvents(nreq.RequestID, nreq.PollServiceArgs.Id);
269 nreq.DoHTTPGruntWork(m_server, responsedata);
270 }
271 catch (ObjectDisposedException) { }
272 finally
273 {
274 byContextDequeue(nreq);
275 nreq = null;
276 }
277 return null;
278 }, null);
279 }
280 else
281 {
282 if ((Environment.TickCount - req.RequestTime) > req.PollServiceArgs.TimeOutms)
283 {
284 PollServiceHttpRequest nreq = req;
274 m_threadPool.QueueWorkItem(x => 285 m_threadPool.QueueWorkItem(x =>
275 { 286 {
276 try 287 try
277 { 288 {
278 req.DoHTTPGruntWork(m_server, responsedata); 289 nreq.DoHTTPGruntWork(m_server,
279 byContextDequeue(req); 290 nreq.PollServiceArgs.NoEvents(nreq.RequestID, nreq.PollServiceArgs.Id));
280 } 291 }
281 catch (ObjectDisposedException) // Browser aborted before we could read body, server closed the stream 292 catch (ObjectDisposedException) {}
293 finally
282 { 294 {
283 // Ignore it, no need to reply 295 byContextDequeue(nreq);
296 nreq = null;
284 } 297 }
285 return null; 298 return null;
286 }, null); 299 }, null);
287 } 300 }
288 else 301 else
289 { 302 {
290 if ((Environment.TickCount - req.RequestTime) > req.PollServiceArgs.TimeOutms) 303 ReQueueEvent(req);
291 {
292 m_threadPool.QueueWorkItem(x =>
293 {
294 try
295 {
296 req.DoHTTPGruntWork(m_server,
297 req.PollServiceArgs.NoEvents(req.RequestID, req.PollServiceArgs.Id));
298 byContextDequeue(req);
299 }
300 catch (ObjectDisposedException)
301 {
302 // Ignore it, no need to reply
303 }
304 return null;
305 }, null);
306 }
307 else
308 {
309 ReQueueEvent(req);
310 }
311 } 304 }
312 } 305 }
313 catch (Exception e) 306 }
314 { 307 catch (Exception e)
315 m_log.ErrorFormat("Exception in poll service thread: " + e.ToString()); 308 {
316 } 309 m_log.ErrorFormat("Exception in poll service thread: " + e.ToString());
317 } 310 }
318 } 311 }
319 } 312 }
320
321 } 313 }
322} 314}
diff --git a/OpenSim/Framework/Servers/HttpServer/RestStreamHandler.cs b/OpenSim/Framework/Servers/HttpServer/RestStreamHandler.cs
index 0305dee..dfc2715 100644
--- a/OpenSim/Framework/Servers/HttpServer/RestStreamHandler.cs
+++ b/OpenSim/Framework/Servers/HttpServer/RestStreamHandler.cs
@@ -50,11 +50,10 @@ namespace OpenSim.Framework.Servers.HttpServer
50 50
51 protected override byte[] ProcessRequest(string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) 51 protected override byte[] ProcessRequest(string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
52 { 52 {
53 string requestBody;
53 Encoding encoding = Encoding.UTF8; 54 Encoding encoding = Encoding.UTF8;
54 StreamReader streamReader = new StreamReader(request, encoding); 55 using(StreamReader streamReader = new StreamReader(request,encoding))
55 56 requestBody = streamReader.ReadToEnd();
56 string requestBody = streamReader.ReadToEnd();
57 streamReader.Close();
58 57
59 string param = GetParam(path); 58 string param = GetParam(path);
60 string responseString = m_restMethod(requestBody, path, param, httpRequest, httpResponse); 59 string responseString = m_restMethod(requestBody, path, param, httpRequest, httpResponse);
diff --git a/OpenSim/Framework/Servers/MainServer.cs b/OpenSim/Framework/Servers/MainServer.cs
index ea7b2b5..523ccba 100644
--- a/OpenSim/Framework/Servers/MainServer.cs
+++ b/OpenSim/Framework/Servers/MainServer.cs
@@ -42,6 +42,7 @@ namespace OpenSim.Framework.Servers
42// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 42// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
43 43
44 private static BaseHttpServer instance = null; 44 private static BaseHttpServer instance = null;
45 private static BaseHttpServer unsecureinstance = null;
45 private static Dictionary<uint, BaseHttpServer> m_Servers = new Dictionary<uint, BaseHttpServer>(); 46 private static Dictionary<uint, BaseHttpServer> m_Servers = new Dictionary<uint, BaseHttpServer>();
46 47
47 /// <summary> 48 /// <summary>
@@ -93,6 +94,21 @@ namespace OpenSim.Framework.Servers
93 } 94 }
94 } 95 }
95 96
97
98 public static BaseHttpServer UnSecureInstance
99 {
100 get { return unsecureinstance; }
101
102 set
103 {
104 lock (m_Servers)
105 if (!m_Servers.ContainsValue(value))
106 throw new Exception("HTTP server must already have been registered to be set as the main instance");
107
108 unsecureinstance = value;
109 }
110 }
111
96 /// <summary> 112 /// <summary>
97 /// Get all the registered servers. 113 /// Get all the registered servers.
98 /// </summary> 114 /// </summary>
@@ -353,5 +369,17 @@ namespace OpenSim.Framework.Servers
353 return m_Servers[port]; 369 return m_Servers[port];
354 } 370 }
355 } 371 }
372
373 public static void Stop()
374 {
375 lock (m_Servers)
376 {
377 foreach (BaseHttpServer httpServer in m_Servers.Values)
378 {
379 httpServer.Stop();
380 }
381 }
382 }
383
356 } 384 }
357} \ No newline at end of file 385} \ No newline at end of file
diff --git a/OpenSim/Framework/Servers/ServerBase.cs b/OpenSim/Framework/Servers/ServerBase.cs
index f627ae6..3c2dce8 100644
--- a/OpenSim/Framework/Servers/ServerBase.cs
+++ b/OpenSim/Framework/Servers/ServerBase.cs
@@ -275,18 +275,6 @@ namespace OpenSim.Framework.Servers
275 (string module, string[] args) => Notice(GetThreadsReport())); 275 (string module, string[] args) => Notice(GetThreadsReport()));
276 276
277 m_console.Commands.AddCommand ( 277 m_console.Commands.AddCommand (
278 "Debug", false, "debug comms set",
279 "debug comms set serialosdreq true|false",
280 "Set comms parameters. For debug purposes.",
281 HandleDebugCommsSet);
282
283 m_console.Commands.AddCommand (
284 "Debug", false, "debug comms status",
285 "debug comms status",
286 "Show current debug comms parameters.",
287 HandleDebugCommsStatus);
288
289 m_console.Commands.AddCommand (
290 "Debug", false, "debug threadpool set", 278 "Debug", false, "debug threadpool set",
291 "debug threadpool set worker|iocp min|max <n>", 279 "debug threadpool set worker|iocp min|max <n>",
292 "Set threadpool parameters. For debug purposes.", 280 "Set threadpool parameters. For debug purposes.",
@@ -343,47 +331,13 @@ namespace OpenSim.Framework.Servers
343 331
344 public void RegisterCommonComponents(IConfigSource configSource) 332 public void RegisterCommonComponents(IConfigSource configSource)
345 { 333 {
346 IConfig networkConfig = configSource.Configs["Network"]; 334// IConfig networkConfig = configSource.Configs["Network"];
347
348 if (networkConfig != null)
349 {
350 WebUtil.SerializeOSDRequestsPerEndpoint = networkConfig.GetBoolean("SerializeOSDRequests", false);
351 }
352 335
353 m_serverStatsCollector = new ServerStatsCollector(); 336 m_serverStatsCollector = new ServerStatsCollector();
354 m_serverStatsCollector.Initialise(configSource); 337 m_serverStatsCollector.Initialise(configSource);
355 m_serverStatsCollector.Start(); 338 m_serverStatsCollector.Start();
356 } 339 }
357 340
358 private void HandleDebugCommsStatus(string module, string[] args)
359 {
360 Notice("serialosdreq is {0}", WebUtil.SerializeOSDRequestsPerEndpoint);
361 }
362
363 private void HandleDebugCommsSet(string module, string[] args)
364 {
365 if (args.Length != 5)
366 {
367 Notice("Usage: debug comms set serialosdreq true|false");
368 return;
369 }
370
371 if (args[3] != "serialosdreq")
372 {
373 Notice("Usage: debug comms set serialosdreq true|false");
374 return;
375 }
376
377 bool setSerializeOsdRequests;
378
379 if (!ConsoleUtil.TryParseConsoleBool(m_console, args[4], out setSerializeOsdRequests))
380 return;
381
382 WebUtil.SerializeOSDRequestsPerEndpoint = setSerializeOsdRequests;
383
384 Notice("serialosdreq is now {0}", setSerializeOsdRequests);
385 }
386
387 private void HandleShowThreadpoolCallsActive(string module, string[] args) 341 private void HandleShowThreadpoolCallsActive(string module, string[] args)
388 { 342 {
389 List<KeyValuePair<string, int>> calls = Util.GetFireAndForgetCallsInProgress().ToList(); 343 List<KeyValuePair<string, int>> calls = Util.GetFireAndForgetCallsInProgress().ToList();
@@ -928,16 +882,12 @@ namespace OpenSim.Framework.Servers
928 sb.Append("\n"); 882 sb.Append("\n");
929 } 883 }
930 884
931 sb.Append("\n"); 885 sb.Append(GetThreadPoolReport());
932 886
933 // For some reason mono 2.6.7 returns an empty threads set! Not going to confuse people by reporting 887 sb.Append("\n");
934 // zero active threads.
935 int totalThreads = Process.GetCurrentProcess().Threads.Count; 888 int totalThreads = Process.GetCurrentProcess().Threads.Count;
936 if (totalThreads > 0) 889 if (totalThreads > 0)
937 sb.AppendFormat("Total threads active: {0}\n\n", totalThreads); 890 sb.AppendFormat("Total process threads active: {0}\n\n", totalThreads);
938
939 sb.Append("Main threadpool (excluding script engine pools)\n");
940 sb.Append(GetThreadPoolReport());
941 891
942 return sb.ToString(); 892 return sb.ToString();
943 } 893 }
@@ -948,15 +898,46 @@ namespace OpenSim.Framework.Servers
948 /// <returns></returns> 898 /// <returns></returns>
949 public static string GetThreadPoolReport() 899 public static string GetThreadPoolReport()
950 { 900 {
901
902 StringBuilder sb = new StringBuilder();
903
904 // framework pool is alwasy active
905 int maxWorkers;
906 int minWorkers;
907 int curWorkers;
908 int maxComp;
909 int minComp;
910 int curComp;
911
912 try
913 {
914 ThreadPool.GetMaxThreads(out maxWorkers, out maxComp);
915 ThreadPool.GetMinThreads(out minWorkers, out minComp);
916 ThreadPool.GetAvailableThreads(out curWorkers, out curComp);
917 curWorkers = maxWorkers - curWorkers;
918 curComp = maxComp - curComp;
919
920 sb.Append("\nFramework main threadpool \n");
921 sb.AppendFormat("workers: {0} ({1} / {2})\n", curWorkers, maxWorkers, minWorkers);
922 sb.AppendFormat("Completion: {0} ({1} / {2})\n", curComp, maxComp, minComp);
923 }
924 catch { }
925
926 if (
927 Util.FireAndForgetMethod == FireAndForgetMethod.QueueUserWorkItem
928 || Util.FireAndForgetMethod == FireAndForgetMethod.UnsafeQueueUserWorkItem)
929 {
930 sb.AppendFormat("\nThread pool used: Framework main threadpool\n");
931 return sb.ToString();
932 }
933
951 string threadPoolUsed = null; 934 string threadPoolUsed = null;
952 int maxThreads = 0; 935 int maxThreads = 0;
953 int minThreads = 0; 936 int minThreads = 0;
954 int allocatedThreads = 0; 937 int allocatedThreads = 0;
955 int inUseThreads = 0; 938 int inUseThreads = 0;
956 int waitingCallbacks = 0; 939 int waitingCallbacks = 0;
957 int completionPortThreads = 0;
958 940
959 StringBuilder sb = new StringBuilder();
960 if (Util.FireAndForgetMethod == FireAndForgetMethod.SmartThreadPool) 941 if (Util.FireAndForgetMethod == FireAndForgetMethod.SmartThreadPool)
961 { 942 {
962 STPInfo stpi = Util.GetSmartThreadPoolInfo(); 943 STPInfo stpi = Util.GetSmartThreadPoolInfo();
@@ -972,22 +953,10 @@ namespace OpenSim.Framework.Servers
972 waitingCallbacks = stpi.WaitingCallbacks; 953 waitingCallbacks = stpi.WaitingCallbacks;
973 } 954 }
974 } 955 }
975 else if ( 956
976 Util.FireAndForgetMethod == FireAndForgetMethod.QueueUserWorkItem
977 || Util.FireAndForgetMethod == FireAndForgetMethod.UnsafeQueueUserWorkItem)
978 {
979 threadPoolUsed = "BuiltInThreadPool";
980 ThreadPool.GetMaxThreads(out maxThreads, out completionPortThreads);
981 ThreadPool.GetMinThreads(out minThreads, out completionPortThreads);
982 int availableThreads;
983 ThreadPool.GetAvailableThreads(out availableThreads, out completionPortThreads);
984 inUseThreads = maxThreads - availableThreads;
985 allocatedThreads = -1;
986 waitingCallbacks = -1;
987 }
988
989 if (threadPoolUsed != null) 957 if (threadPoolUsed != null)
990 { 958 {
959 sb.Append("\nThreadpool (excluding script engine pools)\n");
991 sb.AppendFormat("Thread pool used : {0}\n", threadPoolUsed); 960 sb.AppendFormat("Thread pool used : {0}\n", threadPoolUsed);
992 sb.AppendFormat("Max threads : {0}\n", maxThreads); 961 sb.AppendFormat("Max threads : {0}\n", maxThreads);
993 sb.AppendFormat("Min threads : {0}\n", minThreads); 962 sb.AppendFormat("Min threads : {0}\n", minThreads);
diff --git a/OpenSim/Framework/Servers/Tests/VersionInfoTests.cs b/OpenSim/Framework/Servers/Tests/VersionInfoTests.cs
index 480f2bb..68a1c78 100644
--- a/OpenSim/Framework/Servers/Tests/VersionInfoTests.cs
+++ b/OpenSim/Framework/Servers/Tests/VersionInfoTests.cs
@@ -41,14 +41,5 @@ namespace OpenSim.Framework.Servers.Tests
41 { 41 {
42 Assert.AreEqual(VersionInfo.VERSIONINFO_VERSION_LENGTH, VersionInfo.Version.Length," VersionInfo.Version string not " + VersionInfo.VERSIONINFO_VERSION_LENGTH + " chars."); 42 Assert.AreEqual(VersionInfo.VERSIONINFO_VERSION_LENGTH, VersionInfo.Version.Length," VersionInfo.Version string not " + VersionInfo.VERSIONINFO_VERSION_LENGTH + " chars.");
43 } 43 }
44
45 [Test]
46 public void TestGetVersionStringLength()
47 {
48 foreach (VersionInfo.Flavour flavour in Enum.GetValues(typeof(VersionInfo.Flavour)))
49 {
50 Assert.AreEqual(VersionInfo.VERSIONINFO_VERSION_LENGTH, VersionInfo.GetVersionString("0.0.0", flavour).Length, "0.0.0/" + flavour + " failed");
51 }
52 }
53 } 44 }
54} 45}